ruby on rails - sistema - Rieles: cómo analizar una cadena de fecha y hora en una zona horaria específica
hora y fecha del sistema (6)
Este es el método que se me ocurrió. No es el más bonito, pero funciona. Permite analizar la cadena utilizando un formato específico y luego convertirlo en el formato que sé que Time.zone.parse
requiere.
class ActiveSupport::TimeZone
def strptime(time, format=''%m/%d/%Y'')
formatted = Time.strptime(time, format).strftime(''%Y-%m-%d %T'')
parse(formatted)
end
end
Luego puede hacer algo como lo que se mencionó en otra pregunta, pero con un formato específico:
zone = "Central Time (US & Canada)"
ActiveSupport::TimeZone[zone].strptime(''2013-04-03'', ''%Y-%m-%d'')
O si ya tiene un conjunto de zona horaria:
Time.zone = "Central Time (US & Canada)"
Time.zone.strptime(''01/13/2006'')
Usé un formato predeterminado de %m/%d/%Y
porque eso es lo que mi usuario ingresa la mayor parte del tiempo. Puede personalizar esto según sus necesidades, o usar el formato predeterminado que usa DateTime
que es believe is iso8601 ( %FT%T%z
)
Estoy usando Rails 3.2 y ruby 1.9.3 en Debian. Tengo una aplicación que recopila una fecha, hora y zona horaria en forma de cadenas a través de un formulario HTML. Algo como esto:
start_date: "04-15-2010",
start_time: "10:00:00",
timezone: "Central Time (US & Canada)"
Lo que me gustaría hacer es analizar estos 3 elementos en una sola fecha que se guarda en mi base de datos como UTC, que en este caso agregaría 7 horas a la hora de inicio, una vez que esté en la zona horaria UTC. Por lo tanto, el tiempo almacenado sería de 17:00 una vez que esté en el DB como UTC en lugar del tiempo central recibido.
He intentado algo como esto para analizar la fecha:
ActiveSupport::TimeZone[timezone].at DateTime.strptime("{ 2012-04-09 20:00:00 }", "{ %Y-%m-%d %H:%M:%S }").to_i
Sin embargo, no puedo incorporar la zona horaria en el tiempo resultante con% Z. O bien no analiza o el tiempo se interpreta como UTC, no como hora central. Así que mi pregunta es cómo forzar una cadena de fecha en una zona horaria determinada sin cambiar el valor de la fecha / hora real almacenada. Me gustaría poder analizar la cadena en un objeto de fecha / hora que incluya la zona horaria correcta con ella en ese momento para que las conversiones de zona horaria futuras sean precisas. He buscado por todos lados y no puedo encontrar una manera de hacer esto. Es extraño, ya que parece algo común que uno hace con las fechas ingresadas desde formularios HTML. Gracias por cualquier ayuda.
Finalmente encontré la manera sucia pero definitiva de hacer esto.
Primero, analiza la cadena usando Ruby Time.strptime como este:
time = Time.strptime(''12 : 00 : PM'', ''%I : %M : %p'')
De esta forma obtienes el tiempo analizado, pero todavía no en la zona horaria correcta. Para solucionarlo, conviertamos el tiempo en forma de cadena y analicémoslo con el estándar ActiveSupport :: TimeZone # parse
Time.zone.parse(time.to_s)
El resultado es ActiveSupport :: TimeWithZone con nuestro tiempo analizado en la zona horaria correcta.
La razón por la que tenemos que hacerlo de esta manera es que ni ActiveSupport :: TimeZone ni ActiveSupport :: TimeWithZone son compatibles con el método strptime. Así que tenemos que analizar el tiempo con el núcleo de Ruby strptime que no tiene información de zona horaria, convertirlo a formato aceptable en objetos ActiveSupport y luego analizarlo de nuevo.
Para que DateTime tome la cadena de fecha y adjunte una zona horaria que no sea UTC sin cambiar los valores de la cadena de fecha, use esto, es fácil, no se rompe en el día bisiesto :)
xx = DateTime.strptime("9/1/15 #{object.time_zone}", "%m/%d/%Y %Z")
Prueba esto:
zone = "Central Time (US & Canada)"
ActiveSupport::TimeZone[zone].parse("2013-04-03 17:47:00")
Yo personalmente prefiero usar String # in_time_zone:
>> ''22.09.1986 10:30''.in_time_zone(''Central Time (US & Canada)'')
Mon, 22 Sep 1986 10:30:00 CDT -05:00
%Z
es la forma correcta de especificar un nombre de zona horaria. Has intentado lo siguiente ?
date_and_time = ''%m-%d-%Y %H:%M:%S %Z''
DateTime.strptime("04-15-2010 10:00:00 Central Time (US & Canada)",date_and_time)