ruby on rails - timezones - ¿Rails ActiveSupport Time Parsing?
time rails (5)
El módulo ActiveSupport de Rails amplía la clase de tiempo ruby incorporada con varios métodos.
Cabe destacar que existe el método to_formatted_s
, que le permite escribir Time.now.to_formatted_s(:db)
para obtener una cadena en formato de base de datos, en lugar de tener que escribir strftime
formato de strftime
feas en todas partes.
Mi pregunta es, ¿hay alguna manera de ir hacia atrás?
Algo como Time.parse_formatted_s(:db)
que analizaría una cadena en formato de Base de Datos, devolviendo un nuevo objeto de Tiempo. Esto parece algo que los rieles deberían proporcionar, pero si lo es, no puedo encontrarlo.
¿Acaso no puedo encontrarlo o tengo que escribirlo yo mismo?
Gracias
¡Rails 5 finalmente proporciona tiempo de strptime
!
value = ''1999-12-31 14:00:00''
format = ''%Y-%m-%d %H:%M:%S''
Time.zone.strptime(value, format)
# => Fri, 31 Dec 1999 14:00:00 HST -10:00
ActiveSupport::TimeZone.all.sample.strptime(value, format)
# => Fri, 31 Dec 1999 14:00:00 GST +04:00
Me encontré con esto también y ninguna de las respuestas anteriores fue satisfactoria para mí. Lo ideal sería utilizar ActiveSupport::TimeZone
como Time
y llamar a .strptime
con cualquier formato arbitrario y recuperar el objeto TimeZone
correcto. ActiveSupport::TimeZone.strptime
no existe, así que creé este monopatch:
class ActiveSupport::TimeZone
def strptime(str, fmt, now = self.now)
date_parts = Date._strptime(str, fmt)
return if date_parts.blank?
time = Time.strptime(str, fmt, now) rescue DateTime.strptime(str, fmt, now)
if date_parts[:offset].nil?
ActiveSupport::TimeWithZone.new(nil, self, time)
else
time.in_time_zone(self)
end
end
end
Parece que ActiveSupport proporciona los métodos de análisis que está buscando (y yo también estaba buscando), ¡después de todo! - al menos si la cadena que está tratando de analizar es una fecha estándar, con formato ISO-8601 (formato :db
).
Si la fecha que intentas analizar ya está en tu zona horaria local, ¡es realmente fácil!
> Time.zone.parse(''2009-09-24 08:28:43'')
=> Thu, 24 Sep 2009 08:28:43 PDT -07:00
> Time.zone.parse(''2009-09-24 08:28:43'').class
=> ActiveSupport::TimeWithZone
y ese tiempo de reconocimiento de zona horaria puede convertirse fácilmente a UTC
> Time.zone.parse(''2009-09-24 08:28:43'').utc
=> 2009-09-24 15:28:43 UTC
o a otras zonas horarias:
> ActiveSupport::TimeZone.us_zones.map(&:name)
=> ["Hawaii", "Alaska", "Pacific Time (US & Canada)", "Arizona", "Mountain Time (US & Canada)", "Central Time (US & Canada)", "Eastern Time (US & Canada)", "Indiana (East)"]
> Time.zone.parse(''2009-09-24 08:28:43'').utc.in_time_zone(''Eastern Time (US & Canada)'')
=> Thu, 24 Sep 2009 11:28:43 EDT -04:00
Si la cadena de fecha que está tratando de analizar está en UTC, por otro lado, no parece que haya ningún método para analizarlo directamente en TimeWithZone, pero pude evitarlo usando DataTime.strptime ...
Si la fecha que intenta analizar está en UTC y desea que permanezca como UTC, puede usar:
> DateTime.strptime(''2009-09-24 08:28:43'', ''%Y-%m-%d %H:%M:%S'').to_time
=> 2009-09-24 08:28:43 UTC
Si la fecha que intenta analizar está en UTC y desea convertirla a su zona horaria predeterminada, puede usar:
> DateTime.strptime(''2009-09-24 08:28:43'', ''%Y-%m-%d %H:%M:%S'').to_time.in_time_zone
=> Thu, 24 Sep 2009 01:28:43 PDT -07:00
Parece que incluso puede analizar otros formatos, como el extraño formato que produce Time # to_s:
irb -> Time.zone.parse(''Wed, 23 Sep 2009 02:18:08'').to_s(:db)
=> "2009-09-23 09:18:08"
irb -> Time.zone.parse(''Wed, 23 Sep 2009 02:18:08 EDT'').to_s(:db)
=> "2009-09-23 06:18:08"
Estoy bastante impresionado.
Aquí hay algunos ejemplos más de [ http://api.rubyonrails.org/classes/ActiveSupport/TimeWithZone.html][1] :
Time.zone = ''Eastern Time (US & Canada)'' # => ''Eastern Time (US & Canada)''
Time.zone.local(2007, 2, 10, 15, 30, 45) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
Time.zone.parse(''2007-02-10 15:30:45'') # => Sat, 10 Feb 2007 15:30:45 EST -05:00
Time.zone.at(1170361845) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
Time.zone.now # => Sun, 18 May 2008 13:07:55 EDT -04:00
Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone # => Sat, 10 Feb 2007 15:30:45 EST -05:00
Más enlaces de documentación para referencia:
>> "2009-09-24".to_date
=> Thu, 24 Sep 2009
>> "9/24/2009".to_date
=> Thu, 24 Sep 2009
Funciona muy bien a menos que su fecha esté en algún formato raro.
ActiveSupport::TimeZone.new(''UTC'').parse(''2009-09-23 09:18:08'')
=> Wed, 23 Sep 2009 09:18:08 UTC +00:00