Konwertuj UTC na czas lokalny w Rails 3

95

Mam problem z konwersją czasu UTC Timelub TimeWithZoneczasu lokalnego w Rails 3.

Powiedzmy, że momentto jakaś Timezmienna w UTC (np moment = Time.now.utc.). Jak przestawić się momentna moją strefę czasową, dbając o czas letni (tj. Używając EST / EDT)?

Dokładniej, chciałbym wydrukować „Poniedziałek 14 marca, 9:00”, jeśli godzina odpowiada dzisiejszej godzinie 9:00 EDT i „Poniedziałek 7 marca, 9:00”, jeśli w ostatni poniedziałek był to 9:00 czasu wschodniego.

Mam nadzieję, że jest inny sposób?

Edycja : Najpierw pomyślałem, że „EDT” powinno być rozpoznawalną strefą czasową, ale „EDT” nie jest rzeczywistą strefą czasową, bardziej przypomina stan strefy czasowej. Na przykład nie miałoby sensu prosić Time.utc(2011,1,1).in_time_zone("EDT"). Jest to trochę zagmatwane, ponieważ „EST” to rzeczywista strefa czasowa, używana w kilku miejscach, w których nie jest używany czas letni i obowiązuje przez cały rok (UTC-5).

Marc-André Lafortune
źródło

Odpowiedzi:

113

Railsy mają swoje własne nazwy. Zobacz je z:

rake time:zones:us

Możesz także biegać rake time:zones:allwe wszystkich strefach czasowych. Aby zobaczyć więcej zadań prowizji związanych ze strefami:rake -D time

Tak więc, aby przejść na EST, automatycznie przygotowuje obsługę DST:

Time.now.in_time_zone("Eastern Time (US & Canada)")
Zabba
źródło
21
Jak można automatycznie używać strefy czasowej dla użytkownika uzyskującego dostęp do aplikacji internetowej?
dmonopoly
Jedyny sposób, w jaki znalazłem, to JavaScript, a następnie przekazanie go z powrotem na serwer. (new Date()).getTimeZoneOffset(). Ale jest to dość niekonsekwentne, więc ten facet wydaje się, że napisał swój własny: onlineaspect.com/2007/06/08/ ...
Duke
2
automatycznie dodaj strefę czasową do wszystkich dat w ActiveRecord - config.time_zone = 'Czas wschodni (USA i Kanada)' - w config / application.rb
idrinkpabst
Aktualizacja: właściciel połączonego rozwiązania JS wskazuje na nowsze rozwiązanie: pellepim.bitbucket.org/jstz
Miles
@dmonopoly możesz ustawić strefę czasową w konfiguracji aplikacji, config.time_zone = 'Wellington'a następnie użyć Time.current (co jest odpowiednikiem time.now, ale użyłeś ustawionej strefy czasowej)
Sean
116

Time#localtime poda czas w bieżącej strefie czasowej maszyny, na której działa kod:

> moment = Time.now.utc
  => 2011-03-14 15:15:58 UTC 
> moment.localtime
  => 2011-03-14 08:15:58 -0700 

Aktualizacja: jeśli chcesz dostosować się do określonych stref czasowych, a nie własnej, jesteś na dobrej drodze. Jednak zamiast martwić się o EST vs EDT, po prostu przejdź do ogólnej strefy czasu wschodniego - będzie wiedzieć na podstawie dnia, czy jest to EDT czy EST:

> Time.now.utc.in_time_zone("Eastern Time (US & Canada)")
  => Mon, 14 Mar 2011 11:21:05 EDT -04:00 
> (Time.now.utc + 10.months).in_time_zone("Eastern Time (US & Canada)")
  => Sat, 14 Jan 2012 10:21:18 EST -05:00 
Dylan Markow
źródło
To jest początek. Jak mogę ustawić aktualną strefę czasową (ponieważ nie jestem nawet pewien, gdzie aplikacja będzie hostowana, serwer może znajdować się w innej strefie czasowej niż ta, której należy użyć).
Marc-André Lafortune
6
Metoda „czasu lokalnego” jest fajna, ale strefa czasowa komputera, na którym działa kod, nie jest tak pomocna, jak strefa czasowa użytkownika uzyskującego dostęp do aplikacji internetowej. (Jak wspomniano tutaj: stackoverflow.com/questions/6003491/rails-3-user-timezones/ ... ) Jak można uzyskać strefę czasową dla użytkownika uzyskującego dostęp do aplikacji internetowej?
dmonopoly
@daze Wyobrażam sobie, że możesz ustawić dla swoich użytkowników opcję wyboru stref czasowych, a następnie użyć tej in_time_zonemetody z ich strefą czasową.
Dylan Markow
1
Dzięki, metoda czasu lokalnego jest dokładnie tym, czego potrzebowałem.
Bob
Time.now.localtimedziała na normalnej sesji irb, ale kiedy próbuję go uruchomić na komputerze w strefie czasowej UTC, nie działa.
Ava
15

Można go łatwo skonfigurować za pomocą lokalnej strefy systemu, wystarczy dodać to w pliku application.rb

config.time_zone = Time.now.zone

Następnie szyny powinny pokazywać znaczniki czasu w Twoim czasie lokalnym lub możesz użyć czegoś takiego jak ta instrukcja, aby uzyskać czas lokalny

Post.created_at.localtime
jacr1614
źródło
15

W rzeczywistości istnieje niezły klejnot, do local_timektórego dzwoni basecamp, który robi to wszystko tylko po stronie klienta, jak sądzę:

https://github.com/basecamp/local_time

Mahatmanich
źródło
To działa najlepiej. Znamy już zapisany czas, sposób pokazania go użytkownikowi w formacie najlepiej moim zdaniem zrobić po stronie klienta i to robi.
Neeraj Shukla
1

Nie wiem dlaczego, ale w moim przypadku nie działa to w sposób sugerowany wcześniej. Ale to działa tak:

Time.now.change(offset: "-3000")

Oczywiście musisz zmienić offsetwartość na swoją.

Seybo Glaux
źródło
0

Jeśli faktycznie robisz to tylko dlatego, że chcesz uzyskać strefę czasową użytkownika, wszystko, co musisz zrobić, to zmienić strefę czasową w sobie config/applications.rb.

Lubię to:

Railsy domyślnie zapisują Twój czas w UTC, nawet jeśli określisz aktualną strefę czasową.

config.time_zone = "Singapore"

Więc to wszystko, co musisz zrobić i jesteś gotowy do pracy.

tamaladrain
źródło