2011-10-26 19 views
17

Tengo una cadena que analizo con DateTime.strptime. La zona horaria de la fecha en la cadena es CET, pero Ruby crea un objeto UTC DateTime que, por supuesto, tiene un desplazamiento de 2 horas.Strptime con Timezone

Actualmente estoy trabajando alrededor del problema con DateTime.strptime().change(:offset => "+0020") pero estoy bastante seguro de que esta no es la manera en que debe funcionar.

¿Puede alguien aclararme la forma correcta de hacerlo?

+0

si se encuentra en un país con CEST/CET timezone un desplazamiento fijo no funcionará. También estoy interesado en esto, no veo cómo hacer analizar strptime para la zona horaria actual (pero no el valor en este momento, el correcto dependiendo de la cadena analizada). – tokland

Respuesta

-1

que se puede suprimir una respuesta aceptada

Como @LeeJarvis se señala en la sección de comentarios, Chronic.parse no acepta una opción :time_class. Así que esta respuesta está libre de errores y, aunque parece que funciona, no lo hace (a no ser crónica permite pasar una opción :time_class pronto.)


La gema crónica es realmente de gran alcance.

lo uso como esto:

Chronic.parse("next 5:00 pm", 
:time_class => ActiveSupport::TimeZone.new(User.first.time_zone)).utc 

En el ejemplo anterior, es User.first.time_zone "Hora del Pacífico (EE.UU. & Canadá)".

crónica compatible con una gran cantidad de formatos a fin de comprobar hacia fuera en https://github.com/mojombo/chronic

Asegúrese de pasar la opción :time_class y para convertir a UTC (en la documentación, conjuntos crónicas :time_class antes de llamar a análisis. Evito este enfoque porque que podría causar otras partes a través de la aplicación no funcione)

documentación de zona horaria es al http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html

+0

Esta respuesta no es correcta. 'parse()' no toma una opción 'time_class'. Está configurado en la clase 'Crónica' directamente. Esto eventualmente cambiará en las versiones futuras de Chronic, aunque –

+0

Mi mal ... Lo eliminaré hasta que esta opción esté disponible =) – Abdo

+0

Erm ... No puedo eliminar una respuesta aceptada. Voy a comentar arriba. – Abdo

9

que utilice de la siguiente manera:

ruby-1.9.2-head :001 > require 'date' 
=> true 
ruby-1.9.2-head :002 > fmt = "%m-%d-%Y %H:%M:%S %Z" 
=> "%m-%d-%Y %H:%M:%S %Z" 
ruby-1.9.2-head :003 > DateTime.strptime "10-26-2011 10:16:29 CET", fmt 
=> #<DateTime: 2011-10-26T10:16:29+01:00 (212186380589/86400,1/24,2299161)> 
ruby-1.9.2-head :004 > DateTime.strptime "10-26-2011 10:16:29 UTC", fmt 
=> #<DateTime: 2011-10-26T10:16:29+00:00 (212186384189/86400,0/1,2299161)> 
ruby-1.9.2-head :005 > DateTime.strptime "10-26-2011 10:16:29 PST", fmt 
=> #<DateTime: 2011-10-26T10:16:29-08:00 (212186412989/86400,-1/3,2299161)> 

¿Es lo que quieres decir?

+2

no tengo una cadena que determine la zona horaria en mi cadena analizada. es 10-26-2011 10:16:29 en lugar de "10-26-2011 10:16:29 CET" – Nicolas

+0

Ha resuelto mi problema, puedo '' 19-19-2012 11:08:44 "+" CST "'. Creo que la tuya es la respuesta correcta. – mwoods79

+0

¿Qué pasa cuando pasas al horario de verano? ¿No debería este + "CST" estar más informado? Según el comentario anterior, sería bueno si pudiéramos elegir eso en función del tiempo que acaba de formatear ... estoy aprendiendo a odiar las zonas horarias. –

0

puede convertir la fecha de zona horaria con to_time_in_current_zone. Por ejemplo:

Date.strptime('04/07/1988', '%m/%d/%Y').to_time_in_current_zone 
+3

