Ich bin mir nicht sicher, ob dies eine separate Frage sein sollte, aber wie konvertieren Sie zwischen einem Datum und einer Uhrzeit?
Andrew Grimm
8
Die akzeptierten und am besten bewerteten Antworten sind unter modernen Versionen von Ruby nicht mehr die genauesten. Siehe die Antworten von @theTinMan und @PatrickMcKenzie unten.
Phrogz
Antworten:
50
Sie benötigen zwei leicht unterschiedliche Konvertierungen.
Um von Time zu konvertieren , können DateTimeSie die Zeitklasse wie folgt ändern:
require 'date'classTimedef to_datetime# Convert seconds + microseconds into a fractional number of seconds
seconds = sec +Rational(usec,10**6)# Convert a UTC offset measured in minutes to one measured in a# fraction of a day.
offset =Rational(utc_offset,60*60*24)DateTime.new(year, month, day, hour, min, seconds, offset)endend
Ähnliche Anpassung Datum lassen Sie konvertieren DateTime zu Time .
classDatedef to_gm_time
to_time(new_offset,:gm)enddef to_local_time
to_time(new_offset(DateTime.now.offset-offset),:local)end
privatedef to_time(dest, method)#Convert a fraction of a day to a number of microseconds
usec =(dest.sec_fraction *60*60*24*(10**6)).to_iTime.send(method, dest.year, dest.month, dest.day, dest.hour, dest.min,
dest.sec, usec)endend
Beachten Sie, dass Sie zwischen Ortszeit und GM / UTC-Zeit wählen müssen.
Die beiden obigen Codefragmente stammen aus O'Reillys Ruby Cookbook . Ihre Richtlinie zur Wiederverwendung von Code erlaubt dies.
Dies wird bei 1.9 unterbrochen, wobei DateTime # sec_fraction die Anzahl der Millisekunden in einer Sekunde zurückgibt. Für 1.9 möchten Sie verwenden: usec = dest.sec_fraction * 10 ** 6
dkubb
185
require 'time'
require 'date'
t =Time.now
d =DateTime.now
dd =DateTime.parse(t.to_s)
tt =Time.parse(d.to_s)
+1 Dies ist möglicherweise nicht die effizienteste Ausführung, aber es funktioniert, ist präzise und sehr gut lesbar.
Walt Jones
6
Leider funktioniert das nur im Umgang mit Ortszeiten wirklich. Wenn Sie mit einer DateTime oder Time mit einer anderen Zeitzone beginnen, wird die Analysefunktion in eine lokale Zeitzone konvertiert. Sie verlieren im Grunde die ursprüngliche Zeitzone.
Bernard
6
Ab Ruby 1.9.1 behält DateTime.parse die Zeitzone bei. (Ich habe keinen Zugriff auf frühere Versionen.) Time.parse behält die Zeitzone nicht bei, da es den POSIX-Standard time_t darstellt, der meiner Meinung nach einen ganzzahligen Unterschied zur Epoche darstellt. Jede Konvertierung in Zeit sollte dasselbe Verhalten haben.
Anshul
1
Du hast recht. DateTime.parse funktioniert in 1.9.1, jedoch nicht in Time.parse. In jedem Fall ist es weniger fehleranfällig (konsistent) und wahrscheinlich schneller, DateTime.new (...) und Time.new (..) zu verwenden. Beispielcode finden Sie in meiner Antwort.
Bernard
1
Hallo @anshul. Ich impliziere nicht, dass ich sage :-). Zeitzoneninformationen werden bei Verwendung von Time.parse () nicht beibehalten. Es ist einfach zu testen. Ersetzen Sie in Ihrem obigen Code einfach d = DateTime.now durch d = DateTime.new (2010,01,01, 10,00,00, Rational (-2, 24)). tt zeigt nun das Datum d an, das in Ihre lokale Zeitzone konvertiert wurde. Sie können weiterhin Datumsarithmetik durchführen und alle bis auf die ursprünglichen tz-Informationen gehen verloren. Diese Informationen sind ein Kontext für das Datum und oft wichtig. Siehe hier: stackoverflow.com/questions/279769/…
Bernard
63
Als Update zum Stand des Ruby - Ökosystems Date, DateTimeund Timehat nun Methoden zu konvertieren zwischen den verschiedenen Klassen. Verwenden von Ruby 1.9.2+:
DateTime.to_time gibt eine DateTime zurück ... 1.9.3p327 :007 > ts = '2000-01-01 12:01:01 -0700' => "2000-01-01 12:01:01 -0700" 1.9.3p327 :009 > dt = ts.to_datetime => Sat, 01 Jan 2000 12:01:01 -0700 1.9.3p327 :010 > dt.to_time => Sat, 01 Jan 2000 12:01:01 -0700 1.9.3p327 :011 > dt.to_time.class => DateTime
Jesse Clark
Hoppla. Ich habe gerade festgestellt, dass dies ein Ruby on Rails-Problem ist, kein Ruby-Problem: stackoverflow.com/questions/11277454/… . Sie hatten sogar einen Fehler gegen diese Methode in der 2.x-Zeile und markierten sie "wird nicht behoben". Schreckliche Entscheidung IMHO. Das Rails-Verhalten unterbricht die zugrunde liegende Ruby-Schnittstelle vollständig.
Jesse Clark
12
Leider behalten die Funktionen DateTime.to_time, Time.to_datetimeund Time.parsedie Zeitzoneninformationen nicht bei. Während der Konvertierung wird alles in die lokale Zeitzone konvertiert. Datumsarithmetik funktioniert immer noch, aber Sie können die Datumsangaben nicht mit ihren ursprünglichen Zeitzonen anzeigen. Diese Kontextinformationen sind oft wichtig. Wenn ich beispielsweise möchte, dass Transaktionen während der Geschäftszeiten in New York ausgeführt werden, ziehe ich es wahrscheinlich vor, sie in ihren ursprünglichen Zeitzonen anzuzeigen, nicht in meiner lokalen Zeitzone in Australien (die 12 Stunden vor New York liegt).
Die folgenden Konvertierungsmethoden behalten diese tz-Informationen bei.
require 'date'# Create a date in some foreign time zone (middle of the Atlantic)
d =DateTime.new(2010,01,01,10,00,00,Rational(-2,24))
puts d# Convert DateTime to Time, keeping the original timezone
t =Time.new(d.year, d.month, d.day, d.hour, d.min, d.sec, d.zone)
puts t# Convert Time to DateTime, keeping the original timezone
d =DateTime.new(t.year, t.month, t.day, t.hour, t.min, t.sec,Rational(t.gmt_offset /3600,24))
puts d
Die Zeit ist kompliziert, aber es gibt keine Entschuldigung dafür, keine integrierte Konvertierung zwischen verschiedenen integrierten Zeitklassen bereitzustellen. Sie können eine RangeException auslösen, wenn Sie versuchen, ein UNIX time_t für 4713 BC abzurufen (obwohl ein negativer BigNum-Wert besser wäre), aber zumindest eine Methode dafür bereitstellen.
Mark Reed
1
Time#to_datetimescheint tz für mich zu bewahren:Time.local(0).to_datetime.zone #=> "-07:00"; Time.gm(0).to_datetime.zone #=> "+00:00"
Phrogz
@Phrogz UTC-Offset ist nicht dasselbe wie eine Zeitzone. Einer ist konstant, der andere kann sich zu verschiedenen Jahreszeiten für die Sommerzeit ändern. DateTime hat keine Zone, ignoriert die Sommerzeit. Die Zeit respektiert es, aber nur in der "lokalen" (Systemumgebung) TZ.
Andrew Vit
1
Hier ist mein Versuch, die Gordon Wilson-Lösung zu verbessern:
def to_time#Convert a fraction of a day to a number of microseconds
usec =(sec_fraction *60*60*24*(10**6)).to_i
t =Time.gm(year, month, day, hour, min, sec, usec)
t - offset.abs.div(SECONDS_IN_DAY)end
Sie erhalten die gleiche Zeit in UTC und verlieren die Zeitzone (leider)
Wenn Sie Ruby 1.9 haben, probieren Sie einfach die to_timeMethode aus
Bei solchen Konvertierungen sollte das Verhalten von Zeitzonen bei der Konvertierung von einem Objekt zum anderen berücksichtigt werden. Ich habe in diesem Stackoverflow- Beitrag einige gute Notizen und Beispiele gefunden .
Antworten:
Sie benötigen zwei leicht unterschiedliche Konvertierungen.
Um von
Time
zu konvertieren , könnenDateTime
Sie die Zeitklasse wie folgt ändern:Ähnliche Anpassung Datum lassen Sie konvertieren
DateTime
zuTime
.Beachten Sie, dass Sie zwischen Ortszeit und GM / UTC-Zeit wählen müssen.
Die beiden obigen Codefragmente stammen aus O'Reillys Ruby Cookbook . Ihre Richtlinie zur Wiederverwendung von Code erlaubt dies.
quelle
quelle
Als Update zum Stand des Ruby - Ökosystems
Date
,DateTime
undTime
hat nun Methoden zu konvertieren zwischen den verschiedenen Klassen. Verwenden von Ruby 1.9.2+:quelle
1.9.3p327 :007 > ts = '2000-01-01 12:01:01 -0700' => "2000-01-01 12:01:01 -0700" 1.9.3p327 :009 > dt = ts.to_datetime => Sat, 01 Jan 2000 12:01:01 -0700 1.9.3p327 :010 > dt.to_time => Sat, 01 Jan 2000 12:01:01 -0700 1.9.3p327 :011 > dt.to_time.class => DateTime
Leider behalten die Funktionen
DateTime.to_time, Time.to_datetime
undTime.parse
die Zeitzoneninformationen nicht bei. Während der Konvertierung wird alles in die lokale Zeitzone konvertiert. Datumsarithmetik funktioniert immer noch, aber Sie können die Datumsangaben nicht mit ihren ursprünglichen Zeitzonen anzeigen. Diese Kontextinformationen sind oft wichtig. Wenn ich beispielsweise möchte, dass Transaktionen während der Geschäftszeiten in New York ausgeführt werden, ziehe ich es wahrscheinlich vor, sie in ihren ursprünglichen Zeitzonen anzuzeigen, nicht in meiner lokalen Zeitzone in Australien (die 12 Stunden vor New York liegt).Die folgenden Konvertierungsmethoden behalten diese tz-Informationen bei.
Schauen Sie sich für Ruby 1.8 die Antwort von Gordon Wilson an . Es ist aus dem guten alten zuverlässigen Ruby Cookbook.
Für Ruby 1.9 ist es etwas einfacher.
Dies gibt Folgendes aus
Die vollständigen ursprünglichen DateTime-Informationen einschließlich der Zeitzone werden beibehalten.
quelle
Time#to_datetime
scheint tz für mich zu bewahren:Time.local(0).to_datetime.zone #=> "-07:00"; Time.gm(0).to_datetime.zone #=> "+00:00"
Hier ist mein Versuch, die Gordon Wilson-Lösung zu verbessern:
Sie erhalten die gleiche Zeit in UTC und verlieren die Zeitzone (leider)
Wenn Sie Ruby 1.9 haben, probieren Sie einfach die
to_time
Methode ausquelle
Bei solchen Konvertierungen sollte das Verhalten von Zeitzonen bei der Konvertierung von einem Objekt zum anderen berücksichtigt werden. Ich habe in diesem Stackoverflow- Beitrag einige gute Notizen und Beispiele gefunden .
quelle