Come si converte tra un oggetto DateTime e Time in Ruby?
Come si converte tra un oggetto DateTime e Time in Ruby?
Risposte:
Avrai bisogno di due conversioni leggermente diverse.
Per convertire da Time
a DateTime
te puoi modificare la classe Time come segue:
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
Modifiche simili a Data ti permetteranno di convertire DateTime
in 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
Si noti che è necessario scegliere tra l'ora locale e l'ora GM / UTC.
Entrambi i frammenti di codice sopra riportati sono tratti dal ricettario Ruby di O'Reilly . La loro politica di riutilizzo del codice lo consente.
require 'time'
require 'date'
t = Time.now
d = DateTime.now
dd = DateTime.parse(t.to_s)
tt = Time.parse(d.to_s)
Come aggiornamento allo stato dell'ecosistema Ruby Date
, DateTime
e Time
ora hanno metodi per la conversione tra le varie classi. Utilizzando 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
Sfortunatamente, il DateTime.to_time, Time.to_datetime
eTime.parse
funzioni non mantengono le informazioni sul fuso orario. Tutto viene convertito in fuso orario locale durante la conversione. L'aritmetica della data funziona ancora, ma non sarà possibile visualizzare le date con i loro fusi orari originali. Le informazioni sul contesto sono spesso importanti. Ad esempio, se voglio vedere le transazioni eseguite durante l'orario di lavoro a New York, probabilmente preferisco vederle visualizzate nei loro fusi orari originali, non nel mio fuso orario locale in Australia (che è 12 ore avanti rispetto a New York).
I seguenti metodi di conversione mantengono le informazioni tz.
Per Ruby 1.8, guarda la risposta di Gordon Wilson . Viene dal buon vecchio affidabile Ruby Cookbook.
Per Ruby 1.9, è leggermente più semplice.
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
Questo stampa quanto segue
2010-01-01T10:00:00-02:00
2010-01-01 10:00:00 -0200
2010-01-01T10:00:00-02:00
Vengono conservate tutte le informazioni originali su DateTime incluso il fuso orario.
Time#to_datetime
sembra preservare tz per me:Time.local(0).to_datetime.zone #=> "-07:00"; Time.gm(0).to_datetime.zone #=> "+00:00"
Migliorando la soluzione Gordon Wilson, ecco il mio tentativo:
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
Avrai lo stesso tempo in UTC, perdendo il fuso orario (purtroppo)
Inoltre, se hai ruby 1.9, prova il to_time
metodo