webentwicklung-frage-antwort-db.com.de

Rails: Wie kann ich eine Datum/Uhrzeit-Zeichenfolge in eine bestimmte Zeitzone einlesen?

Ich benutze Rails 3.2 und Ruby 1.9.3 unter Debian. Ich habe eine App, die Datum, Uhrzeit und Zeitzone in Form von Zeichenfolgen über ein HTML-Formular erfasst. Etwas wie das:

start_date: "04-15-2010",
start_time: "10:00:00",
timezone: "Central Time (US & Canada)"

Ich möchte diese 3 Elemente in ein einziges Datum parsen, das in meiner Datenbank als UTC gespeichert wird. In diesem Fall würde die Startzeit um 7 Stunden verlängert, wenn sie sich in der UTC-Zeitzone befindet Die gespeicherte Zeit wäre 17:00 Uhr, wenn sie sich in der DB als UTC anstelle der empfangenen Zentralzeit befindet.

Ich habe so etwas versucht, um das Datum zu analysieren:

ActiveSupport::TimeZone[timezone].at DateTime.strptime("{ 2012-04-09 20:00:00 }", "{ %Y-%m-%d %H:%M:%S }").to_i

Ich kann die Zeitzone mit% Z jedoch nicht in die resultierende Zeit einbeziehen. Es wird entweder nicht geparst oder die Zeit wird als UTC und nicht als Zentralzeit interpretiert. Meine Frage ist also, wie man einen Datumsstring in eine bestimmte Zeitzone zwingt, ohne den Wert des tatsächlich gespeicherten Datums/der aktuellen Uhrzeit zu ändern. Ich möchte in der Lage sein, die Zeichenfolge in ein Datums-/Zeitobjekt zu parsen, das die richtige Zeitzone enthält zu diesem Zeitpunkt , damit zukünftige Zeitzonenumwandlungen genau sind. Ich habe überall nachgesehen und finde keinen Weg, dies zu tun. Es ist seltsam, da es so aussieht, als ob etwas mit Datumsangaben aus HTML-Formularen üblich ist. Danke für jede Hilfe.

35
Matt Schwartz

%Z ist der richtige Weg, um den Namen einer Zeitzone anzugeben. Hast du folgendes probiert?

date_and_time = '%m-%d-%Y %H:%M:%S %Z'
DateTime.strptime("04-15-2010 10:00:00 Central Time (US & Canada)",date_and_time)
17
0x4a6f4672

Versuche dies:

zone = "Central Time (US & Canada)"  

ActiveSupport::TimeZone[zone].parse("2013-04-03 17:47:00")
98
ryancheung

Verwenden Sie String#in_time_zone (Rails 4+)

Ich persönlich bevorzuge String#in_time_zone:

>> '22.09.1986 10:30'.in_time_zone('Central Time (US & Canada)')
# => Mon, 22 Sep 1986 10:30:00 CDT -05:00

Dadurch werden Datum und Uhrzeit in der Zeichenfolge in der angegebenen Zeitzone analysiert.

30
Artur Beljajev

Ich habe endlich den schmutzigen, aber definitiven Weg gefunden, dies zu tun.

Analysieren Sie den String zunächst mit normalem Ruby Time.strptime wie folgt:

time = Time.strptime('12 : 00 : PM', '%I : %M : %p')

Auf diese Weise erhalten Sie die geparste Zeit, aber noch nicht in der richtigen Zeitzone. Um dies zu beheben, konvertieren Sie die Zeit in eine String-Form und parsen sie mit der standardmäßigen ActiveSupport :: TimeZone # -Parse

Time.zone.parse(time.to_s)

Das Ergebnis ist ActiveSupport :: TimeWithZone, wobei unsere Zeit in die richtige Zeitzone geparst wird.

Der Grund, warum wir dies auf diese Weise tun müssen, ist, dass weder ActiveSupport :: TimeZone noch ActiveSupport :: TimeWithZone die strptime-Methode unterstützen. Wir müssen also die Zeit mit der Ruby-Striptime des Kerns analysieren, die keine Zeitzoneninformationen enthält, in ActiveSupport-Objekte in ein akzeptables Format konvertieren und dann erneut analysieren.

1
Phitherek_

Dies ist die Methode, die ich mir ausgedacht habe. Nicht das Schönste, aber es funktioniert. Erlaubt das Analysieren der Zeichenfolge in einem angegebenen Format und das Umwandeln in ein Format, das ich Time.zone.parse benötige.

class ActiveSupport::TimeZone
  def strptime(time, format='%m/%d/%Y')
    formatted = Time.strptime(time, format).strftime('%Y-%m-%d %T')
    parse(formatted)
  end
end

Dann können Sie etwas tun, was in einer anderen Frage erwähnt wurde, jedoch mit einem bestimmten Format:

zone = "Central Time (US & Canada)"  
ActiveSupport::TimeZone[zone].strptime('2013-04-03', '%Y-%m-%d')

Oder wenn Sie bereits eine Zeitzone eingestellt haben:

Time.zone = "Central Time (US & Canada)" 
Time.zone.strptime('01/13/2006')

Ich habe ein Standardformat von %m/%d/%Y verwendet, da dies meistens meine Benutzereingaben sind. Sie können dies an Ihre Bedürfnisse anpassen oder das Standardformat DateTime verwenden, das iso8601 (%FT%T%z) ist

1
ifightcrime

Konvertieren Sie ein bestimmtes Datumsformat in UTC.

ActiveSupport::TimeZone['UTC'].parse(Time.strptime('01/24/2019T16:10:16', "%m/%d/%YT%H:%M:%S").asctime)
0
DenisKo

Damit DateTime die Datumszeichenfolge verwenden und eine andere Zeitzone als UTC anhängen kann, ohne die Werte der Datumszeichenfolge zu ändern, verwenden Sie diese Einstellung. 

xx = DateTime.strptime("9/1/15 #{object.time_zone}", "%m/%d/%Y %Z")
0
Jon