Comment puis-je faire en sorte que `date` affiche l'heure d'un fuseau horaire différent?

115

J'ai un serveur en cours d'exécution avec le fuseau horaire défini sur UTC. Il semblait que c'était généralement une bonne pratique (corrigez-moi si je me trompe).

Quoi qu’il en soit, l’un des serveurs auquel je me connecte, pour les scpfichiers, s’exécute EDTet stocke les fichiers que je dois copier au format/path/to/filename/data20120913

J'ai essayé d'essayer de rsyncclasser des fichiers en utilisant quelque chose comme l' -mtime -1indicateur de recherche pour les fichiers modifiés le dernier jour, mais je n'ai pas eu de chance.

Cela ne me dérange pas de simplement utiliser scppour copier le fichier de la journée en cours, mais à l'heure actuelle, il existe une fenêtre de 4 heures où l'exécution date +%Y%m%dindique un jour différent sur chaque serveur, ce qui me perturbe un peu.

En regardant à travers, man dateje vois que je peux avoir la sortie heure comme UTC, mais je ne vois pas le moyen de la sortir comme un autre fuseau horaire commeEDT

Je suppose que je pourrais aussi utiliser quelque chose comme l' GNUextension de date date -d 20100909 +%spour obtenir la date en secondes à partir de l'époque, appliquer un 4 * 60 * 60second calcul manuel et voir comment rendre celle-ci en tant que date. .

Existe-t-il un moyen plus simple d’afficher la date dans un YYYYMMDDformat EDTdéfini sur un serveur défini UTC?

cwd
la source
EDT n’est pas un fuseau horaire reconnu - du moins pour Linux. Voir mon "Soyez prudent!" Répondez ci-dessous pour toute l'histoire laide. Si EDT est reconnu sur votre marque * NIX, vous devez néanmoins faire preuve de prudence et revérifier votre chaîne de fuseau horaire.
Mike S

Réponses:

175

Vous pouvez définir un fuseau horaire pour la durée de la requête, ainsi:

TZ=America/New_York date

Notez les espaces entre le TZparamètre et la datecommande. Dans un rcshell Bourne-like et-like , la TZvariable n'est définie que pour la ligne de commande. Dans d' autres coquilles ( csh, tcsh, fish), vous pouvez toujours utiliser la envcommande à la place:

env TZ=America/New_York date

tl; dr

Sur les systèmes Linux. Les fuseaux horaires sont définis dans les fichiers du /usr/share/zoneinforépertoire. Cette structure est souvent appelée "base de données Olson" pour honorer son contributeur fondateur.

Les règles de chaque fuseau horaire sont définies comme des lignes de fichier texte qui sont ensuite compilées dans un fichier binaire. Les lignes ainsi compilées définissent le nom de la zone. une plage de données et de temps pendant lesquels la zone s’applique; un décalage par rapport à l'heure UTC pour l'heure standard; et la notation permettant de définir le cas échéant le passage à l'heure d'été ou à l'heure d'été.

Par exemple, le répertoire "America" ​​contient les informations requises pour New York dans le fichier America/New_Yorkutilisé ci-dessus.

Attention, la spécification d'une zone inexistante (nom de fichier) est ignorée et les heures UTC sont signalées. Par exemple, cela signale une heure incorrecte:

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

La spécification UNIX unique, version 3, appelée SUSv3 ou POSIX-2001, indique que, pour des raisons de portabilité, la chaîne de caractères identifiant la description du fuseau horaire doit commencer par un caractère deux-points. Ainsi, on peut aussi écrire:

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

En tant que méthode alternative à la spécification de fuseaux horaires utilisant un chemin d'accès à un fichier de description, SUSv3 décrit le modèle POSIX. Dans ce format, une chaîne est définie comme suit:

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

stdest le nom du composant standard et celui de dstl'heure d'été. Chaque nom est composé de trois caractères ou plus. Il offsetest positif pour les fuseaux horaires situés à l'ouest du premier méridien et négatif pour ceux situés à l'est du méridien. Le décalage est ajouté à l'heure locale pour obtenir l'UTC (anciennement GMT). Les champs startet endheure indiquent quand les transitions standard / lumière du jour ont lieu.

Par exemple, dans l’est des États-Unis, l’heure standard est 5 heures plus tôt que UTC, et nous pouvons spécifier EST5EDTà la place de America/New_York. Toutefois, ces solutions de remplacement ne sont pas toujours reconnues, en particulier pour les zones situées en dehors des États-Unis, et il vaut mieux les éviter.

