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.

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.


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>.


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

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"

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))

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

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

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)"

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

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

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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.