Posso dar ao GNU date uma data e uma string de formato para essa data e dizer para ele também subtrair algum tempo dela? Parece que posso fazer 2 de 3 em 1 comando, mas não todos
Tenho este formato de data:
09/Sep/24 05:02 AM
e preciso subtrair 1 dia dele:
Por exemplo:
09/Sep/24 05:02 AM
- 1 day ago
deve render08/Sep/24 05:02 AM
Eu tentei, então, isso faz as contas:
date "+%m/%d/%y %H:%M %r" -d "1 hour ago"
e produz
09/09/24 14:52 02:52:30 PM
(bom, exceto que eu não disse para produzir segundos)
Isso não funciona de jeito nenhum
date "+%m/%b/%y %H:%M %r" -d "09/Sep/24 05:02 AM"
date: invalid date ‘09/Sep/24 05:02 AM’
mesmo que isso faça:
date "+%m/%b/%y %H:%M %r"
09/Sep/24 15:55 03:55:49 PM
Mais uma vez, incluindo segundos que não quero.
De acordo com esta postagem, o seguinte deve funcionar:
date -d "09/Sep/24 05:02 AM - 2 hours" '+%m/%b/%y %H:%M %r'
date: invalid date ‘09/Sep/24 05:02 AM - 2 hours’
É possível fazer isso com o gnu date em 1 linha?
info date 'date input formats'
informará quais formatos de data o GNUdate
aceita como entrada ( o mesmo online para a versão mais recente do GNU coreutils).E
09/Sep/24 05:02 AM
não é um dos que ele reconhece. Qualquer formato de data que não especifique o deslocamento UTC também é ambíguo, pois você não sabe a qual fuso horário ele se refere, e mesmo se assumirmos o horário local , há momentos no ano em que não podemos saber se é inverno ou verão (para aqueles fusos horários onde o DST se aplica).Para o formato de saída, veja aqui .
Então, isso depende do local. Veja a saída de
locale t_fmt_ampm
para ver o que é no seu local. No meu:Inclui segundos.
Um formato inequívoco, simples de analisar e reconhecido por muitas coisas, incluindo GNU, BSD, busybox, toybox, ast-open
date
,zsh
's e todas asstrftime
funções internas/funções de todas as linguagens, ksh93/bashprintf %T
é o tempo de época (o número de segundos Unix desde 1970-01-01 00:00:00 +0000) em decimal, embora dependendo da ferramenta, ele precise ser prefixado com#
ou@
quando especificado como entrada.Um formato que é legível por humanos e suportado como formato de entrada por muitas coisas, incluindo a maioria das
date
implementações que aceitam data como entrada para qualquer coisa diferente de acertar o relógio, é a variante ISO 8601 no formatoYYYY-MM-DD HH:MM:ZZ {+,-}ZZZZ
produzido pordate '+%F %T %z'
.(para busybox,
ENABLE_FEATURE_TIMEZONE
deve ser habilitado no momento da compilação)Para poder usar um formato de data arbitrário como entrada, você precisa de uma ferramenta ou
date
implementação que suporte a especificação do formato de entrada (o padrão+fmt
é para o formato de saída e, a propósito, deve vir depois das opções, pois é um argumento não opcional). Isso inclui ast-opendate
com a-p
opção busyboxdate
(se compilado em) com-D
, BSDdate
com-jf
, zsh'sstrftime -r
, ksh93'sprintf %T
(também ast-open'sdate
) com a$DATEMSK
variável de ambiente, mas não GNUdate
(ainda, veja a discussão anterior onde o recurso foi considerado ou esta solicitação de bug ).Também tenha cuidado porque strings como
Sep
são dependentes de localidade. Então, para analisar as em inglês, você vai querer definir a localidade para uma em que o inglês seja o idioma (pode ser aC
localidade neste caso).(aqueles presumiram que a data se referia ao meu horário local).
Cuidado com os especificadores de formato, pois alguns
strptime()
cobrem apenas um subconjunto daqueles destrftime()
.Agora, quando se trata de fazer cálculos sobre eles, ele se torna ainda menos portátil. GNU e ast-open's
date
/ ksh93'sprintf
suportam alguma sintaxe para timespecs relativos, mas a sintaxe varia entre eles. BSDsdate
têm uma maneira mais formal e inequívoca de fazer isso com sua-v
opção.O mais fácil é frequentemente trabalhar com tempo de época onde você obtém um número inteiro de segundos. Você faria:
O builtin do zsh
strftime
é bom para issoSe você tiver que usar GNU
date
, já que essa implementação não suporta especificar o formato de entrada, você precisa converter o$datetime
para um formato que ele reconheça. Isso poderia ser,09 Sep 2024 05:02 AM
por exemplo (funciona com GNU ou ast-opendate
, não outrasdate
implementações) para o qual precisamos apenas substituir o/
s por espaços.Aqui, usando um shell com suporte para o operador ksh93,
${param//pattern/replacement}
como ksh93, zsh, bash, mksh, yash:Ou usando
date
o suporte interno do GNU para calcular deslocamentos para datas:Para obter o formato de impressão do nome abreviado do mês do ano sem segundos:
Saída:
Para obter o número do mês:
Saída:
O formato
%I:%M %p
imprime o horário de 12 horas sem segundos, enquanto%r
imprime o horário com segundos.Além disso, observe que as datas do calendário em meus comandos são impressas com
+%d/%b/%y
e+%d/%m/%y
que imprimem o número do dia, número do mês e ano de dois dígitos e o número do dia, mês abreviado do ano e ano de dois dígitos, respectivamente. Você tem isso como+%m/%d/%y
para um dos seus exemplos e+%m/%b/%y
para outro. O que eles estão realmente imprimindo são o número do mês, o número do dia do mês e o ano de dois dígitos e, em seguida, o número do mês, o nome abreviado do mês e o ano de dois dígitos, respectivamente. Parece que está imprimindo o dia, o mês e o ano porque o dia do mês e o número do mês (setembro) são o mesmo número hoje.Para ilustrar melhor isso, se você usar seu comando
Você verá que a saída é
O que indica que o mês é, na verdade, o primeiro número, enquanto você quer que ele seja o segundo número.
Tenha em mente que os horários estão um pouco errados porque são dos momentos em que executei os comandos.