Converti in / da DateTime e Time in Ruby

Come si converte tra un object DateTime e un object Time in Ruby?

Avrai bisogno di due conversioni leggermente diverse.

Per convertire da Time a DateTime è ansible modificare la class 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 

Adeguamenti simili a Date 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 ora locale e ora GM / UTC.

Entrambi i frammenti di codice sopra riportati sono tratti dal Ruby Cookbook 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 convertire 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) => # [5] pry(main)> ds.to_date => # [6] pry(main)> ds.to_datetime => # [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 => # [13] pry(main)> ts.to_date.class => Date [14] pry(main)> ts.to_datetime => # [15] pry(main)> ts.to_datetime.class => DateTime 

Sfortunatamente, le funzioni DateTime.to_time, Time.to_datetime e Time.parse non conservano le informazioni sul fuso orario. Tutto viene convertito in fuso orario locale durante la conversione. Gli aritmetici delle date funzionano ancora ma non sarà ansible visualizzare le date con i fusi orari originali. Quelle informazioni di contesto sono spesso importanti. Ad esempio, se voglio vedere le transazioni eseguite durante l’orario lavorativo a New York, probabilmente preferisco vederle visualizzate nei fusi orari originali, non il fuso orario locale in Australia (che 12 ore prima di New York).

I seguenti metodi di conversione mantengono quella informazione tz.

Per Ruby 1.8, guarda la risposta di Gordon Wilson . È dal buon vecchio e 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 le informazioni originali DateTime complete, incluso il fuso orario.

Migliorando la soluzione di 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 

Otterrai lo stesso tempo in UTC, perdendo il fuso orario (sfortunatamente)

Inoltre, se hai Ruby 1.9, prova semplicemente il metodo to_time