Bagaimana cara menghasilkan tanggal kuartal tahun dari baris perintah?


10

Saya tertarik untuk menghasilkan representasi dari kuartal tahun berjalan, serta kuartal tahun untuk bulan sebelumnya.

Jika hari ini adalah 1 Januari 2012, saya ingin mendapatkannya

2012q1

dan

2011q4

sebagai output masing-masing.

Jawaban:


10

Satu (agak jelek) solusi, menggunakan evaluasi aritmatika BASH dan dateperintah GNU :

echo $(date +%Y)q$(( ($(date +%-m)-1)/3+1 ))
echo $(date -d "-1 month" +%Y)q$(( ($(date -d "-1 month" +%-m)-1)/3+1 ))

Perhatikan bahwa %-mpencegah datedari 0-padding, jadi ini masih akan berfungsi untuk Agustus dan September.


2
Ambil $ (...) alih-alih backticks yang sudah usang. Mereka dapat dengan mudah disarangkan.
pengguna tidak dikenal

1
hanya ingin tahu: mengapa jawaban lain menggunakan 4 sebagai pembagi.
LiuYan 刘 研

2
@LiuYan 刘 研: Tidak yakin. Ada 3 bulan dalam seperempat, jadi saya pikir 3 adalah pembagi yang benar. (Meskipun itu membingungkan saya pada awalnya juga.)
smokris

Pada bulan September %mmemberikan 09bash yang mencoba untuk menafsirkan sebagai oktal karena 0 yang memimpin, jadi ini melempar kesalahan yang mengatakan 09: value too great for base (error token is "09"). Ini dapat diperbaiki dengan menonaktifkan 0-padding dengan mengubah %mke %-m.
Matius

5

Gunakan dateutils saya :

dconv 2012-01-01 -f '%Y%Q'
=>
  2012Q1

The %qdan %Qbendera khusus untuk dateutils, dan kembali kuartal sebagai nomor atau dalam bentuk Q<NUMBER>.


dconv now -f%Y%Q | tr Q qjika Anda benar-benar membutuhkan Q agar lebih rendah. (PS: kami mengemas ini di Fedora dengan datesebagai awalan alih-alih d, jadi " dateconv".)
mattdm

5

Semua solusi yang dibagi empat gagal, misalnya November:

% echo $(( 11/4+1 ))
3

Matematika yang benar adalah:

$(( (m-1)/3 +1 ))

Dan dengan demikian, kuartal bulan berjalan dan sebelumnya adalah:

echo curr ${y}q$(((m-1)/3+1))
if [ $m = 1 ]; then
  echo prev $((y-1))q4
else
  echo prev ${y}q$(((m-2)/3+1))
fi

Hanya perlu dua belas nilai untuk diperiksa, sungguh ...

% for m in {1..12}; do echo $m Q$(((m-1)/3+1)); done
1 Q1
2 Q1
3 Q1
4 Q2
5 Q2
6 Q2
7 Q3
8 Q3
9 Q3
10 Q4
11 Q4
12 Q4

1
+1 Untuk "Semua solusi yang dibagi karena gagal". Kamu benar! Seperempat berlangsung selama 3 bulan sehingga jawabannya harus dibagi dengan 3.
Stephen Quan

4

Mungkin, tidak ada solusi langsung.

Anda dapat menggunakan awkuntuk menghindari begitu banyak kutu kembali.

date +"%Y %m" | awk '{q=int($2/4)+1; printf("%sq%s\n", $1, q);}'
date +"%Y %m" | awk '{q=int($2/4);y=$1;if (q==0){q=4;y=y-1;}; printf("%sq%s\n", y, q);}'

Sebuah perlsolusi akan menjadi lebih bersih tapi perldan DateTimemerupakan prasyarat berat.

#!/usr/bin/perl

use DateTime;

my $today = DateTime->now;
print "today: " . $today->year . "q" . $today->quarter . "\n";

my $ago = DateTime->now->subtract( months=> 4);
print "some time ago: " . $ago->year . "q" . $ago->quarter . "\n"

Keren. Saya suka baris tanggal / awk pertama, karena itu menghindari panggilan (dan melewati parameter ke) datedua kali.
smokris

4

Membagi format dengan tanggal, menghitung dengan awk, format dengan printf:

date +"%Y %m" | awk '{printf ("%4dq%1d\n", $1, ($2/4)+1)}'

Hanya kencan dan pesta:

echo $(date +%Yq)$(($(date +%m)/4+1))

Baris pertama menampilkan 2012q0yang salah.
smokris

@smokris: Anda benar - saya salah memilih tes saya.
pengguna tidak diketahui

4

Alternatif, lebih sebagai rasa ingin tahu. Jika GNU awkterlibat, datetidak diperlukan:

awk 'BEGIN{print strftime("%Y")"q"int((strftime("%-m")-1)/3)+1}'

3

Panggil dateuntuk mengambil tahun dan bulan saat ini, dan lakukan sisanya dengan aritmatika di shell.

set $(date '+%Y %m');
this_quarter=${1}q$(($2 / 4 + 1))
if [ $2 -eq 1 ]; then
  last_month_quarter=$(($1 - 1))q4
else
  last_month_quarter=${1}q$((($2 - 1) / 4 + 1))
fi

2

Tahun-Kuartal untuk bulan ini

date +"%Yq$(expr $(expr $(date +%m) - 1) / 3 + 1)"

Tahun-Kuartal untuk bulan yang lalu

date +"%Yq$(expr $(expr $(date -d '-1 month' +%m) - 1) / 3 + 1)"

2

Matematika dasar untuk kuartal ini dan kuartal bulan lalu:

y1=$(date +%Y)
m1=$(date +%m)
q1=$(( (m1 - 1) / 3 + 1))
y2=$(( y1 - (m1 == 1) ))
m2=$(( (m1 + 10) % 12 + 1 ))
q2=$(( (m2 - 1) / 3 + 1 ))
echo This Quarter: $((y1))q$q1
echo Last Month Quarter: $((y2))q$q2

Script menggunakan bagian-bagian berikut:

  1. $ (unix-cmd) - mengevaluasi perintah dalam skrip shell
  2. $ ((expr)) - mengevaluasi ekspresi matematika
  3. memetakan ulang 1..12 -> 1..4 menggunakan matematika berikut (m-1) / 3 + 1
  4. mengevaluasi bulan sebelumnya menggunakan modulo matematika

2

Sekarang ada %qformat untuk menampilkan informasi ini.

Dari log rilis coreutils-8.26 mulai 30 November 2016:

Fitur Baru
...
tanggal sekarang menerima format% q untuk menghasilkan kuartal tahun ini.

Dan ya itu berhasil!

$ date "+%q"
4
$ date "+%Yq%q"
2016q4

0

Jika Anda ingin kuartal fiskal 13 minggu yang didasarkan pada kalender minggu ISO, maka% q baru yang berguna tidak akan berfungsi, sayangnya. Inilah versi solusi tanpa data @ manatwork dengan awk / strftime.

awk 'BEGIN{$x=int((strftime("%V")-1)/13)+1;print strftime("%G")"q"($x>4?4:$x)}'

Bit terner kecil terakhir menangani tahun kabisat ISO tahun di mana kuartal terakhir memiliki 14 minggu.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.