¿Cómo generar una fecha trimestral desde la línea de comando?

10

Estoy interesado en generar una representación del trimestre actual, así como el trimestre del mes anterior.

Si hoy es el 1 de enero de 2012, me gustaría obtener

2012q1

y

2011q4

como las respectivas salidas.

smokris
fuente

Respuestas:

10

Una solución (un poco fea), usando la evaluación aritmética de BASH y el datecomando 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 ))

Tenga en cuenta que esto %-mevita el daterelleno 0, por lo que esto seguirá funcionando para agosto y septiembre.

smokris
fuente
2
Tome $ (...) en lugar de los backticks obsoletos. Se pueden anidar fácilmente.
usuario desconocido
1
solo sea curioso: por qué otras respuestas usan 4 como divisor.
LiuYan 刘 研
2
@LiuYan 刘 研: No estoy seguro. Hay 3 meses en un trimestre, así que creo que 3 es el divisor correcto. (Aunque eso también me confundió al principio.)
smokris
En septiembre %mda 09qué bash intenta interpretar como octal debido al 0 inicial, por lo que arroja un error que dice 09: value too great for base (error token is "09"). Esto se puede solucionar deshabilitando el relleno 0 cambiando %ma %-m.
Mateo
5

Usa mis dateutils :

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

Las banderas %qy %Qson específicas de dateutils y devuelven el trimestre como número o en el formulario Q<NUMBER>.

hroptatyr
fuente
dconv now -f%Y%Q | tr Q qsi realmente necesitas que Q esté en minúsculas. (PD: estamos empacando esto en Fedora con dateel prefijo en lugar de d" dateconv".)
mattdm
5

Todas las soluciones que se dividen entre cuatro fallan, por ejemplo noviembre:

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

Las matemáticas correctas serían:

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

Y como tal, el trimestre del mes actual y anterior sería:

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

Son solo doce valores para verificar, realmente ...

% 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
fuente
1
+1 Para "Todas las soluciones que se dividen por fallas". ¡Tienes razón! Un cuarto dura 3 meses, por lo que las respuestas deberían dividirse por 3.
Stephen Quan
4

Probablemente, no hay una solución directa.

Podrías awkevitar tantas contratiempos.

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

Una perlsolución sería más limpio pero perly DateTimeson un requisito previo pesado.

#!/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
fuente
Frio. Me gusta la primera línea date / awk, ya que evita llamar (y pasar parámetros a) datedos veces.
smokris
4

Divida el formato con fecha, calcule con awk, formatee con printf:

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

Solo fecha y fiesta:

echo $(date +%Yq)$(($(date +%m)/4+1))
usuario desconocido
fuente
La primera línea sale 2012q0que es incorrecta.
smokris
@smokris: Tienes razón: elegí la línea incorrecta de mis pruebas.
usuario desconocido
4

Una alternativa, más como curiosidad. Si GNU awkestá involucrado, dateno es necesario:

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

Llame datepara recuperar el año y mes actuales, y haga el resto con la aritmética en el 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- deja de ser malvado'
fuente
2

Trimestre del año para este mes

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

Año-Trimestre para ayer-mes

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

Matemáticas básicas para este trimestre y el trimestre del mes pasado:

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

El script usa las siguientes partes:

  1. $ (unix-cmd): evalúa un comando en el script de shell
  2. $ ((expr)) - evalúa una expresión matemática
  3. reasignación 1..12 -> 1..4 utiliza las siguientes matemáticas (m-1) / 3 + 1
  4. evaluando el mes anterior usa modulo matemático
Stephen Quan
fuente
2

Ahora existe el %qformato para mostrar esta información.

Del registro de lanzamiento de coreutils-8.26 del 30 de noviembre de 2016:

Nuevas características
... la
fecha ahora acepta el formato% q para generar el trimestre del año.

¡Y sí, funciona!

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

Si desea el trimestre fiscal de 13 semanas que se basa en el calendario semanal ISO, entonces el nuevo práctico% q no va a funcionar, lamentablemente. Aquí hay una versión de la solución sin fecha de @manatwork con awk / strftime.

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

El último pequeño bit ternario maneja los años de la semana de salto ISO donde el último trimestre tiene 14 semanas.

TKH
fuente