Como posso o `date` imprimir a hora de um fuso horário diferente?

115

Eu tenho um servidor executando com o fuso horário definido como UTC. Parecia que geralmente era uma boa prática (por favor, corrija-me se estiver errado).

De qualquer forma, um dos servidores aos quais eu me conecto, para scparquivos, está em execução EDTe armazena os arquivos que eu preciso copiar no formato/path/to/filename/data20120913

Eu olhei para tentar rsyncarquivos usando algo como o -mtime -1sinalizador de localização de arquivos modificados no último dia, mas não tive sorte.

Eu não me importo em usar apenas scppara copiar o arquivo do dia atual, mas a partir de agora há uma janela de 4 horas em que a execução date +%Y%m%dfornecerá um dia diferente em cada servidor e isso me incomoda um pouco.

Examinando man date, vejo que posso obter o horário como UTC, mas não vejo uma maneira de fazê-lo como outro fuso horário comoEDT

Suponho que eu também possa usar algo como a GNUextensão de data date -d 20100909 +%spara obter a data em segundos a partir da época, aplicar um 4 * 60 * 60segundo cálculo manual e ver como renderizá-la como uma data - mas, quando o horário de verão chegar, ainda haverá uma hora de folga .

Existe uma maneira mais simples de gerar a data em um YYYYMMDDformato para EDTum servidor definido como UTC?

cwd
fonte
EDT não é um fuso horário reconhecido no Linux, pelo menos. Veja o meu "Cuidado!" responda abaixo para toda a história feia. Se o EDT for reconhecido na sua marca do * NIX, você ainda deve ter cuidado e verificar duas vezes a sequência do fuso horário.
Mike S

Respostas:

175

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 TZconfiguração e o datecomando. No rcshell Bourne-like e -like, isso define a TZvariável apenas para a linha de comando. Em outras conchas ( csh, tcsh, fish), você sempre pode usar o envcomando:

env TZ=America/New_York date

tl; dr

Em sistemas Linux. fusos horários são definidos nos arquivos no /usr/share/zoneinfodiretório 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 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 do UTC para o horário padrão; e a notação para definir como ocorre a transição para o horário de verão, se aplicável.

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

Cuidado que a especificação de uma zona inexistente (nome do arquivo) é silenciosamente ignorada e os horários UTC são relatados. Por exemplo, isso informa um horário incorreto:

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

A Especificação Única do UNIX, 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 método alternativo à especificação de fusos horários usando um nome de caminho para um arquivo de descrição, o SUSv3 descreve o modelo POSIX. Nesse formato, uma sequência é definida como:

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

onde 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 valor offseté positivo para os fusos horários a oeste do meridiano principal e negativo para os a leste do meridiano. O deslocamento é adicionado à hora local para obter o UTC (anteriormente conhecido como GMT). Os campos starte endhora indicam quando ocorrem as transições padrão / horário de verão.

Por exemplo, no leste dos Estados Unidos, o horário padrão é 5 horas mais cedo que o UTC e podemos especificar EST5EDTem vez de America/New_York. No entanto, essas alternativas nem sempre são reconhecidas, especialmente para zonas fora dos Estados Unidos, e devem ser evitadas.

O HP-UX (um UNIX compatível com SUSv3) usa regras de texto /usr/lib/tztabe 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.

NOTA: Você deve ser capaz de encontrar todos os fusos horários inspecionando o seguinte diretório: /usr/share/zoneinfo.

JRFerguson
fonte
não tenho certeza se estou errado, mas exportparece melhor que o envcomando
insira 23/12/19
@JRFerguson - Se um fuso horário não estiver incluído na lista, por exemplo, Las Vegas ou Nevada, quais são as alternativas para validar o horário?
Motivado
@Motivated Se sua cidade ou estado não estiver incluído, escolha um que use as mesmas informações de zona que as suas. Por exemplo, estou na Flórida, que usa o mesmo fuso horário de Nova York, então minhas máquinas são sincronizadas com o horário de Nova York.
JRFerguson 31/01
1
@JRFerguson - Isso pressupõe que a pessoa esteja ciente dos vários fusos horários e seja capaz de usar uma alternativa, por exemplo, Nova York no seu caso. Essa seria a única opção? Por exemplo, eu não moro na Europa e não conhecerei os fusos horários sobrepostos.
Motivado
1
@Motivated Você pode usar algo como este site para ajudá-lo a encontrar outros pontos na sua zona.
JRFerguson 31/01
33

Você pode fazer isso manipulando a TZvariável de ambiente. A seguir, será apresentado o horário local para os EUA / Leste, que também será inteligente o suficiente para lidar com o horário de verão quando houver:

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

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

James Sneeringer
fonte
17

Seja cuidadoso! Data felizmente cuspir o tempo no seu fuso horário ATUAL, se você atribuir um fuso horário que não reconhece.

Veja 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. Na verdade,

-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 as informações da sua zona coincidirem com as suas, você poderá exibir a data no horário da zona de Gobbledygook e terá prazer em fazê-lo sem um valor de saída para que você saiba que o zona não é conhecida por ele:

-bash-4.2$ TZ=Gobbledygook date
Wed Feb 18 19:37:36 Gobbledygook 2015
-bash-4.2$ echo $?
0
Mike S
fonte
YMMV: na minha caixa MacOS / BSD, a TZstring malformada retorna o horário UTC.
Mark Hudson
8
TODAY=$(TZ=":US/Eastern" date)
echo $TODAY
Lin
fonte
6

A sintaxe da data é misteriosa e propensa a erros, o que torna uma chamada de linha de comando um problema. Portanto, escrevi um pequeno script ( denominei -o horário mundial ), que imprimirá o horário especificado (ou atual) do zome de horário base (o local) em alguns outros fusos horários e no inverso.

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

#! / bin / sh
#
# Imprima a hora especificada (ou atual) a partir da hora base em outros fusos horários
# e o inverso
#

# Fuso horário base de / para o qual converter
TZBASE = Europa / Atenas

# Fusos horários a serem exibidos
# Veja / usr / share / zoneinfo / para mais nomes
TZONES = 'UTC America / Los_Angeles America / Nova_Iorque Europa / Londres Europa / Paris'

# Formato de apresentação
FORMATO = '% H:% M (% p)% Z% a% m% b% Y'

se ["$ 1"]; então
  time = "$ 1"
outro
  hora = `data +% T`
fi

# Mostra a hora no fuso horário de entrada especificado na saída especificada
# fuso horário
altura de começar()
{
  TZIN = $ 1
  TZOUT = $ 2

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

para tz em $ TZONES; Faz
  horário do show $ TZBASE $ tz
feito

eco

para tz em $ TZONES; Faz
  hora do show $ tz $ TZBASE
feito

Diomidis Spinellis
fonte
3

Geralmente, você tem um carimbo de data / hora 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
dimcha
fonte