Como posso fazer com que 'date' imprima a hora a partir de um fuso horário diferente?

93

Eu tenho um servidor em execução com o fuso horário definido como UTC . Parecia que geralmente era uma boa prática (por favor me corrija se eu estiver errado).

De qualquer forma, um dos servidores aos quais me conecto, para scp files, está em execução em EDT e armazena arquivos que preciso copiar no formato /path/to/filename/data20120913

Eu olhei para tentar rsync arquivos usando algo como -mtime -1 flag do find para arquivos modificados no último dia, mas não tive sorte.

Eu não me importo de usar apenas scp para copiar o arquivo do dia atual, mas a partir de agora há uma janela de 4 horas em que executar date +%Y%m%d dará um dia diferente em cada servidor e isso me incomodará pouco.

Olhando através de man date , vejo que posso ter a saída de tempo como UTC , mas não vejo uma maneira de ter a saída como outro fuso horário, como EDT

Suponho que eu também poderia usar algo como GNU date extension date -d 20100909 +%s para obter a data em segundos a partir da época, aplicar um cálculo 4 * 60 * 60 segundo manual e ver a renderização como uma data. quando a luz do dia entra em ação, ainda será uma hora de folga.

Existe uma maneira mais simples de gerar a data em um formato YYYYMMDD para EDT em um servidor definido como UTC ?

    
por cwd 13.09.2012 / 23:24

6 respostas

143

Você pode definir um fuso horário para a duração da consulta, assim:

TZ=America/New_York date

Observe o espaço em branco entre a configuração TZ e o comando date . Em shell parecido com Bourne e rc , isso define a variável TZ apenas para a linha de comando. Em outros shells ( csh , tcsh , fish ), você sempre pode usar o comando env :

env TZ=America/New_York date

tl; dr

Nos sistemas Linux. fusos horários são definidos em arquivos no diretório /usr/share/zoneinfo . Essa estrutura é geralmente chamada de "banco de dados Olson" para homenagear seu colaborador fundador.

As regras para cada fuso horário são definidas como linhas de arquivo de texto que são então compiladas em um arquivo binário. As linhas assim compiladas, definem o nome da zona; um intervalo de dados e tempo durante o qual a zona se aplica; um deslocamento de UTC para o horário padrão; e a notação para definir como ocorre a transição para e do horário de verão, se aplicável.

Por exemplo, o diretório "America" contém as informações necessárias para Nova York no arquivo America/New_York , conforme usado acima.

Tenha em atenção que a especificação de uma zona inexistente (nome do ficheiro) é silenciosamente ignorada e os tempos UTC são reportados. Por exemplo, isso informa um tempo incorreto:

TZ="America/New York" date ### WRONG ###

A Single UNIX Specification, versão-3, conhecida como SUSv3 ou POSIX-2001, observa que, para portabilidade, a cadeia de caracteres que identifica a descrição do fuso horário deve começar com um caractere de dois-pontos. Assim, também podemos escrever:

TZ=":America/New_York" date
TZ=":America/Los_Angeles" date

Como um método alternativo para a especificação de fusos horários usando um nome de caminho para um arquivo de descrição, o SUSv3 descreve o modelo POSIX. Neste formato, uma string é definida como:

std offset [dst[offset][,start-date[/time],end-date[/time]]]

em que std é o nome do componente padrão e dst é o horário de verão. Cada nome consiste em três ou mais caracteres. O offset é positivo para fusos horários a oeste do meridiano principal e negativo para aqueles a leste do meridiano. O deslocamento é adicionado à hora local para obter o UTC (anteriormente conhecido como GMT). Os campos start e end time indicam quando ocorrem as transições padrão / de luz do dia.

Por exemplo, no leste dos Estados Unidos, o horário padrão é 5 horas antes do UTC e podemos especificar EST5EDT em vez de America/New_York . Essas alternativas nem sempre são reconhecidas, no entanto, especialmente para zonas fora dos Estados Unidos e devem ser evitadas.

