with rails in_time_zone current ruby-on-rails ruby timezone activesupport

ruby on rails - rails - Rieles veces extraña: "x días a partir de ahora"



strftime ruby (3)

Como ha comentado willcodejavaforfood , esto se debe al horario de verano que finaliza este fin de semana.

Al agregar una duración, ActiveSupport tiene algún código para compensar si la hora de inicio es en horario de verano y la hora resultante no (o viceversa).

def since(seconds) f = seconds.since(self) if ActiveSupport::Duration === seconds f else initial_dst = self.dst? ? 1 : 0 final_dst = f.dst? ? 1 : 0 (seconds.abs >= 86400 && initial_dst != final_dst) ? f + (initial_dst - final_dst).hours : f end rescue self.to_datetime.since(seconds) end

Si tiene 11:09:27 y agrega un número de días, aún obtendrá 11:09:27 en el día resultante, incluso si el DST ha cambiado. Esto se traduce en una hora adicional cuando llega a hacer cálculos en segundos.

Un par de ideas:

  • Utilice el método helper distance_of_time_in_words para dar al usuario una indicación de cuánto tiempo queda en su prueba.
  • Calcule la caducidad como Time.now + (14 * 86400) lugar de usar 14.days.from_now , pero algunos usuarios pueden afirmar que han perdido una hora de su prueba.
  • Configure las pruebas para que caduquen a las 23:59:59 del día de vencimiento, independientemente de la hora de registro real.

cuando los usuarios se registran en uno de mis sitios para una prueba gratuita, configuro el vencimiento de su cuenta como "14.days.from_now". Luego, en la página de inicio, muestro cuántos días quedan, lo que obtengo con:

(user.trial_expires - Time.now)/86400

(porque hay 86400 segundos en un día, es decir, 60 * 60 * 24)

Lo gracioso es que esto sale como más de 14, por lo que se redondea a 15. En una investigación más detallada en la consola, esto ocurre solo por dos días en el futuro (si sabe a qué me refiero). p.ej

>> Time.now => Fri Oct 29 11:09:26 0100 2010 >> future_1_day = 1.day.from_now => Sat, 30 Oct 2010 11:09:27 BST 01:00 #ten past eleven tomorrow >> (future_1_day - Time.now)/86400 => 0.999782301526931 #less than 1, what you''d expect right? >> future_2_day = 2.day.from_now => Sun, 31 Oct 2010 11:09:52 GMT 00:00 >> (future_2_day - Time.now)/86400 => 2.04162248861183 #greater than 2 - why?

Pensé que tal vez tenía que ver con las zonas horarias: noté que el tiempo desde el primer día a partir de ahora estaba en BST y el tiempo dentro de 2 días a las GMT. Entonces, ¡traté de usar el horario local y obtuve los mismos resultados!

>> future_2_day = 2.day.from_now.localtime => Sun Oct 31 11:11:24 0000 2010 >> (future_2_day - Time.now)/86400 => 2.04160829127315 >> (future_2_day - Time.now.localtime)/86400 => 2.04058651585648

Luego me pregunté qué tan grande es la diferencia, y resulta que es exactamente una hora fuera. Así que parece una rareza de zona horaria, o al menos algo que ver con zonas horarias que no entiendo. Actualmente mi zona horaria es BST (horario de verano británico), que es una hora más tarde que UTC en este momento (hasta este domingo, momento en el que vuelve a ser el mismo que UTC).

La hora extra parece ser introducida cuando agrego dos días a Time.now: mira esto. Comienzo con Time.now, le agrego dos días, resto Time.now, luego resto dos días de segundos del resultado y me queda una hora.

Se me acaba de ocurrir, en un momento de bofetadas, que esto está ocurriendo PORQUE los relojes se devuelven el domingo por la mañana: es decir, a las 11.20 del domingo por la mañana, serán dos días Y una hora más a partir de ahora. Estaba a punto de eliminar toda esta publicación, pero luego me di cuenta de esto: pensé ''ah, puedo solucionar esto usando (24 * daynum) .horas en lugar de daynum.days, pero todavía obtengo el mismo resultado: incluso cuando yo uso segundos!

>> (Time.now + (2*24).hours - Time.now) - 86400*2 => 3599.99969500001 >> (Time.now + (2*24*3600).seconds - Time.now) - 86400*2 => 3599.999855

Así que ahora estoy confundido de nuevo. ¿Cómo pueden ahora más dos días de segundos, menos ahora, menos dos días de segundos pueden ser una hora de segundos? ¿Dónde entra la hora extra?


Puede usar la clase Date para calcular el número de días entre hoy y la fecha de caducidad.

expire_date = Date.new(user.trial_expires.year, user.trial_expires.month, user.trial_expires.day) days_until_expiration = (expire_date - Date.today).to_i


Usar since , ejemplo: 14.days.since.to_date