Por que TZ = UTC-8 produz datas UTC + 8?


25

O horário atual em Los Angeles é 18:05. Mas quando corro TZ=UTC-8 date --iso=ns, recebo:

2013-12-07T10:05:37,788173835+0800

O utilitário date me diz que a hora é 10:05 e até diz que está relatando como UTC + 8. Por quê?

Respostas:


33

O motivo é que TZ=UTC-8é interpretado como um fuso horário POSIX . No formato do fuso horário POSIX, as três letras são a abreviação do fuso horário (que é arbitrária) e o número é o número de horas que o fuso horário está atrás do UTC. Portanto, UTC-8significa um fuso horário abreviado "UTC" que é de -8 horas atrás do UTC real, ou UTC + 8 horas.

(Funciona assim porque o Unix foi desenvolvido nos EUA, atrás do UTC. Esse formato permite que os fusos horários dos EUA sejam representados como EST5, CST6 etc.)

Você pode ver o que está acontecendo com estes exemplos:

$ TZ=UTC-8 date +'%Z %z'
UTC +0800
$ TZ=UTC8 date +'%Z %z'
UTC -0800
$ TZ=FOO-8 date +'%Z %z'
FOO +0800

O -0800formato do fuso horário ISO adota a abordagem oposta, -indicando que a zona está atrás do UTC e +indicando que a zona está à frente do UTC.


Ah, então o que eu realmente queria era TZ=PST+8 date. Obrigado. Também encontrei esta explicação em man timezone: "A string std especifica o nome do fuso horário e deve ter três ou mais caracteres alfabéticos. A string de deslocamento segue imediatamente std e especifica o valor da hora a ser adicionado à hora local para obter o Tempo Universal Coordenado ( UTC). O deslocamento é positivo se o fuso horário local estiver a oeste do Meridiano Prime e negativo se estiver a leste. A hora deve estar entre 0 e 24 e os minutos e segundos 0 e 59. "
AlexDaniel12

3
@ Alex não, o que você realmente quer é TZ=America/Los_Angeles. Você está esquecendo que o horário do Pacífico é -7 durante o horário de verão.
precisa

3
@MattJohnson, você quer dizer TZ=:America/Los_Angeles. Os dois pontos indicam que é um arquivo de fuso horário da Olson. E em outro comentário, ele mencionou que queria ignorar o horário de verão, o que não faria.
Cjm 07/12

@ CCJ, Obrigado, você está certo sobre o cólon, e eu não tinha visto esse comentário.
Matt Johnson-Pint

América, causa ao mundo, se isso significa que temos que ser EST-5 CST-6.
Evan Carroll

7

Sempre que você especifica um fuso horário no formato de +/- 00:00, está especificando um deslocamento , não o fuso horário real. A partir da GNU libc documentação (que segue o padrão POSIX):

O deslocamento especifica o valor da hora que você deve adicionar à hora local para obter um valor de Tempo Universal Coordenado. Possui sintaxe como [+ | -] hh [: mm [: ss]]. Isso é positivo se o fuso horário local estiver a oeste do Meridiano Prime e negativo se estiver a leste. A hora deve estar entre 0 e 23 e os minutos e segundos entre 0 e 59.

É por isso que parece ser o inverso do que você espera.


2

Why?

Porque o POSIX exige .

Se precedido por um '-', o fuso horário deve estar a leste do Primeiro Meridiano; caso contrário, deve ser oeste (o que pode ser indicado por um '+' precedente opcional).

Portanto, isso dará um tempo próximo a [1] Los Angeles (com qualquer rótulo de três letras para o texto do fuso horário):

$ TZ=ANY8 date "+%Y-%m-%d %H:%M:%S %Z%z"
2016-04-23 10:47:12 ANY-0800

$ TZ=GMT+8 date "+%Y-%m-%d %H:%M:%S %Z%z"
2016-04-23 10:47:12 GMT-0800

E isso deve dar o tempo próximo Shanghai, Chinaou Perth, Australia:

$ TZ=ANY-8 date "+%Y-%m-%d %H:%M:%S %Z%z"
2016-04-24 02:47:12 ANY+0800

$ TZ=CST-8 date "+%Y-%m-%d %H:%M:%S %Z%z"
2016-04-23 02:47:12 CST+0800

[1] Próximo, pois pode haver algum horário de verão que altera a "hora local" real.


1

Como método alternativo, você pode usar o comando zdumppara mostrar a hora atual em outros fusos horários + compensações.

O Zdump imprime a hora atual em cada nome de zona nomeado na linha de comando.

As mesmas regras se aplicam aos fusos horários; oeste do meridiano principal estar "atrás", enquanto o leste estar "à frente".

Exemplo

$ zdump PST PST Sáb 7 de dezembro 03:25:27 2013 PST

Eu criei esse script para mostrar vários dos fusos horários + desvios que estamos interessados ​​em usar zdumpe datepara podermos compará-los.

$ cat cmd.bash
#!/bin/bash

printf "\ndate: %s\n\n" "$(date)"

for tz in EST PST PST+8 PST-8 UTC UTC+8 UTC-8; do
  echo "-- timezone $tz"
  printf "zdump: %s\n" "$(zdump $tz)"
  printf "date:         %s\n" "$(TZ=$tz date +'%a %b %d %T %Y - (%Z %z)')"
  echo ""
done

Então, quando você o executa, pode ver a comparação de zdumppara date:

$ ./cmd.bash 

date: Sat Dec  7 02:59:05 EST 2013

-- timezone EST
zdump: EST  Sat Dec  7 02:59:05 2013 EST
date:         Sat Dec 07 02:59:05 2013 - (EST -0500)

-- timezone PST
zdump: PST  Sat Dec  7 07:59:05 2013 PST
date:         Sat Dec 07 07:59:05 2013 - (PST +0000)

-- timezone PST+8
zdump: PST+8  Fri Dec  6 23:59:05 2013 PST
date:         Fri Dec 06 23:59:05 2013 - (PST -0800)

-- timezone PST-8
zdump: PST-8  Sat Dec  7 15:59:05 2013 PST
date:         Sat Dec 07 15:59:05 2013 - (PST +0800)

-- timezone UTC
zdump: UTC  Sat Dec  7 07:59:05 2013 UTC
date:         Sat Dec 07 07:59:05 2013 - (UTC +0000)

-- timezone UTC+8
zdump: UTC+8  Fri Dec  6 23:59:05 2013 UTC
date:         Fri Dec 06 23:59:05 2013 - (UTC -0800)

-- timezone UTC-8
zdump: UTC-8  Sat Dec  7 15:59:05 2013 UTC
date:         Sat Dec 07 15:59:05 2013 - (UTC +0800)

Na verdade, estou tentando obter o horário atual no horário padrão do Pacífico, ignorando o horário de verão.
Alex Henrie

11
Eu tive que votar este abaixo porque você está supondo que "UTC-8" está incorreto. Está correto, simplesmente não faz o que o usuário espera. Não acho que ele responda à pergunta de por que funciona dessa maneira.
Jordanm #

@ Jordanm - veja a limpeza.
slm

11
Ainda explica o que está acontecendo, mas não o porquê e "por que" é o que o OP está perguntando. Vou remover meu voto negativo, mas ainda não sinto que seja uma boa resposta para a pergunta.
Jordanm #
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.