web-dev-qa-db-fra.com

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

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 (veuillez me corriger si je me trompe).

Quoi qu'il en soit, l'un des serveurs auxquels je me connecte, afin de scp fichiers, s'exécute sur EDT et stocke les fichiers que je dois copier au format /path/to/filename/data20120913

J'ai essayé de rsync fichiers en utilisant quelque chose comme find's -mtime -1 drapeau pour les fichiers modifiés le dernier jour, mais je n'ai pas eu de chance.

Cela ne me dérange pas d'utiliser simplement scp pour copier le fichier du jour en cours, mais en ce moment il y a une fenêtre de 4 heures où exécuter date +%Y%m%d donnera une journée différente sur chaque serveur et cela me dérange un peu.

En regardant à travers man date Je vois que je peux avoir la sortie de temps en tant que UTC, mais je ne vois pas de moyen de la faire sortir comme un autre fuseau horaire comme EDT

Je suppose que je pourrais également utiliser quelque chose comme l'extension de date GNUdate -d 20100909 +%s pour obtenir la date en secondes de l'époque, appliquez un manuel 4 * 60 * 60 deuxième calcul, et voir comment le rendre sous forme de date - mais quand l'heure d'été commencera, ce sera encore une heure de repos.

Existe-t-il un moyen plus simple de sortir la date au format YYYYMMDD pour EDT sur un serveur défini sur UTC?

119
cwd

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

TZ=America/New_York date

Notez l'espace entre le paramètre TZ et la commande date. Dans Bourne-like et rc- comme Shell, cela définit la variable TZ uniquement pour la ligne de commande. Dans d'autres shells (csh, tcsh, fish), vous pouvez toujours utiliser la commande env à la place:

env TZ=America/New_York date

tl; dr

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

Les règles pour 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 à UTC pour l'heure standard; et la notation pour définir comment la transition vers et depuis l'heure d'été se produit, le cas échéant.

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

Attention, la spécification d'une zone inexistante (nom de fichier) est silencieusement 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, connue sous le nom de SUSv3 ou POSIX-2001, note que pour la portabilité, la chaîne de caractères qui identifie la description du fuseau horaire doit commencer par un caractère deux-points. Ainsi, nous pouvons également écrire:

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

Comme méthode alternative à la spécification des fuseaux horaires en 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:

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

std est le nom du composant standard et dst est celui de l'heure d'été. Chaque nom se compose de trois caractères ou plus. Le offset est positif pour les fuseaux horaires à l'ouest du méridien principal et négatif pour ceux à l'est du méridien. Le décalage est ajouté à l'heure locale pour obtenir l'UTC (anciennement GMT). Les champs d'heure start et end indiquent quand les transitions standard/lumière du jour se produisent.

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 au lieu de America/New_York. Cependant, ces alternatives ne sont pas toujours reconnues, en particulier pour les zones en dehors des États-Unis, et il vaut mieux les éviter.

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

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

186
JRFerguson

Vous pouvez le faire en manipulant la variable d'environnement TZ. Les informations suivantes vous donneront l'heure locale pour les États-Unis/l'Est, qui sera également assez intelligente pour gérer l'heure d'été lorsque cela se produit:

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

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

33
James Sneeringer

Faites attention! La date crachera volontiers l'heure dans votre fuseau horaire actuel, si vous lui donnez un fuseau horaire qu'elle 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*"

retour

/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 vit dans le pays mystique de Gobbledygook et que ses informations de zone coïncident avec les vôtres, vous pouvez avoir la date et l'heure dans la zone de Gobbledygook et il sera heureux de le faire avec une valeur de sortie nulle pour vous faire savoir que le 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
20
Mike S
TODAY=$(TZ=":US/Eastern" date)
echo $TODAY
9
Lin

La syntaxe date est obscure et sujette aux erreurs, ce qui rend une invocation en ligne de commande difficile. J'ai donc écrit un petit script (je l'ai nommé worldtime), qui imprimera l'heure spécifiée (ou actuelle) à partir du zome de l'heure de base (votre heure locale) dans certains autres fuseaux horaires et l'inverse.

C'est ici. Ajustez-le en fonction de vos besoins, mettez-le sur votre chemin et rendez-le exécutable.

 #!/bin/sh 
 # 
 # Imprimer 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 à partir duquel/vers lequel convertir 
 TZBASE = Europe/Athènes 
 
 # Fuseaux horaires à afficher 
 # Voir/usr/share/zoneinfo/pour plus de noms 
 TZONES = 'UTC America/Los_Angeles America/New_York Europe/London Europe/Paris' 
 
 # Format d'affichage 
 FORMAT = '% H:% M (% p)% Z% a% m% b% Y' 
 
 Si ["$ 1"]; puis 
 heure = "$ 1" 
 sinon 
 heure = `date +% T` 
 fi 
 
 # Affiche l'heure à partir du fuseau horaire d'entrée spécifié dans la sortie spécifiée 
 # fuseau horaire 
 showtime () 
 {
 TZIN = 1 $ 
 TZOUT = 2 $ 
 
 TZ = $ TZOUT date --date = 'TZ = "' $ TZIN '"' "$ time" + "$ time $ TZIN est $ TZOUT $ FORMAT" 
} 
 
 pour tz en $ TZONES; 
 showtime $ TZBASE $ tz 
 done 
 
 echo 
 
 for tz in $ TZONES; faire 
 showtime $ tz $ TZBASE 
 fait 
 
7
Diomidis Spinellis

Souvent, vous avez un horodatage dans le fuseau horaire local et vous devez le convertir en tz distant. Cela peut se faire avec:

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

où:

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