2017-05-03 4 views
0

Dieses Problem hat mich für eine Weile verzehrt.Rails 5: DateTime-Objekt Zeitzone nicht korrekt konvertieren

Ich nehme ein Datum Zeit string:

[14] pry(#<EventsController>)> params[:event][:ended_at] 
=> "05/31/2017 2:00 PM" 

ich es in ein Datetime-Objekt konvertieren:

pry(#<EventsController>)> to_datetime = DateTime.strptime(params[:event][:ended_at], "%m/%d/%Y %H:%M %p") 
=> Wed, 31 May 2017 14:00:00 +0000 

Wenn ich die in_time_zone Methode auf dem to_datetime Objekt ausgeführt es gibt die falsche Zeit für pacific Zeitzone:

[16] pry(#<EventsController>)> to_datetime.in_time_zone("Pacific Time (US & Canada)") 
=> Wed, 31 May 2017 07:00:00 PDT -07:00 

Es sollte "2:00 PM" das gleiche lesen wie es eingegeben wird.

Wenn ich gehe zu Google und überprüfen, um zu sehen, ob „14.00.00 0.000“ die für die PDT Zeit korrekte Eingabe ist prüft es als richtig:

http://imgur.com/a/ZJ80F

Irgendwelche Hinweise darüber, warum es nicht korrekt konvertieren?

Antwort

1

der Fehler kommt, dass die ended_at von der Systemkonfiguration angenommen wird, dass in diesem Fall '+0000' ist, müssen Sie die ursprüngliche Zeitzone die ended_at ist.

irb(main):001:0> date = "05/31/2017 2:00 PM" 
=> "05/31/2017 2:00 PM" 
irb(main):002:0> to_datetime = DateTime.strptime(date, "%m/%d/%Y %H:%M %p") 
=> Wed, 31 May 2017 14:00:00 +0000 

Beachten Sie, dass dieses bereits als UTC eingestellt, da er durch das System der Zeitzone

irb(main):001:0> date = "05/31/2017 2:00 PM -0700" 
=> "05/31/2017 2:00 PM -0700" 
irb(main):002:0> to_datetime = DateTime.strptime(date, "%m/%d/%Y %H:%M %p %z") 
=> Wed, 31 May 2017 14:00:00 -0700 
irb(main):003:0> new_to_datetime = to_datetime.utc 
=> Wed, 31 May 2017 21:00:00 +0000 
irb(main):004:0> new_to_datetime.in_time_zone("Pacific Time (US & Canada)") 
=> Wed, 31 May 2017 14:00:00 PDT -07:00 

aktualisieren

@antonio ‚s Kommentar Erwähnung angenommen wurde 1 Stunde aus

irb(main):046:0> time = DateTime.strptime(date + " Pacific Time (US & Canada)", "%m/%d/%Y %H:%M %p %Z").class 
=> DateTime 
irb(main):047:0> time = DateTime.strptime(date + " Pacific Time (US & Canada)", "%m/%d/%Y %H:%M %p %Z") 
=> Wed, 31 May 2017 14:00:00 -0800 
irb(main):048:0> time.utc.class 
=> Time 

Wie Sie diese verschiedenen Klassen sehen, und das ist Zeichen von Problemen, was Sie tun können, ist Time anstelle von DateTime

irb(main):049:0> time = Time.strptime(date + " Pacific Time (US & Canada)", "%m/%d/%Y %H:%M %p %Z") 
=> 2017-05-31 14:00:00 -0700 
irb(main):050:0> time.class 
=> Time 
+0

Ich bin * fast * da. Allerdings habe ich einen Unterschied von einem Stundenunterschied. Die Strings, mit denen ich arbeite, enthalten nicht die '-0700', also muss ich sie mit der 'current_user' Zeitzone formatieren (aktuell" Pacific Time (USA & Canada) "): ' datetime_string = Parameter [: Ereignis] [: Started_at] + "" + Current_user.time_zone " ' to_datetime = DateTime.strptime (datetime_string, "% m /% d /% Y% H:% M% p% Z") ' Wenn ich sehe, wie es in der Konsole speichert, sehe ich 'Wed, 31. Mai 2017 20:00:00 UTC +00: 00' Welches ist 1PM und nicht 2PM wie die Zeichenfolge kam als. Was ist falsch daran, wie ich es mache? – Antonio

+0

die einzige Erklärung, die ich dafür habe, ist, dass, wenn Sie die anfängliche Umwandlung 'strptime' verwenden, die Sommerzeitänderung nicht feststellen. Ich empfehle Ihnen, 'time = Time.strptime (Datum +" Pacific Time (USA & Kanada) ","% m /% d /% Y% H:% M% p% Z ")' – zetacu

+0

Ich sah Ihre Bearbeitung, Ich erhalte keinen UTC-Offset, den Sie bei Ihrer Bearbeitung demonstrieren. Ich sehe, Ihre ist -0700 und meins zeigt +0000 '[2] pry (# )> datetime_string' ' => "31.05.2017 2:00 Uhr Pacific Time (USA und Kanada)" ' ' [3] pry (# )> Zeit = Zeit.Strptime (DatumZeichenfolge, "% m /% d /% Y% H:% M% p% Z") ' ' => 2017-05 -31 14:00:00 + 0000' – Antonio

0

Wenn wir bei Ihrem ersten Versuch aussehen:

pry(#<EventsController>)> to_datetime = DateTime.strptime(params[:event][:ended_at], "%m/%d/%Y %H:%M %p") 
=> Wed, 31 May 2017 14:00:00 +0000 

wir sehen dass "05/31/2017 2:00 PM" wird korrekt analysiert in UTC, daher die +0000 Offset.

Dann, wenn Sie die UTC-Zeit zu PDT konvertieren Sie eine -7 Stunden Anlegezeiteinstellmittel:

=> Wed, 31 May 2017 07:00:00 PDT -07:00 
# -------------------------------^^^^^^ 

und die 14:00:00 wird 07:00:00 weil 14 - 7 == 7.

Wenn Sie to_datetime wollen in der PDT sein, dann wäre es am einfachsten sein, so zu starten, indem Sie DateTime.strptime zu sagen, dass der Zeitstempel-String PDT ist:

no_tz  = '05/31/2017 2:00 PM' 
to_datetime = DateTime.strptime("#{no_tz} PDT", '%m/%d/%Y %H:%M %p %z') 
# ------------------------------^^^^^^^^^^^^^^^---------------------^^ 

Dann werden Sie erhalten die 14:00:00 PDT Sie suchen :

> to_datetime.iso8601 
=> "2017-05-31T14:00:00-07:00" 
# -------------^^------^^^^^^ 
+0

verwendet. Ich möchte, dass die DateTime in UTC gespeichert wird, so dass alle Benutzer nur ihre Zeitzone auswählen und bis zu ihrer Zeitzone UTC-Zeit angezeigt werden müssen. Welche Änderungen müsste ich an dem Code vornehmen, damit Benutzer den richtigen Zeitpunkt sehen können, wenn Benutzer ihre 'Time.zone' auswählen? – Antonio

+0

'to_datetime.in_time_zone ('UTC')' gibt Ihnen den Zeitstempel in UTC. –

Verwandte Themen