¿Por qué TZ = UTC-8 produce fechas que son UTC + 8?

25

La hora actual en Los Ángeles es 18:05. Pero cuando corro TZ=UTC-8 date --iso=ns, obtengo:

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

La utilidad de fecha me dice que son las 10:05, e incluso dice que lo informa como UTC + 8. ¿Por qué?

Alex Henrie
fuente

Respuestas:

33

La razón es que TZ=UTC-8se interpreta como una zona horaria POSIX . En el formato de zona horaria POSIX, las 3 letras son la abreviatura de la zona horaria (que es arbitraria) y el número es la cantidad de horas que la zona horaria está detrás de UTC. Entonces, UTC-8significa una zona horaria abreviada "UTC" que está −8 horas detrás del UTC real, o UTC + 8 horas.

(Funciona de esa manera porque Unix se desarrolló en los EE. UU., Que está detrás de UTC. Este formato permite que las zonas horarias de EE. UU. Se representen como EST5, CST6, etc.)

Puedes ver que eso es lo que sucede con estos ejemplos:

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

El -0800formato de zona horaria ISO toma el enfoque opuesto, -indicando que la zona está detrás de UTC e +indicando que la zona está por delante de UTC.

cjm
fuente
Ah, entonces lo que realmente quería era TZ=PST+8 date. Gracias. También encontré esta explicación en man timezone: "La cadena estándar especifica el nombre de la zona horaria y debe tener tres o más caracteres alfabéticos. La cadena de desplazamiento sigue inmediatamente a la norma y especifica el valor de hora que se agregará a la hora local para obtener la hora universal coordinada ( UTC). El desplazamiento es positivo si la zona horaria local está al oeste del Meridiano principal y negativa si está al este. La hora debe estar entre 0 y 24, y los minutos y segundos 0 y 59. "
Alex Henrie
3
@ Alex no, lo que realmente quieres es TZ=America/Los_Angeles. Olvida que la hora del Pacífico es -7 durante el horario de verano.
Matt Johnson-Pint
3
@ MattJohnson, quieres decir TZ=:America/Los_Angeles. Los dos puntos indican que es un archivo de zona horaria de Olson. Y en otro comentario, mencionó que quería ignorar el horario de verano, lo que no haría.
cjm
@cjm, gracias, tienes razón sobre el colon, y no había visto ese comentario.
Matt Johnson-Pint
América, porque el mundo significa que tenemos que ser EST-5 CST-6 .
Evan Carroll
7

Cada vez que especifica una zona horaria en el formato de +/- 00:00, está especificando un desplazamiento , no la zona horaria real. De la GNU libc documentación (que sigue el estándar POSIX):

El desplazamiento especifica el valor de hora que debe agregar a la hora local para obtener un valor de hora universal coordinada. Tiene una sintaxis como [+ | -] hh [: mm [: ss]]. Esto es positivo si la zona horaria local está al oeste del primer meridiano y negativa si está al este. La hora debe estar entre 0 y 23, y los minutos y segundos entre 0 y 59.

Es por eso que parece ser lo contrario de lo que espera.

jordanm
fuente
2

Why?

Porque POSIX lo requiere .

Si está precedido por un '-', la zona horaria estará al este del meridiano principal; de lo contrario, estará al oeste (lo que puede indicarse mediante un '+' opcional anterior).

Entonces, esto dará tiempo cerca de [1] Los Angeles (con cualquier etiqueta de 3 letras para el texto de zona horaria):

$ 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

Y esto debería dar el tiempo cerca Shanghai, Chinao 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] Cerca porque puede haber algún horario de verano (DST) que cambie la "hora local" real.


fuente
1

Como método alternativo, puede usar el comando zdumppara mostrar la hora actual en otras zonas horarias + compensaciones.

Zdump imprime la hora actual en cada nombre de zona nombrado en la línea de comando.

Las mismas reglas se aplican con las zonas horarias; al oeste del meridiano principal está "atrás" mientras que al este está "adelante".

Ejemplo

$ zdump PST PST sáb 7 dic 03:25:27 2013 PST

Hice este script para mostrar varias de las zonas horarias + compensaciones que estamos interesados ​​en usar zdumpy datepara poder compararlas.

$ 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

A continuación, cuando se ejecuta se puede ver la comparación de zdumpa 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)
slm
fuente
Realmente estoy tratando de obtener la hora actual en la hora estándar del Pacífico, ignorando el horario de verano.
Alex Henrie
1
Tuve que rechazar este porque estás adivinando que "UTC-8" es incorrecto. Es correcto, simplemente no hace lo que el usuario espera. No creo que responda la pregunta de por qué funciona de esa manera.
jordanm
@jordanm: mira la limpieza.
slm
1
Todavía explica qué está sucediendo, pero no por qué y "por qué" es lo que pregunta OP. Eliminaré mi voto negativo, pero todavía no siento que sea una buena respuesta a la pregunta.
jordanm