Как мне сделать так, чтобы `date` выводила время из другого часового пояса?

115

У меня работает сервер с часовым поясом UTC. Казалось, что это в целом хорошая практика (пожалуйста, поправьте меня, если я ошибаюсь).

Во всяком случае, один из серверов, к которым я подключаюсь, для scpфайлов работает EDTи хранит файлы, которые мне нужно скопировать в формате/path/to/filename/data20120913

Я посмотрел на попытку rsyncфайлов, используя что-то вроде -mtime -1флага find для файлов, измененных в последний день, но мне не повезло.

Я не возражаю против того, scpчтобы просто использовать для копирования файл текущего дня, но на данный момент есть 4-часовое окно, в котором запуск date +%Y%m%dдаст разные дни на каждом сервере, и это немного меня беспокоит.

Просматривая, man dateя вижу, что у меня может быть вывод времени как UTC, но я не вижу способа, чтобы он выводился как другой часовой пояс, напримерEDT

Я полагаю, что я мог бы также использовать что-то вроде GNUрасширения даты, date -d 20100909 +%sчтобы получить дату в секундах от эпохи, применить ручной 4 * 60 * 60подсчет секунд и посмотреть, как это будет выглядеть как дата - но тогда, когда наступит дневное время, все равно будет час ,

Есть ли более простой способ вывода даты в YYYYMMDDформате для EDTна сервере, который установлен в UTC?

УХО
источник
EDT не является признанным часовым поясом - по крайней мере, в Linux. Смотрите мой "Будь осторожен!" ответ ниже для всей ужасной истории. Если EDT распознается на вашем бренде * NIX, вы все равно должны проявлять осторожность и перепроверить строку часового пояса.
Майк С

Ответы:

175

Вы можете установить часовой пояс для продолжительности запроса, таким образом:

TZ=America/New_York date

Обратите внимание на пробел между TZнастройкой и dateкомандой. В Bourne-like и-like rcshell, который устанавливает TZпеременную только для командной строки. В других оболочках ( csh, tcsh, fish), вы всегда можете использовать envкоманду вместо:

env TZ=America/New_York date

ТЛ; др

В системах Linux. часовые пояса определяются в файлах в /usr/share/zoneinfoкаталоге. Эту структуру часто называют «базой данных Олсона», чтобы почтить ее основателя.

Правила для каждого часового пояса определяются как строки текстового файла, которые затем компилируются в двоичный файл. Скомпилированные строки определяют имя зоны; диапазон данных и время, в течение которого применяется зона; смещение от UTC для стандартного времени; и примечание для определения того, как происходит переход на летнее время и обратно, если это применимо.

Например, каталог «Америка» содержит необходимую информацию для Нью-Йорка в указанном выше файле America/New_York.

Помните, что спецификация несуществующей зоны (имя файла) игнорируется и сообщается время UTC. Например, это сообщает о неправильном времени:

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

В Единой спецификации UNIX версии 3, известной как SUSv3 или POSIX-2001, отмечается, что для переносимости строка символов, которая идентифицирует описание часового пояса, должна начинаться с символа двоеточия. Таким образом, мы также можем написать:

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

В качестве альтернативного метода спецификации часовых поясов, использующего путь к файлу описания, SUSv3 описывает модель POSIX. В этом формате строка определяется как:

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

где std- стандартное имя компонента и dstлетнее. Каждое имя состоит из трех или более символов. Это offsetположительно для часовых поясов к западу от основного меридиана и отрицательно для тех к востоку от меридиана. Смещение добавляется к местному времени, чтобы получить UTC (ранее известное как GMT). startИ endполя времени указывают , когда происходят стандарт / дневного света переходы.

Например, в восточной части Соединенных Штатов стандартное время на 5 часов раньше, чем в формате UTC, и мы можем указать EST5EDTвместо America/New_York. Однако эти альтернативы не всегда признаются, особенно для зон за пределами Соединенных Штатов, и их лучше избегать.

HP-UX (UNIX, совместимый с SUSv3) использует текстовые правила /usr/lib/tztabи имена POSIX, такие как EST5EDT, CST6CDT, MST7MDT, PST8PDT. Файл включает в себя все исторические правила для каждого часового пояса, родственные базе данных Олсона.

