Menampilkan angka minggu dalam format tertentu menggunakan ncal atau cal

15

Tidakkah Anda hanya menyukainya ketika dua perintah masing-masing melakukan satu hal yang Anda inginkan tetapi juga tidak keduanya?

Inilah yang caldilakukan. Pemformatan yang bagus. Tidak memiliki angka minggu:

$ cal
    January 2012      
Su Mo Tu We Th Fr Sa  
 1  2  3  4  5  6  7  
 8  9 10 11 12 13 14  
15 16 17 18 19 20 21  
22 23 24 25 26 27 28  
29 30 31              

Inilah yang ncaldilakukan. Pemformatan yang aneh, tetapi dengan angka minggu:

$ ncal -w
    January 2012      
Su  1  8 15 22 29   
Mo  2  9 16 23 30   
Tu  3 10 17 24 31   
We  4 11 18 25      
Th  5 12 19 26      
Fr  6 13 20 27      
Sa  7 14 21 28      
    1  2  3  4  5   

Jenis output yang saya inginkan, sebenarnya persilangan antara caldan ncal -w:

$ cal --magik-calendar-week-option
      January 2012      
   Su Mo Tu We Th Fr Sa  
1   1  2  3  4  5  6  7  
2   8  9 10 11 12 13 14  
3  15 16 17 18 19 20 21  
4  22 23 24 25 26 27 28  
5  29 30 31
k0pernikus
sumber

Jawaban:

13

Jika tidak satu pun dari perintah ini yang sesuai dengan kebutuhan Anda, Anda dapat menggunakan gcaluntuk melakukan apa yang Anda inginkan.

Contoh

$ gcal -K

      April 2014
 Su Mo Tu We Th Fr Sa CW
        1  2  3  4  5 13
  6  7  8  9 10 11 12 14
 13 14 15 16 17 18 19 15
 20 21 22 23 24 25 26 16
 27 28 29 30          17

Mencetak nomor minggu di kolom terakhir di sebelah kanan.

Referensi

slm
sumber
gcal --starting-day=Monday --with-week-numberlebih sesuai dengan kebutuhan saya namun alat ini sangat bagus.
k0pernikus
9

Ini menyoroti tanggal hari ini, dan dapat menampilkan bulan apa pun melalui $1formulir: YYYY-mm-dd... Ini default ke tanggal hari ini

Ini diatur untuk menunjukkan angka minggu ISO, dan hari kerja pertama adalah hari Senin.