O HP-UX (um UNIX compatível com SUSv3) usa regras textuais em /usr/lib/tztab e os nomes POSIX como EST5EDT, CST6CDT, MST7MDT, PST8PDT. O arquivo inclui todas as regras históricas para cada fuso horário, semelhante ao banco de dados Olson.

OBSERVAÇÃO: você deve conseguir encontrar todos os fusos horários inspecionando o seguinte diretório: /usr/share/zoneinfo .

    
por 13.09.2012 / 23:41
30

Você pode fazer isso manipulando a variável de ambiente TZ . A seguir, você terá a hora local para EUA / Leste, que também será inteligente o suficiente para lidar com o horário de verão quando isso acontecer:

# all on one line
TZ=":US/Eastern" date +%Y%m%d

O nome da zona vem dos arquivos e diretórios dentro de /usr/share/zoneinfo .

    
por 13.09.2012 / 23:58
17

Tenha cuidado! A data ficará feliz em cuspir a hora no fuso horário CURRENT, se você conceder um fuso horário que não reconheça.

Verifique isso:

-bash-4.2$ env TZ=EDT date
Wed Feb 18 19:34:41 EDT 2015
-bash-4.2$ date
Wed Feb 18 19:34:43 UTC 2015

Observe que não há fuso horário chamado EDT. De fato,

-bash-4.2$ find /usr/share/zoneinfo -name "*EDT*"

retorna

/usr/share/zoneinfo/EST5EDT
/usr/share/zoneinfo/posix/EST5EDT
/usr/share/zoneinfo/right/EST5EDT

E isso funciona:

-bash-4.2$ TZ=EST5EDT date
Wed Feb 18 14:36:59 EST 2015
-bash-4.2$ date
Wed Feb 18 19:37:01 UTC 2015

No entanto, se seu amigo mora na terra mística de Gobbledygook e sua informação de zona coincide com a sua, você pode ter a data de saída na zona de Gobbledygook e ficará feliz em fazer isso sem um valor de saída saiba que a zona não é conhecida:

-bash-4.2$ TZ=Gobbledygook date
Wed Feb 18 19:37:36 Gobbledygook 2015
-bash-4.2$ echo $?
0
    
por 18.02.2015 / 20:42
8
TODAY=$(TZ=":US/Eastern" date)
echo $TODAY
    
por 31.03.2015 / 17:36
4

A sintaxe date é enigmática e propensa a erros, o que torna uma invocação na linha de comando um problema. Eu, portanto, escrevi um pequeno script (eu o nomeei worldtime ), que irá imprimir o tempo especificado (ou atual) do zome da base (seu local) em alguns outros fusos horários e o inverso.

Aqui está. Ajuste-o para atender às suas necessidades, coloque-o em seu caminho e torne-o executável.

#!/bin/sh
#
# Print the specified (or current) time from base time in other time zones
# and the converse
#

# Base time zone from/to which to convert
TZBASE=Europe/Athens

# Time zones to display
# See /usr/share/zoneinfo/ for more names
TZONES='UTC America/Los_Angeles America/New_York Europe/London Europe/Paris'

# Display format
FORMAT='%H:%M (%p) %Z %a %m %b %Y'

if [ "$1" ] ; then
  time="$1"
else
  time='date +%T'
fi

# Show the time from the specified input time zone in the specified output
# time zone
showtime()
{
  TZIN=$1
  TZOUT=$2

  TZ=$TZOUT date --date='TZ="'$TZIN'"'" $time" +"$time $TZIN is $TZOUT $FORMAT"
}

for tz in $TZONES ; do
  showtime $TZBASE $tz
done

echo

for tz in $TZONES ; do
  showtime $tz $TZBASE
done

    
por 13.04.2015 / 11:16
3

Muitas vezes você tem timestamp no fuso horário local e precisa convertê-lo em tz remoto. Isso pode ser feito com:

TZ=America/Curacao date -d 'Tue Nov 28 00:07:05 MSK 2016'

onde:

America/Curacao - remote timezone
MSK - local timezone
    
por 29.11.2016 / 11:44

Tags