Jak mogę ustawić datę na wyjście z innej strefy czasowej?

115

Mam serwer działający z ustawioną strefą czasową UTC. Wyglądało na to, że była to ogólnie dobra praktyka (popraw mnie, jeśli się mylę).

W każdym razie jeden z serwerów, z którymi się łączę, w celu obsługi scpplików, działa EDTi przechowuje pliki, które muszę skopiować w formacie/path/to/filename/data20120913

Patrzyłem na próbę rsyncplików przy użyciu czegoś takiego jak -mtime -1flaga find dla plików zmodyfikowanych w ostatnim dniu, ale nie miałem szczęścia.

Nie mam nic przeciwko zwykłemu scpkopiowaniu pliku z bieżącego dnia, ale teraz jest 4-godzinne okno, w którym uruchomienie date +%Y%m%dda inny dzień na każdym serwerze, co trochę mnie wkurza.

Przeglądając man date, widzę, że mogę uzyskać wynik czasu jako UTC, ale nie widzę sposobu, aby uzyskać wynik jako kolejną strefę czasową, taką jakEDT

Przypuszczam, że mógłbym również użyć czegoś takiego jak GNUrozszerzenie daty, date -d 20100909 +%saby uzyskać datę w sekundach od epoki, zastosować ręczne 4 * 60 * 60obliczenia sekundowe i zobaczyć renderowanie tego jako daty - ale wtedy, gdy zacznie się czas letni, będzie jeszcze godzina wolnego .

Czy istnieje prostszy sposób na wyświetlenie daty w YYYYMMDDformacie dla EDTserwera, który jest ustawiony UTC?

cwd
źródło
EDT nie jest uznaną strefą czasową - przynajmniej w Linuksie. Zobacz moje „Uważaj!” odpowiedz poniżej na całą brzydką historię. Jeśli EDT jest rozpoznawany przez twoją markę * NIX, powinieneś zachować ostrożność i dokładnie sprawdzić ciąg strefy czasowej.
Mike S

Odpowiedzi:

175

Możesz ustawić strefę czasową na czas trwania zapytania, a zatem:

TZ=America/New_York date

Zwróć uwagę na spację między TZustawieniem a datepoleceniem. W rcpowłoce podobnej do Bourne'a i podobnej ustawia TZzmienną tylko dla wiersza poleceń. W innych powłok ( csh, tcsh, fish), zawsze można użyć envzamiast polecenia:

env TZ=America/New_York date

tl; dr

W systemach Linux. strefy czasowe są zdefiniowane w plikach w /usr/share/zoneinfokatalogu. Struktura ta jest często nazywana „bazą danych Olson”, aby uhonorować jej twórcę.

Reguły dla każdej strefy czasowej są zdefiniowane jako wiersze pliku tekstowego, które są następnie kompilowane do pliku binarnego. Tak skompilowane linie określają nazwę strefy; zakres danych i czas obowiązywania strefy; przesunięcie względem UTC dla czasu standardowego; oraz notacja określająca sposób przejścia na czas letni i zimowy, jeśli dotyczy.

Na przykład katalog „Ameryka” zawiera informacje wymagane dla Nowego Jorku w America/New_Yorkużytym pliku powyżej.

Uwaga: specyfikacja nieistniejącej strefy (nazwa pliku) jest dyskretnie ignorowana i podawane są czasy UTC. Na przykład zgłasza niepoprawny czas:

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

Pojedyncza specyfikacja UNIX, wersja 3, znana jako SUSv3 lub POSIX-2001, zauważa, że ​​dla przenośności ciąg znaków identyfikujący opis strefy czasowej powinien zaczynać się od dwukropka. Zatem możemy również napisać:

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

Jako alternatywna metoda dla specyfikacji stref czasowych przy użyciu ścieżki do pliku opisu, SUSv3 opisuje model POSIX. W tym formacie ciąg jest zdefiniowany jako:

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

gdzie stdjest standardową nazwą komponentu i dsttą, która zachowuje czas letni. Każda nazwa składa się z trzech lub więcej znaków. offsetJest pozytywna dla stref czasowych na zachód od głównego południka i negatywne dla tych na wschód od południka. Przesunięcie jest dodawane do czasu lokalnego w celu uzyskania UTC (wcześniej znanego jako GMT). Pola starti endczas wskazują, kiedy występują przejścia standardowe / dzienne.

Na przykład we wschodnich Stanach Zjednoczonych standardowy czas jest o 5 godzin wcześniejszy niż UTC, a EST5EDTzamiast niego możemy podać America/New_York. Te alternatywy nie zawsze są jednak rozpoznawane, szczególnie w strefach poza Stanami Zjednoczonymi i najlepiej ich unikać.

HP-UX (system UNIX zgodny z SUSv3) używa reguł tekstowych /usr/lib/tztabi nazw POSIX, takich jak EST5EDT, CST6CDT, MST7MDT, PST8PDT. Plik zawiera wszystkie reguły historyczne dla każdej strefy czasowej, podobnie jak baza danych Olson.

