Wie generiere ich ein Jahresquartalsdatum über die Befehlszeile?

10

Ich bin daran interessiert, eine Darstellung des aktuellen Jahresquartals sowie des Jahresquartals des Vormonats auszugeben.

Wenn heute der 1. Januar 2012 ist, würde ich gerne bekommen

2012q1

und

2011q4

als die jeweiligen Ausgänge.

Smokris
quelle

Antworten:

10

Eine (etwas hässliche) Lösung, bei der die arithmetische Auswertung von BASH und der dateBefehl GNU verwendet werden :

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

Beachten Sie, dass die %-mverhindert , dass datevon 0-Polster, so dass diese nach wie vor für August und September wird funktionieren.

Smokris
quelle
2
Nehmen Sie $ (...) anstelle der veralteten Backticks. Sie können leicht verschachtelt werden.
Benutzer unbekannt
1
Sei einfach neugierig: Warum andere Antworten 4 als Teiler verwenden.
LiuYan
2
@LiuYan 刘 研: Nicht sicher. Es gibt 3 Monate in einem Viertel, also denke ich, dass 3 der richtige Teiler ist. (Obwohl mich das zuerst auch verwirrte.)
Smokris
Im September %mgibt es an, 09welche Bash aufgrund der führenden 0 versucht, als oktal zu interpretieren, was einen Fehler auslöst, der besagt 09: value too great for base (error token is "09"). Dies kann behoben werden, indem das 0-Auffüllen durch Ändern %mauf deaktiviert wird %-m.
Matthew
5

Benutze meine Dateutils :

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

Die Flags %qund %Qsind spezifisch für dateutils und geben das Quartal als Zahl oder in Form zurück Q<NUMBER>.

hroptatyr
quelle
dconv now -f%Y%Q | tr Q qwenn Sie wirklich brauchen, dass das Q niedriger ist. (PS: Wir verpacken dies in Fedora mit dateals Präfix anstelle von d, also " dateconv".)
Mattdm
5

Alle Lösungen, die durch vier geteilt werden, schlagen fehl, zum Beispiel im November:

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

Die richtige Mathematik wäre:

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

Und als solches wäre das Quartal des laufenden und des Vormonats:

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

Es sind nur zwölf Werte zu überprüfen, wirklich ...

% 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
bif
quelle
1
+1 Für "Alle Lösungen, die sich durch Fehlschlagen teilen". Du hast recht! Ein Viertel dauert 3 Monate, daher sollten die Antworten durch 3 geteilt werden.
Stephen Quan
4

Wahrscheinlich gibt es keine direkte Lösung.

Sie könnten awkso viele Back-Ticks vermeiden.

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);}'

Eine perlLösung wäre aber sauberer perlund DateTimeeine große Voraussetzung.

#!/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"
andcoz
quelle
Cool. Ich mag die erste Date / Awk-Zeile, da sie das datezweimalige Aufrufen (und Übergeben von Parametern) vermeidet .
Smokris
4

Teilen Sie das Format mit Datum, berechnen Sie mit awk, formatieren Sie mit printf:

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

Nur Date und Bash:

echo $(date +%Yq)$(($(date +%m)/4+1))
Benutzer unbekannt
quelle
Die erste Zeile wird ausgegeben, 2012q0was falsch ist.
Smokris
@smokris: Du hast recht - ich habe die falsche Zeile meiner Tests gewählt.
Benutzer unbekannt
4

Eine Alternative, eher als Kuriosität. Wenn GNU awkbeteiligt ist, datewird nicht benötigt:

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

Rufen Sie datean, um das aktuelle Jahr und den aktuellen Monat abzurufen, und erledigen Sie den Rest mit der Arithmetik in der 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
Gilles 'SO - hör auf böse zu sein'
quelle
2

Jahresquartal für diesen Monat

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

Jahresquartal für den vergangenen Monat

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

Grundlegende Mathematik für dieses Quartal und das Quartal des letzten Monats:

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

Das Skript verwendet die folgenden Teile:

  1. $ (unix-cmd) - wertet einen Befehl im Shell-Skript aus
  2. $ ((Ausdruck)) - wertet einen mathematischen Ausdruck aus
  3. Beim erneuten Zuordnen von 1..12 -> 1..4 wird die folgende Mathematik (m-1) / 3 + 1 verwendet
  4. Für die Auswertung des Vormonats wird Modulo-Mathematik verwendet
Stephen Quan
quelle
2

Es gibt jetzt das %qFormat, um diese Informationen anzuzeigen.

Aus dem Release-Protokoll von coreutils-8.26 vom 30. November 2016:

Neue Funktionen
...
Datum akzeptiert jetzt das% q-Format, um das Quartal des Jahres auszugeben.

Und ja es funktioniert!

$ date "+%q"
4
$ date "+%Yq%q"
2016q4
fedorqui
quelle
0

Wenn Sie das 13-Wochen- Geschäftsquartal möchten , das auf dem ISO-Wochenkalender basiert, funktioniert das neue praktische% q leider nicht. Hier ist eine Version der dateless-Lösung von @ manatwork mit awk / strftime.

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

Das letzte kleine ternäre Bit behandelt die ISO-Schaltwochenjahre, in denen das letzte Quartal 14 Wochen umfasst.

TKH
quelle