now - Convierta a/desde DateTime y Time en Ruby
strftime ruby (5)
Como una actualización del estado del ecosistema Ruby, Date
, DateTime
y Time
ahora tienen métodos para convertir entre las diversas clases. Usando 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
¿Cómo se convierte entre un objeto DateTime y un objeto Time en Ruby?
Desafortunadamente, las funciones DateTime.to_time, Time.to_datetime
y Time.parse
no retienen la información de la zona horaria. Todo se convierte a la zona horaria local durante la conversión. La aritmética de fechas aún funciona pero no podrá mostrar las fechas con sus zonas horarias originales. Esa información de contexto a menudo es importante. Por ejemplo, si quiero ver las transacciones realizadas durante el horario comercial en Nueva York, probablemente prefiera verlas en sus zonas horarias originales, no en la zona horaria local en Australia (12 horas antes que en Nueva York).
Los métodos de conversión a continuación guardan esa información.
Para Ruby 1.8, mira la respuesta de Gordon Wilson . Es del buen viejo confiable libro de cocina de Ruby.
Para Ruby 1.9, es un poco más fácil.
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
Esto imprime lo siguiente
2010-01-01T10:00:00-02:00
2010-01-01 10:00:00 -0200
2010-01-01T10:00:00-02:00
Se conserva la información original de DateTime, incluida la zona horaria.
Mejorando la solución de Gordon Wilson, aquí está mi intento:
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
Obtendrá el mismo tiempo en UTC, perdiendo la zona horaria (por desgracia)
Además, si tienes ruby 1.9, simplemente prueba el método to_time
Necesitará dos conversiones ligeramente diferentes.
Para convertir de Time
a fecha y Time
, puede modificar la clase de tiempo de la siguiente manera:
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
Ajustes similares a la Fecha le permitirán convertir DateTime
a 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
Tenga en cuenta que debe elegir entre la hora local y GM / UTC.
Ambos fragmentos de código están tomados del Libro de cocina Ruby de O''Reilly. Su policy reutilización de código lo permite.
require ''time''
require ''date''
t = Time.now
d = DateTime.now
dd = DateTime.parse(t.to_s)
tt = Time.parse(d.to_s)