Примечание: Вы должны быть в состоянии найти все часовые пояса, проверив следующий каталог: /usr/share/zoneinfo.

JRFerguson
источник
не уверен, если я ошибаюсь, но exportвыглядит лучше, чем envкоманда
insign
@JRFerguson - Если часовой пояс не включен в список, например, Лас-Вегас или Невада, каковы альтернативы при проверке времени?
мотивировано
@ Мотивированный Если ваш город или штат не включены, выберите тот, который использует ту же информацию о зоне, что и ваша. Например, я во Флориде, где используется тот же часовой пояс, что и в Нью-Йорке, поэтому мои машины синхронизируются с нью-йоркским временем.
JRFerguson
1
@JRFerguson - это предполагает, что человек знает о различных часовых поясах и может использовать альтернативу, например, Нью-Йорк в вашем случае. Это будет единственный вариант? Например, я не живу в Европе и не знаю перекрывающихся часовых поясов.
мотивировано
1
@ Мотивированный Вы можете использовать что-то вроде этого сайта, чтобы помочь вам найти другие точки в вашей зоне.
JRFerguson
33

Вы можете сделать это, манипулируя TZпеременной окружения. Следующее даст вам местное время для США / Восточной, которое также будет достаточно умным для обработки DST, когда это происходит:

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

Название зоны происходит из файлов и каталогов внутри /usr/share/zoneinfo.

Джеймс Снерингер
источник
17

Быть осторожен! Дата с радостью покажет время в вашем текущем часовом поясе, если вы дадите ему часовой пояс, который он не распознает.

Проверь это:

-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

Обратите внимание, что нет часового пояса с именем EDT. Собственно говоря,

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

возвращается

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

И это работает:

-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

Однако, если ваш друг живет в мистической стране Gobbledygook, и информация о его зоне совпадает с вашей собственной, вы можете указать дату и время в зоне Gobbledygook, и он с радостью сделает это с нулевым значением выхода, чтобы вы знали, что зона ему не известна:

-bash-4.2$ TZ=Gobbledygook date
Wed Feb 18 19:37:36 Gobbledygook 2015
-bash-4.2$ echo $?
0
Майк С
источник
YMMV: в моем окне MacOS / BSD искаженная TZстрока возвращает время UTC.
Марк Хадсон
6

Дата синтаксис аркана и подвержены ошибкам, что делает командную строку вызов боли. Поэтому я написал небольшой скрипт (я назвал его worldtime ), который будет печатать указанное (или текущее) время из базового часового пояса (вашего локального) в некоторых других часовых поясах и наоборот.

Вот. Настройте его в соответствии с вашими потребностями, поместите его на свой путь и сделайте его исполняемым.

#! / Bin / ш
#
# Распечатать указанное (или текущее) время из базового времени в других часовых поясах
# и обратное
#

# Базовый часовой пояс из / в который нужно конвертировать
TZBASE = Europe / Athens

# Часовые пояса для отображения
# Смотрите / usr / share / zoneinfo / для большего количества имен
TZONES = 'UTC America / Los_Angeles America / New_York Europe / London Europe / Paris'

# Формат отображения
ФОРМАТ = '% H:% M (% p)% Z% a% m% b% Y'

if ["$ 1"]; тогда
  время = "$ 1"
еще
  время = `дата +% T`
фи

# Показать время из указанного входного часового пояса в указанном выходе
# часовой пояс
время для шоу()
{
  = $ Цин 1
  TZOUT = $ 2

  TZ = $ TZOUT date --date = 'TZ = "' $ TZIN '"' "$ time" + "$ time $ TZIN - это $ TZOUT $ FORMAT"
}

для tz в $ TZONES; делать
  showtime $ TZBASE $ tz
сделанный

эхо

для tz в $ TZONES; делать
  showtime $ tz $ TZBASE
сделанный

Диомидис Спинеллис
источник
3

Часто у вас есть временная метка в местном часовом поясе, и вам нужно преобразовать ее в удаленный tz. Это можно сделать с помощью:

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

где:

America/Curacao - remote timezone
MSK - local timezone
dimcha
источник