http://apidock.com/rails/Date/to_time_in_current_zone método se deprecia lo siento :( – Brandt

1

que estaba "strptiming" esta cadena:

19/05/2014 8:13:26 a.m. 

Una marca de tiempo local, que es en mi caso es Auckland NZ sin un sello zona horaria en la cadena, como puede verse.

Lo mejor que puedo decir Time.strptime usa la zona horaria del servidor como base.

En mi situación, y la buena práctica general, mis servidores funcionan en la zona UTC por lo que cada análisis sintáctico de la cadena terminó creando un objeto de tiempo, el tiempo de 0000 (UTC):

2014-05-19 08:13:26 +0000 

Entonces conversión a dio:

Mon, 19 May 2014 20:13:26 NZST +12:00 

que, como se puede ver es de 12 horas (el desfase UTC) más tarde que el tiempo real que quería.

He intentado utilizar el truco +' Auckland', '...%Z' como se indica anteriormente sin ningún cambio. Luego utilicé el truco + '+1200', '...%Z' como se indica arriba, que funcionó correctamente.

Sin embargo, estaba preocupado por el horario de verano, entonces el análisis estaría fuera por una hora, así que esto es lo que he terminado todavía con:

Time.strptime(call_data[:datetime].gsub(/\./, "").gsub(/am/, "AM").gsub(/pm/, "PM") + (Time.zone.now.time_zone.utc_offset/3600).to_s.ljust(4,'0').rjust(6,' +'), '%d/%m/%Y %I:%M:%S %p %Z').in_time_zone(Time.zone) 

Resultado:

Mon, 19 May 2014 08:13:26 NZST +12:00 

No es particularmente elegante pero funciona.

0

He estado batallando con este mismo problema al intentar analizar una cadena de fecha de un formulario y guardarlo independientemente de la hora del servidor. El proceso que he seguido es como tal. Aseguro que las zonas horarias RoR y Ruby están configuradas en UTC. También lo hace más fácil si el servidor está en hora UTC.

estoy almacenando los usuarios Locale utilizando el ActiveSupport: formato de zona horaria como US/Eastern tengo una función de fecha interpretar que puede representar una cadena de fecha que no contiene una zona horaria de forma nativa o compensado

# date_str looks something like this `12/31/2014 6:22 PM` 
# tz is a string containing an ActiveSupport::TimeZone name like `US/Eastern` 
def interpret_date(date_str, tz) 
    Time.use_zone tz do 
    parsed_dt = DateTime.strptime(date_str, '%m/%d/%Y %H:%M %p') 
    offset = parsed_dt.in_time_zone(tz).utc_offset 
    parsed_dt.advance(seconds: -(offset)).in_time_zone(tz) 
    end 
end 

Este por supuesto, no parece una solución perfecta, pero funciona. Las medidas para asegurar la zona horaria correcta son:

  1. analizar la cadena de la fecha de acuerdo a nuestro formato
  2. Extraer la corriente de compensación en base a la vez en esa zona horaria UTC (que tenemos que hacer esto si la fecha está el análisis está en dst mientras que su hora local no es dst para el este, esto asegurará que el dst sea local en el tiempo analizado)
  3. Convierta la hora a nuestra configuración regional objetivo y permita que el tiempo cambie con la compensación correcta añadida
1

Al menos un s de rieles 4.2 (quizás antes, no han probado), siempre y cuando se utiliza en lugar de Time#strptimeDateTime.strptime, la zona horaria actual se aplica automáticamente:

> DateTime.strptime('12/28/2016 5:00 PM', '%m/%d/%Y %H:%M %p') 
=> Wed, 28 Dec 2016 17:00:00 +0000 

> Time.strptime('12/28/2016 5:00 PM', '%m/%d/%Y %H:%M %p') 
=> 2016-12-28 17:00:00 -0800 
3

Esto funciona en los carriles 5:

Time.zone.strptime("2017-05-20 18:20:10", "%Y-%m-%d %H:%M:%S") 

Devuelve la hora en la zona horaria especificada.