Wie konvertiert man in Ruby zwischen einem DateTime- und einem Time-Objekt?
Wie konvertiert man in Ruby zwischen einem DateTime- und einem Time-Objekt?
Antworten:
Sie benötigen zwei leicht unterschiedliche Konvertierungen.
Um von Time
zu konvertieren , können DateTime
Sie die Zeitklasse wie folgt ändern:
require 'date'
class Time
def 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)
end
end
Ähnliche Anpassung Datum lassen Sie konvertieren DateTime
zu Time
.
class Date
def to_gm_time
to_time(new_offset, :gm)
end
def to_local_time
to_time(new_offset(DateTime.now.offset-offset), :local)
end
private
def 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_i
Time.send(method, dest.year, dest.month, dest.day, dest.hour, dest.min,
dest.sec, usec)
end
end
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.
require 'time'
require 'date'
t = Time.now
d = DateTime.now
dd = DateTime.parse(t.to_s)
tt = Time.parse(d.to_s)
Als Update zum Stand des Ruby - Ökosystems Date
, DateTime
und Time
hat nun Methoden zu konvertieren zwischen den verschiedenen Klassen. Verwenden von Ruby 1.9.2+:
pry
[1] pry(main)> ts = 'Jan 1, 2000 12:01:01'
=> "Jan 1, 2000 12:01:01"
[2] pry(main)> require 'time'
=> true
[3] pry(main)> require 'date'
=> true
[4] pry(main)> ds = Date.parse(ts)
=> #<Date: 2000-01-01 (4903089/2,0,2299161)>
[5] pry(main)> ds.to_date
=> #<Date: 2000-01-01 (4903089/2,0,2299161)>
[6] pry(main)> ds.to_datetime
=> #<DateTime: 2000-01-01T00:00:00+00:00 (4903089/2,0,2299161)>
[7] pry(main)> ds.to_time
=> 2000-01-01 00:00:00 -0700
[8] pry(main)> ds.to_time.class
=> Time
[9] pry(main)> ds.to_datetime.class
=> DateTime
[10] pry(main)> ts = Time.parse(ts)
=> 2000-01-01 12:01:01 -0700
[11] pry(main)> ts.class
=> Time
[12] pry(main)> ts.to_date
=> #<Date: 2000-01-01 (4903089/2,0,2299161)>
[13] pry(main)> ts.to_date.class
=> Date
[14] pry(main)> ts.to_datetime
=> #<DateTime: 2000-01-01T12:01:01-07:00 (211813513261/86400,-7/24,2299161)>
[15] pry(main)> ts.to_datetime.class
=> DateTime
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
und Time.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.
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
Dies gibt Folgendes aus
2010-01-01T10:00:00-02:00
2010-01-01 10:00:00 -0200
2010-01-01T10:00:00-02:00
Die vollständigen ursprünglichen DateTime-Informationen einschließlich der Zeitzone werden beibehalten.
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:
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_time
Methode aus