Mam rekord foo
w bazie danych, który ma :start_time
i :timezone
atrybuty.
Na przykład :start_time
jest to czas UTC 2001-01-01 14:20:00
. Na przykład :timezone
jest to ciąg znaków America/New_York
.
Chcę utworzyć nowy obiekt Time z wartością, :start_time
ale którego strefa czasowa jest określona przez :timezone
. Nie chcę ładować, :start_time
a następnie konwertować do :timezone
, ponieważ Railsy będą sprytne i zaktualizują czas z UTC, aby był zgodny z tą strefą czasową.
Obecnie,
t = foo.start_time
=> 2000-01-01 14:20:00 UTC
t.zone
=> "UTC"
t.in_time_zone("America/New_York")
=> Sat, 01 Jan 2000 09:20:00 EST -05:00
Zamiast tego chcę zobaczyć
=> Sat, 01 Jan 2000 14:20:00 EST -05:00
to znaczy. Chcę zrobić:
t
=> 2000-01-01 14:20:00 UTC
t.zone = "America/New_York"
=> "America/New_York"
t
=> 2000-01-01 14:20:00 EST
Odpowiedzi:
Wygląda na to, że chcesz czegoś podobnego do
To mówi, że przekonwertuj ten czas lokalny (używając strefy) na utc. Jeśli masz
Time.zone
ustawione, możesz oczywiścieTo nie użyje strefy czasowej dołączonej do t - zakłada, że jest lokalna dla strefy czasowej, z której konwertujesz.
Jednym z skrajnych przypadków, przed którym należy się tutaj wystrzegać, są przejścia na czas letni: określony czas lokalny może nie istnieć lub może być niejednoznaczny.
źródło
Time.use_zone(self.timezone) { Time.zone.local_to_utc(t) }.localtime
Właśnie stanąłem przed tym samym problemem i oto, co mam zamiar zrobić:
Oto dokumentacja dotycząca asctime
źródło
asctime
jest to, że obniża wszelkie wartości podsekundowe (które zachowuje moja odpowiedź).Jeśli używasz Railsów, oto inna metoda na wzór odpowiedzi Erica Walsha:
źródło
.in_time_zone
do końca.Time.zone.now
czegoś, co jest najbliższe czasowi, w którym chcesz zmienić, zadziała?Po konwersji musisz dodać przesunięcie czasu do swojego czasu.
Najłatwiej to zrobić:
Nie jestem pewien, dlaczego chciałbyś to zrobić, chociaż prawdopodobnie najlepiej jest pracować z czasami tak, jak są zbudowane. Wydaje mi się, że pomocne byłoby wyjaśnienie, dlaczego należy przesunąć czas i strefy czasowe.
źródło
Time.in_time_zone
, wymagając odpowiednich części active_support:require 'active_support/core_ext/time'
Właściwie myślę, że musisz odjąć przesunięcie po konwersji, jak w:
źródło
Zależy od tego, gdzie zamierzasz wykorzystać ten czas.
Kiedy twój czas jest atrybutem
Jeśli czas jest używany jako atrybut, możesz użyć tego samego klejnotu date_time_attribute :
Kiedy ustawisz osobną zmienną
Użyj tego samego klejnotu date_time_attribute :
źródło
Szybka funkcja, którą wymyśliłem, aby rozwiązać tę pracę. Jeśli ktoś ma bardziej efektywny sposób na zrobienie tego, opublikuj go!
źródło
Założenie OP jest niepoprawne: „Nie chcę ładować: start_time, a następnie konwertować do: timezone, ponieważ Railsy będą sprytne i zaktualizują czas z UTC, aby był zgodny z tą strefą czasową.” Niekoniecznie jest to prawda, na co wskazuje udzielona tutaj odpowiedź.
źródło
t.zone
przedt.change
tym, co widzisz? A co po uruchomieniut.zone
pot.change
? A jakie parametryt.change
dokładnie przekazujesz ?Stworzyłem kilka metod pomocniczych, z których jedna robi to samo, o co prosi pierwotny autor posta w Ruby / Rails - Zmień strefę czasową czasu, bez zmiany wartości .
Udokumentowałem również kilka osobliwości, które zaobserwowałem, a także ci pomocnicy zawierają metody całkowicie ignorujące automatyczne oszczędzanie światła dziennego stosowane podczas konwersji czasu, które nie są dostępne od razu po zainstalowaniu we frameworku Rails:
Przykłady, które można wypróbować na konsoli railsowej lub w skrypcie ruby po umieszczeniu powyższych metod w klasie lub module:
Mam nadzieję że to pomoże.
źródło
Oto inna wersja, która działała lepiej dla mnie niż obecne odpowiedzi:
Przenosi przez nanosekundy używając „% N”. Jeśli potrzebujesz innej precyzji, zobacz to odniesienie do strftime .
źródło
Spędziłem również sporo czasu zmagając się z TimeZones i po majstrowaniu przy Rubim 1.9.3 zdałem sobie sprawę, że nie musisz konwertować na nazwany symbol strefy czasowej przed konwersją:
Oznacza to, że możesz skupić się na uzyskaniu odpowiedniego ustawienia czasu najpierw w wybranym regionie, tak jak byś o tym pomyślał (przynajmniej w mojej głowie dzielę to w ten sposób), a następnie przekonwertować na koniec do strefy chcesz zweryfikować swoją logikę biznesową.
Działa to również dla Rubiego 2.3.1.
źródło