UWAGA: Powinieneś być w stanie znaleźć wszystkich stref czasowych, sprawdzając następującym katalogu: /usr/share/zoneinfo.

JRFerguson
źródło
nie jestem pewien, czy się mylę, ale exportwygląda lepiej niż envrozkaz
insign
@JRFerguson - Jeśli strefa czasowa nie jest uwzględniona na liście, np. Las Vegas lub Nevada, jakie są alternatywy w sprawdzaniu czasu?
Zmotywowany
@ Zmotywowany Jeśli Twoje miasto lub państwo nie jest uwzględnione, wybierz takie, które używa tych samych informacji o strefie co twoje. Na przykład jestem na Florydzie, która używa tej samej strefy czasowej co Nowy Jork, więc moje maszyny synchronizują się z czasem nowojorskim.
JRFerguson
1
@ JRFerguson - Zakłada się, że dana osoba zna różne strefy czasowe i może w twoim przypadku skorzystać z alternatywy, np. Nowy Jork. Czy to byłaby jedyna opcja? Na przykład nie mieszkam w Europie i nie będę znać nakładających się stref czasowych.
Zmotywowany
1
@Motivated Możesz użyć czegoś takiego jak ta strona, aby pomóc ci znaleźć inne punkty w swojej strefie.
JRFerguson
33

Możesz to zrobić, manipulując TZzmienną środowiskową. Poniższe informacje przedstawiają czas lokalny dla US / Eastern, który będzie również wystarczająco inteligentny, aby poradzić sobie z czasem letnim:

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

Nazwa strefy pochodzi z plików i katalogów w środku /usr/share/zoneinfo.

James Sneeringer
źródło
17

Bądź ostrożny! Data szczęśliwie wypluje czas w twojej AKTUALNEJ strefie czasowej, jeśli nadasz jej strefę czasową, której nie rozpozna.

Spójrz na to:

-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

Pamiętaj, że nie ma strefy czasowej o nazwie EDT. Prawdę powiedziawszy,

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

zwroty

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

I to działa:

-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

Jeśli jednak twój przyjaciel mieszka w tajemniczej krainie Gobbledygook, a informacje o jego strefie pokrywają się z twoją, możesz podać datę i godzinę w strefie Gobbledygook, a on chętnie zrobi to, gdy nie będzie wartości wyjścia, aby poinformować cię, że strefa nie jest mu znana:

-bash-4.2$ TZ=Gobbledygook date
Wed Feb 18 19:37:36 Gobbledygook 2015
-bash-4.2$ echo $?
0
Mike S.
źródło
YMMV: na moim komputerze MacOS / BSD źle sformułowany TZciąg zwraca czas UTC.
Mark Hudson,
8
TODAY=$(TZ=":US/Eastern" date)
echo $TODAY
Lin
źródło
6

Termin składnia jest tajemna i podatne na błędy, które sprawia, że wywołanie z linii poleceń ból. Dlatego napisałem mały skrypt (nazwałem go worldtime ), który wydrukuje określony (lub bieżący) czas z podstawowego czasu zome (twojego lokalnego) w niektórych innych strefach czasowych i na odwrót.

Oto jest. Dostosuj go do swoich potrzeb, umieść na swojej ścieżce i spraw, aby był wykonywalny.

#! / bin / sh
#
# Wydrukuj określony (lub bieżący) czas z czasu bazowego w innych strefach czasowych
# i odwrotnie
#

# Podstawowa strefa czasowa z / na którą należy przekonwertować
TZBASE = Europa / Ateny

# Strefy czasowe do wyświetlenia
# Zobacz / usr / share / zoneinfo /, aby uzyskać więcej nazw
TZONES = 'UTC America / Los_Angeles America / New_York Europe / London Europe / Paris'

# Format wyswietlania
FORMAT = „% H:% M (% p)% Z% a% m% b% Y”

jeśli [„$ 1”]; następnie
  czas = „1 USD”
jeszcze
  czas = `data +% T`
fi

# Pokaż czas z określonej strefy czasowej wejścia na określonym wyjściu
# strefa czasowa
czas na przedstawienie()
{
  TZIN = 1 USD
  TZOUT = 2 USD

  TZ = $ TZOUT data - data = 'TZ = "' $ TZIN '" "" $ czas "+" $ czas $ TZIN to $ TZOUT $ FORMAT "
}

dla tz w $ TZONES; zrobić
  showtime $ TZBASE $ tz
gotowy

Echo

dla tz w $ TZONES; zrobić
  showtime $ tz $ TZBASE
gotowy

Diomidis Spinellis
źródło
3

Często masz sygnaturę czasową w lokalnej strefie czasowej i musisz przekonwertować ją na zdalny tz. Można to zrobić za pomocą:

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

gdzie:

America/Curacao - remote timezone
MSK - local timezone
dimcha
źródło