HP-UX (UNIX compatible SUSv3) utilise des règles textuelles /usr/lib/tztabet les noms POSIX tels que EST5EDT, CST6CDT, MST7MDT, PST8PDT. Le fichier comprend toutes les règles historiques de chaque fuseau horaire, semblables à la base de données Olson.

REMARQUE: Vous devriez être en mesure de trouver tous les fuseaux horaires en inspectant le répertoire suivant: /usr/share/zoneinfo.

JRFerguson
la source
ne sais pas si je me trompe, mais a l' exportair mieux que envcommande
insign
@JRFerguson - Si un fuseau horaire n'est pas inclus dans la liste, par exemple Las Vegas ou Nevada, quelles sont les alternatives pour valider l'heure?
Motivé le
@Motivated Si votre ville ou votre état n'est pas inclus, choisissez-en un qui utilise les mêmes informations de zone que le vôtre. Par exemple, je suis en Floride, où le fuseau horaire est le même que celui de New York. Mes machines sont donc synchronisées avec l'heure de New York.
JRFerguson le
1
@JRFerguson - Cela suppose que la personne connaisse les différents fuseaux horaires et puisse utiliser une alternative, par exemple New York, dans votre cas. Serait-ce la seule option? Par exemple, je ne vis pas en Europe et je ne connais pas les fuseaux horaires qui se chevauchent.
Motivé le
1
@ Motivé Vous pouvez utiliser quelque chose comme ce site pour vous aider à trouver d'autres points dans votre zone.
JRFerguson le
33

Vous pouvez le faire en manipulant la TZvariable d'environnement. Ce qui suit vous donnera l’heure locale pour US / Eastern, qui sera également assez malin pour gérer l’heure d’été lorsque cela fonctionne:

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

Le nom de la zone provient des fichiers et des répertoires à l'intérieur /usr/share/zoneinfo.

James Sneeringer
la source
17

Faites attention! Date crachera volontiers l'heure dans votre fuseau horaire ACTUEL, si vous lui attribuez un fuseau horaire qu'il ne reconnaît pas.

Regarde ça:

-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

Notez qu'il n'y a pas de fuseau horaire appelé EDT. En réalité,

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

résultats

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

Et cela fonctionne:

-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

Cependant, si votre ami habite dans le pays mystique de Gobbledygook et que ses informations de zone coïncident avec les vôtres, vous pouvez faire en sorte que la date soit affichée dans la zone de Gobbledygook. la zone ne lui est pas connue:

-bash-4.2$ TZ=Gobbledygook date
Wed Feb 18 19:37:36 Gobbledygook 2015
-bash-4.2$ echo $?
0
Mike S
la source
YMMV: sur ma machine MacOS / BSD, une TZchaîne malformée renvoie l'heure UTC.
Mark Hudson le
8
TODAY=$(TZ=":US/Eastern" date)
echo $TODAY
Lin
la source
6

La syntaxe de la date est arcane et sujette aux erreurs, ce qui complique tout appel en ligne de commande. J'ai donc écrit un petit script (je l'ai appelé worldtime ), qui imprimera l'heure spécifiée (ou actuelle) à partir du zome de l'heure de base (votre heure locale) dans d'autres fuseaux horaires et inversement.

C'est ici. Ajustez-le pour répondre à vos besoins, mettez-le dans votre chemin, et rendez-le exécutable.

#! / bin / sh
#
# Affiche l'heure spécifiée (ou actuelle) à partir de l'heure de base dans d'autres fuseaux horaires
# et l'inverse
#

# Fuseau horaire de base de / vers lequel convertir
TZBASE = Europe / Athènes

# Fuseaux horaires à afficher
# Voir / usr / share / zoneinfo / pour plus de noms
TZONES = 'UTC America / Amérique du Nord / New_York Europe / Londres Europe / Paris'

# Format d'affichage
FORMAT = '% H:% M (% p)% Z% a% m% b% Y'

si ["$ 1"]; ensuite
  time = "$ 1"
autre
  heure = `date +% T`
Fi

# Affiche l'heure du fuseau horaire spécifié dans la sortie spécifiée.
# fuseau horaire
afficher l'heure()
{
  TZIN = 1 $
  TZOUT = 2 $

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

pour tz en $ TZONES; faire
  showtime $ TZBASE $ tz
terminé

écho

pour tz en $ TZONES; faire
  showtime $ tz $ TZBASE
terminé

Diomidis Spinellis
la source
3

Vous avez souvent l’horodatage dans le fuseau horaire local et vous devez le convertir en tz distant. Cela peut être fait avec:

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

où:

America/Curacao - remote timezone
MSK - local timezone
dimcha
la source