#!/bin/bash
# Input reference date is expected in  'YYYY-mm-dd' format
#
today=($(date '+%Y %m %d')); Y=0; m=1; d=2                # establish today's date
[[ -z $1 ]] && ref=(${today[@]}) || ref=(${1//-/ })       # get input date
dNbA=$(date --date="$(date +%Y-%m-01)" +'%u')             # day-number of 1st day of reference month
today[m]=$((10#${today[m]})); ref[m]=$((10#${ref[m]}))    # remove leading zero (octal clash)
today[d]=$((10#${today[d]})); ref[d]=$((10#${ref[d]}))    # remove leading zero (octal clash)
nxtm=$(( ref[m]==12 ?1       :ref[m]+1 ))                 # month-number of next month
nxtY=$(( ref[m]==12 ?ref[Y]+1:ref[Y]   ))                 # year-number of next month
nxtA="$nxtY-$nxtm-1"                                      # date of 1st day of next month
refZ=$(date --date "$(date +$nxtA) yesterday" +%Y-%m-%d)  # date of last day of reference  month
days=$(date --date="$refZ" '+%d')                         # days in reference month

h1="$(date --date="${ref[Y]}-${ref[m]}-${ref[d]}" '+%B %Y')" # header 1 
h2="Mo Tu We Th Fr Sa Su"                                    # header 2 
printf "    %$(((${#h2}-${#h1}-1)/2))s%s\n" " " "$h1"
printf "    %s\n" "$h2"
# print week rows   
printf "%2d  " "$((10#$(date -d "$(date +${ref[Y]}-${ref[m]}-01)" +'%V')))" # week-number (of year) with suppressed leading 0
printf "%$(((dNbA-1)*3))s"  # lead spaces (before start of month)
dNbW=$dNbA  # day-number of week
dNbM=1      # day-number of month
while ((dNbM <= days)) ;do
    if (( today[Y]==ref[Y] &&  
          today[m]==ref[m] && 
          today[d]==dNbM )) ;then
        printf "\x1b[7m%2d\x1b[0m " "$dNbM" # highlight today's date 
    else
        printf "%2d " "$dNbM"
    fi
    ((dNbM++))
    if ((dNbW  >=7)) ;then
        cdate=$((10#$(date -d "$(date +${ref[Y]}-${ref[m]}-$dNbM)" +'%V'))) # remove leading zero (octal clash)
        printf "\n%2d  " "$cdate" # week-number of year
        dNbW=0
    fi
    ((dNbW++))
done
printf "%$(((8-dNbW)*3))s\n" # trailing spaces (after end of month)

Ini tampilan bulan ini (dengan yang 20disorot)

       January 2012
    Mo Tu We Th Fr Sa Su
52                     1 
 1   2  3  4  5  6  7  8 
 2   9 10 11 12 13 14 15 
 3  16 17 18 19 20 21 22 
 4  23 24 25 26 27 28 29 
 5  30 31                
Peter.O
sumber
Saya bahkan tidak memperhatikan iso-isu. Itu akan dilakukan :)
k0pernikus
1
@ k0pernikus: Saya baru saja memodifikasi skripnya .. (sekitar 35 menit setelah Anda memposting komentar di atas) .. Itu semakin terperangkap 08dan 09ditafsirkan sebagai oktal bukan desimal .. Seharusnya tidak apa-apa sekarang ...
Peter.O
7

Anda dapat menggunakan nlnomor baris (itulah tujuan program :). Tetapi Anda perlu mengekstrak minggu pertama di bulan tersebut dari suatu tempat. Itu bisa dilakukan dengan ncalsendirinya:

$ ncal -w 2 2012 | tail -1 | awk '{print $1}'
5

Kami menyisipkan ini sebagai parameter untuk nlopsi -v(mulai nomor baris), dan kirim ke hanya nomor baris dengan angka atau spasi.

$ cal 2 2012 | nl -bp'^[0-9 ]\+$' -w2 -s'  ' -v$(ncal -w 2 2012 | tail -1 | awk '{print $1}')
       February 2012
    Su Mo Tu We Th Fr Sa
 5            1  2  3  4
 6   5  6  7  8  9 10 11
 7  12 13 14 15 16 17 18
 8  19 20 21 22 23 24 25
 9  26 27 28 29

Ini semua sangat rapuh. Lagi pula, jika Anda tidak akan membutuhkan calopsi yang lebih canggih, itu akan berhasil. Anda bisa memasukkannya ke dalam file dan mengganti "$@"tempat saya meletakkan 2 2012.


EDIT: Tapi ini SALAH! Saya baru memperhatikan bahwa minggu pertama bulan Januari dapat memiliki nomor 52 atau 53! Jadi kita harus membuat pengecualian untuk Januari, atau cukup mengekstrak semua angka minggu dari ncaldan menerapkannya pada output cal.

Ini adalah solusi yang saya pikir awalnya, tetapi saya pikir (keliru) saya akan menyederhanakannya menggunakan nl. Ini menggunakan paste, yang menggabungkan file berdampingan. Karena tidak ada file, kita harus menggunakan bashism <(...); itulah yang saya coba hindari.

"File" pertama kami akan menjadi daftar angka minggu, dengan dua baris kosong di awal:

$ printf '   \n   \n' && printf '%2d \n' $(ncal -w 1 2011 | tail -1)


52
 1
 2
 3
 4
 5

Yang kedua, hanya output dari cal. Secara keseluruhan, sebagai parameter untuk paste:

$ paste -d' ' <(printf '   \n   \n' && printf '%2d \n' $(ncal -w 1 2011 | tail -1)) <(cal 1 2011)
        January 2011
    Su Mo Tu We Th Fr Sa
52                     1
 1   2  3  4  5  6  7  8
 2   9 10 11 12 13 14 15
 3  16 17 18 19 20 21 22
 4  23 24 25 26 27 28 29
 5  30 31

Jauh lebih berantakan dan tidak kompatibel dengan yang lain. En fin ...

angus
sumber
Tidak begitu bagus :-/. Lihat hasil edit saya.
angus
7

Hasilkan urutan minggu dengan ncaldan gunakan pasteuntuk memiliki kedua output berdampingan.

$ paste <(echo; echo; ncal -w | tail -1 | xargs -n1 printf '%2d\n') <(cal)

Jika Anda tidak suka memiliki tab sebagai pembatas, tambahkan saja sesuatu seperti sed 's/\t/ /'


Edit : lebih sederhana, tidak perlu peduli tentang tab:

$ paste -d' ' <((echo -n '   '; ncal -w | tail -1 )| fold -w 3) <(cal)
funollet
sumber
Elegan dan mewujudkan banyak dari 17 Aturan Unix ESR . Harus menjadi jawaban yang diterima karena benar-benar menggabungkan output dari caldan ncal(pendekatan lain meniru perilaku salah satu calatau ncal).
Uskup
4

Salah satu cara menggunakan Perl (bahasa output saya dari calperintah adalah Spanyol, tapi saya harap hasilnya tidak berbeda dari bahasa Inggris):

$ cal | perl -pe 'if ( m/\A\s*\d/ ) { s/\A/++$i . qq[ ] x 2/e } else { s/\A/qq[ ] x 3/e }'

Keluaran:

       enero de 2012   
   lu ma mi ju vi sá do
1                     1
2   2  3  4  5  6  7  8
3   9 10 11 12 13 14 15
4  16 17 18 19 20 21 22
5  23 24 25 26 27 28 29
6  30 31

Penjelasan:

-pe                     # For every input line from previous pipe, execute  next
                        # instructions and print to output.
if ( m/\A\s*\d/ )       # If line begins with a digit omitting spaces...
s/\A/++$i . qq[ ] x 2/e # Insert at the beginning of the line a counter plus two spaces.
else                    # else...
s/\A/qq[ ] x 3/e        # Insert three spaces at the beginning of the line.
Birei
sumber
bagaimana ini akan bekerja untuk bulan-bulan berikutnya. Minggu Februari tidak dimulai dari 1 lagi, mereka mulai dari 5/6 sama Maret akan dari 9/10.
Nikhil Mulley
kal 02 2012, akankah ini gagal ??
Nikhil Mulley
@ Nikhil: Saya tidak mengerti maksud Anda. Bisakah Anda mencoba menjelaskannya lebih mendalam? Apakah skrip gagal cal 02 2012? Tampaknya berhasil dalam pengujian saya.
Birei
@ Nikhil: Ah, baiklah. Saya salah mengerti pertanyaan itu. Itu berarti angka absolut minggu dan bukan relatif terhadap setiap bulan. Saya akan menghapus jawaban saya yang salah sebentar.
Birei
1
cool..do tidak menghapus jawaban, tolong simpan untuk referensi.
Nikhil Mulley
1

Tanpa perwakilan yang cukup untuk mengomentari jawaban oleh slm, gcal dapat diinstal pada Mac OS menggunakan brew install gcal.

(Saya menemukan jawabannya di sini terlebih dahulu, kemudian jawaban ini pada bertanya berbeda, tetapi jawaban unix tidak memiliki semua informasi yang saya butuhkan untuk menginstal pada mac.)

pengguna3.1415927
sumber
0

Berikut ini solusi saya yang lebih pendek dalam kode dan berfungsi dengan baik untuk tanggal lain dari bulan saat ini. Maaf untuk orang-orang AS, ini menggunakan format ISO, yaitu hari pertama minggu adalah Senin. Ini dilakukan dengan opsi -m untuk kal dan opsi% V untuk tanggal

#!/bin/bash
if [ "$1" = "" ]
then
  when="now"
else
  when="$1"
fi
y=$(date --date "$when" +%Y )
if [ $? -ne 0 ]
then
  exit
fi
m=$(date --date "$when" +%m )
w=$(date --date $(printf %4d%02d01 $y $m) +%V)
cal -m $m $y |
  awk -v w=$w '
    NR>2{ww=w++}
    $0!=""{printf "%2s %s\n", ww , $0}
  '
Pistol
sumber
0

Saya melakukan script ini untuk menghasilkan kalender yang sedang bertugas untuk tim. Ini menghasilkan kalender dengan angka minggu dan memberikan nama kepada mereka (hanya round-robin). Setelah output dicetak, Anda hanya perlu menyalinnya ke excel dan melakukan "teks ke kolom" dengan; dan sekali lagi melakukan "teks ke kolom" pada kolom pertama dengan menggunakan opsi "tetap". Manfaat dari kalender ini (dibandingkan dengan orientasi horisontal) adalah Anda dapat menggunakan filter otomatis (Alt + dff) dan hanya menemukan minggu-minggu Anda.

#! / usr / bin / ksh
y = 2017
set -A team1 Petars Justas Richard Jukka Jesper
set -A team2 Modestas Timo Mats Andreas

i1 = 0
i2 = 0
wn = 1
sendiri = 1

echo "WN Bulan Mo Tu We Th Fr Sa Su; Team1; Team2"
ycal = `untuk m dalam 1 2 3 4 5 6 7 8 9 10 11 12
melakukan
IFS =
        cal -m $ m $ y | egrep -v "Mo | ^ $" | saat membaca baris
        melakukan
                echo $ line | grep -q $ y && mname = $ line || cetak $ mname $ line | sed 's /' $ y '//'
        selesai
selesai`
IFS =
gema "$ ycal" | saat membaca baris2
melakukan
IFS =
        gema "$ line2" | grep -v "1 2 3 4 5 6 7" | egrep -q "* 1 | * 1 $" || biarkan wn ++
        [$ milik -n $ wn] && {\
                [$ i1 -eq $ {# team1 [@]} - 1] && i1 = 0 || biarkan i1 ++; \
                [$ i2 -eq $ {# team2 [@]} - 1] && i2 = 0 || biarkan i2 ++; }
        printf '% 2s% s;% s;% s \ n' $ wn $ line2 $ {team1 [$ i1]} $ {team2 [$ i2]}
        sendiri = $ wn
selesai

Maaf, kode agak jahat ... dan tidak ada komentar ... tetapi berfungsi dengan baik;)

Petras L
sumber
0

Saya tidak benar-benar ingin menginstal gcal, dan saya tidak bisa membuatnya berfungsi dengan baik pada sistem saya. Jadi tanpa gcal, jawaban funollet memang solusi terbaik. Saya baru saja mengubahnya sedikit sehingga juga mempertahankan format seperti highlight hari , warna dll menggunakan perintah. Saya juga menghapus karakter yang berlebihan, sehingga cocok sebagai alias, seperti:script

alias today="paste -d' ' <((echo ' '{,};ncal -w|tail -1)|fold -w3) <(script /dev/null -qc cal)"

Atau ganti caldengan fungsi baru. Namun, dengan ini Anda tidak dapat melakukan hal-hal seperti cal -3. Anda mendapatkan minggu yang benar tetapi mereka tidak selaras dengan benar. Solusi sederhana namun tidak lengkap adalah memeriksa apakah caldipanggil tanpa argumen, seperti:

function cal {
    if [[ $# -eq 0 ]]; then
        paste -d' ' <((echo ' '{,};ncal -w $@|tail -1)|fold -w3) <(script /dev/null -qc "cal $@")
    else
        /usr/bin/cal "$@"
    fi
}
lima
sumber