¿Cómo puedo hacer que `date` muestre la hora desde una zona horaria diferente?

115

Tengo un servidor ejecutándose con la zona horaria establecida en UTC. Parecía que generalmente era una buena práctica (corríjame si me equivoco).

De todos modos, uno de los servidores a los que me conecto, en orden a los scparchivos, se está ejecutando EDTy almacena los archivos que necesito copiar en el formato/path/to/filename/data20120913

Miré el intento de rsyncarchivos usando algo como encontrar la -mtime -1bandera de encontrar archivos modificados en el último día, pero no tuve suerte.

No me importa usar solo scppara copiar el archivo del día actual, pero a partir de ahora hay una ventana de 4 horas donde la ejecución date +%Y%m%ddará un día diferente en cada servidor y eso me molesta un poco.

Mirando a través man dateveo que puedo tener la salida de tiempo como UTC, pero no veo una manera de que salga como otra zona horaria comoEDT

Supongo que también podría usar algo como la GNUextensión de fecha date -d 20100909 +%spara obtener la fecha en segundos de la época, aplicar un 4 * 60 * 60segundo cálculo manual y ver cómo representar eso como una fecha, pero cuando comience el horario de verano todavía habrá una hora libre .

¿Hay una manera más simple de generar la fecha en un YYYYMMDDformato para EDTun servidor configurado UTC?

cwd
fuente
EDT no es una zona horaria reconocida, al menos en Linux. Mira mi "¡Ten cuidado!" responde a continuación para toda la historia fea. Si se reconoce EDT en su marca de * NIX, aún debe tener precaución y verificar su cadena de zona horaria.
Mike S

Respuestas:

175

Puede establecer una zona horaria para la duración de la consulta, por lo tanto:

TZ=America/New_York date

Tenga en cuenta el espacio en blanco entre la TZconfiguración y el datecomando. En el rcshell Bourne-like and like , eso establece la TZvariable solo para la línea de comando. En otras conchas ( csh, tcsh, fish), siempre se puede utilizar el envcomando:

env TZ=America/New_York date

tl; dr

En sistemas Linux. las zonas horarias se definen en archivos en el /usr/share/zoneinfodirectorio. Esta estructura a menudo se conoce como la "base de datos Olson" para honrar a su contribuyente fundador.

Las reglas para cada zona horaria se definen como líneas de archivo de texto que luego se compilan en un archivo binario. Las líneas así compiladas definen el nombre de la zona; un rango de datos y tiempo durante el cual se aplica la zona; un desplazamiento de UTC para la hora estándar; y la notación para definir cómo ocurre la transición hacia y desde el horario de verano, si corresponde.

Por ejemplo, el directorio "América" ​​contiene la información requerida para Nueva York en el archivo America/New_Yorktal como se utilizó anteriormente.

Tenga en cuenta que la especificación de una zona inexistente (nombre de archivo) se ignora silenciosamente y se informan los tiempos UTC. Por ejemplo, esto informa una hora incorrecta:

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

La especificación Single UNIX, versión-3, conocida como SUSv3 o POSIX-2001, señala que para la portabilidad, la cadena de caracteres que identifica la descripción de la zona horaria debe comenzar con un carácter de dos puntos. Por lo tanto, también podemos escribir:

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

Como un método alternativo a la especificación de zonas horarias utilizando un nombre de ruta a un archivo de descripción, SUSv3 describe el modelo POSIX. En este formato, una cadena se define como:

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

donde stdes el nombre del componente estándar y dstes el horario de verano. Cada nombre consta de tres o más caracteres. El offsetes positivo para las zonas horarias al oeste del meridiano principal y negativo para las del este del meridiano. El desplazamiento se agrega a la hora local para obtener UTC (anteriormente conocido como GMT). Los campos starty endhora indican cuándo ocurren las transiciones estándar / luz del día.

Por ejemplo, en el este de los Estados Unidos, la hora estándar es 5 horas antes que UTC, y podemos especificar EST5EDTen lugar de America/New_York. Sin embargo, estas alternativas no siempre se reconocen, especialmente para zonas fuera de los Estados Unidos y es mejor evitarlas.

HP-UX (un UNIX compatible con SUSv3) utiliza reglas de texto /usr/lib/tztaby los nombres POSIX como EST5EDT, CST6CDT, MST7MDT, PST8PDT. El archivo incluye todas las reglas históricas para cada zona horaria, similar a la base de datos Olson.

