Как сгенерировать год-квартал из командной строки?


10

Я заинтересован в выводе представления текущего квартала года, а также квартала за предыдущий месяц.

Если сегодня 1 января 2012 года, я хотел бы получить

2012q1

а также

2011q4

в качестве соответствующих выходов.

Ответы:


10

Одно (довольно уродливое) решение, использующее арифметическую оценку BASH и команду GNU date:

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

Обратите внимание, что %-mпредотвращает dateнулевое заполнение, так что это будет работать в августе и сентябре.


2
Возьмите $ (...) вместо устаревших символов обратной галочки. Они могут быть легко вложены.
пользователь неизвестен

1
просто будьте любопытны: почему другие ответы используют 4 в качестве делителя.
LiuYan 研 研

2
@LiuYan 刘 研: Не уверен. В четверти 3 месяца, поэтому я считаю, что 3 - правильный делитель. (Хотя это поначалу и меня смущало.)
smokris

В сентябре %mдает, 09какой bash пытается интерпретировать как восьмеричный из-за ведущего 0, так что это выдает ошибку, которая говорит 09: value too great for base (error token is "09"). Это можно исправить, отключив 0-padding, изменив %mна %-m.
Мэтью

5

Используйте мои dateutils :

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

%qИ %Qфлаги являются специфическими для dateutils, и вернуть четверть как число или в форме Q<NUMBER>.


dconv now -f%Y%Q | tr Q qесли вам действительно нужно, чтобы Q было в нижнем регистре. (PS: мы упаковываем это в Fedora с dateпрефиксом вместо d, так что " dateconv".)
mattdm

5

Все решения, которые делятся на четыре, терпят неудачу, например, ноябрь:

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

Правильная математика будет:

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

И как таковой, квартал текущего и предыдущего месяца будет:

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

Это всего лишь двенадцать значений для проверки, правда ...

% 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 За «Все решения, которые делятся на неудачу». Вы правы! Четверть длиться 3 месяца, поэтому ответы должны быть разделены на 3.
Стивен Куан

4

Вероятно, прямого решения не существует.

Вы можете использовать, awkчтобы избежать так много обратных тиков.

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

perlРешение было бы чище , но perlи DateTimeявляется тяжелым условием.

#!/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"

Круто. Мне нравится первая строка date / awk, так как она избегает вызова (и передачи параметров) dateдважды.
Smokris

4

Разделите формат с датой, рассчитайте с помощью awk, отформатируйте с помощью printf:

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

Просто дата и bash:

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

Первая строка выводит, 2012q0что неверно.
Smokris

@smokris: Ты прав - я выбрал неправильную линию своих тестов.
пользователь неизвестен

4

Альтернатива, скорее как любопытство. Если awkзадействован GNU , dateон не нужен:

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

3

Позвоните, dateчтобы получить текущий год и месяц, а остальное сделайте с помощью арифметики в оболочке.

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

Год-квартал за этот месяц

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

Четверть года за месяц

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

2

Основная математика за этот квартал и квартал прошлого месяца:

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

Скрипт использует следующие части:

  1. $ (unix-cmd) - оценивает команду в сценарии оболочки
  2. $ ((expr)) - вычисляет математическое выражение
  3. переназначение 1..12 -> 1..4 использует следующую математику (m-1) / 3 + 1
  4. оценка предыдущего месяца использует модуль по математике

2

Теперь есть %qформат для отображения этой информации.

Из журнала выпуска coreutils-8.26 от 30 ноября 2016 года:

Новые функции
...
дата теперь принимает формат% q для вывода квартала года.

И да, это работает!

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

0

Если вам нужен финансовый 13-недельный квартал, основанный на недельном календаре ISO, то, к сожалению, новый удобный% q не сработает. Вот версия устаревшего решения @ manatwork с awk / strftime.

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

Последний маленький троичный бит обрабатывает годы високосной ISO, где в последнем квартале 14 недель.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.