NOTA: Usted debe ser capaz de encontrar todas las zonas horarias inspeccionando el directorio siguiente: /usr/share/zoneinfo.

JRFerguson
fuente
no estoy seguro de si me equivoco, pero se exportve mejor que el envcomando
insign
@JRFerguson: si una zona horaria no está incluida en la lista, por ejemplo, Las Vegas o Nevada, ¿cuáles son las alternativas para validar la hora?
Motivado el
@ Motivado Si su ciudad o estado no está incluido, elija uno que use la misma información de zona que la suya. Por ejemplo, estoy en Florida, que usa la misma zona horaria que Nueva York, por lo que mis máquinas se sincronizan con la hora de Nueva York.
JRFerguson
1
@JRFerguson: eso supone que la persona conoce las diversas zonas horarias y puede usar una alternativa, por ejemplo, Nueva York en su caso. ¿Sería esa la única opción? Por ejemplo, no vivo en Europa y no sabré las zonas horarias superpuestas.
Motivado el
1
@ Motivado Puede usar algo como este sitio para ayudarlo a encontrar otros puntos en su zona.
JRFerguson
33

Puede hacer esto manipulando la TZvariable de entorno. Lo siguiente le dará la hora local para EE. UU. / Este, que también será lo suficientemente inteligente como para manejar el horario de verano cuando eso ocurra:

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

El nombre de la zona proviene de los archivos y directorios dentro /usr/share/zoneinfo.

James Sneeringer
fuente
17

¡Ten cuidado! Date felizmente escupirá la hora en su zona horaria ACTUAL, si le da una zona horaria que no reconoce.

Mira esto:

-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

Tenga en cuenta que no hay una zona horaria llamada EDT. Como una cuestión de hecho,

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

devoluciones

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

Y esto 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

Sin embargo, si su amigo vive en la tierra mística de Gobbledygook y su información de zona coincide con la suya, puede obtener la fecha y hora en la zona de Gobbledygook y estará encantado de hacerlo sin ningún valor de salida para hacerle saber que el La zona no es conocida:

-bash-4.2$ TZ=Gobbledygook date
Wed Feb 18 19:37:36 Gobbledygook 2015
-bash-4.2$ echo $?
0
Mike S
fuente
YMMV: en mi caja MacOS / BSD, la TZcadena con formato incorrecto devuelve la hora UTC.
Mark Hudson
8
TODAY=$(TZ=":US/Eastern" date)
echo $TODAY
Lin
fuente
6

La sintaxis de la fecha es arcana y propensa a errores, lo que hace que una invocación de línea de comandos sea una molestia. Por lo tanto, escribí un pequeño script (lo llamé worldtime ), que imprimirá el tiempo especificado (o actual) desde el tiempo base zome (el local) en algunas otras zonas horarias y viceversa.

Aquí está. Ajústelo para que coincida con sus necesidades, póngalo en su camino y hágalo ejecutable.

#! / bin / sh
# #
# Imprima el tiempo especificado (o actual) desde el tiempo base en otras zonas horarias
# y lo contrario
# #

# Zona horaria base desde / a la cual convertir
TZBASE = Europa / Atenas

# Zonas horarias para mostrar
# Ver / usr / share / zoneinfo / para más nombres
TZONES = 'UTC America / Los_Angeles America / New_York Europe / London Europe / Paris'

# Desplegar formato
FORMATO = '% H:% M (% p)% Z% a% m% b% Y'

si ["$ 1"]; entonces
  tiempo = "$ 1"
más
  hora = `fecha +% T`
fi

# Muestra la hora de la zona horaria de entrada especificada en la salida especificada
# zona horaria
tiempo de la funcion()
{
  TZIN = $ 1
  TZOUT = $ 2

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

por tz en $ TZONES; hacer
  showtime $ TZBASE $ tz
hecho

eco

por tz en $ TZONES; hacer
  showtime $ tz $ TZBASE
hecho

Diomidis Spinellis
fuente
3

A menudo tiene una marca de tiempo en la zona horaria local y necesita convertirla a tz remota. Se puede hacer con:

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

dónde:

America/Curacao - remote timezone
MSK - local timezone
dimcha
fuente