Establecer parte de la hora de DateTime en ruby

104

Digamos que tengo un objeto de fecha y hora, por ejemplo DateTime.now. Quiero establecer las horas y los minutos en 0 (medianoche). ¿Cómo puedo hacer eso?

Jesse Aldridge
fuente

Respuestas:

220

Dentro de un entorno de Rails:

Gracias a ActiveSupport puede utilizar:

DateTime.now.midnight
DateTime.now.beginning_of_day

O

DateTime.now.change({ hour: 0, min: 0, sec: 0 })

# More concisely
DateTime.now.change({ hour: 0 })                

Dentro de un entorno puramente Ruby:

now = DateTime.now
DateTime.new(now.year, now.month, now.day, 0, 0, 0, now.zone)

O

now = DateTime.now
DateTime.parse(now.strftime("%Y-%m-%dT00:00:00%z"))
ashoda
fuente
26
FWIW, el método de cambio es parte de rieles, no ruby. Las opciones de tiempo (hora, minuto, seg) se restablecen en cascada, por lo que si solo se pasa la hora, los minutos y los segundos se establecen en 0. Si se pasan la hora y los minutos, los segundos se establecen en 0.
Anna
1
Tenga en cuenta que DateTime.now.midnight no devuelve 24:00:00 como podría esperar, devuelve 00:00:00, el mismo valor que begin_of_day. Vea mi respuesta sobre por qué esto podría ser importante en algunos escenarios.
rmcsharry
1
Su primera solución puramente rubí arroja información de zona horaria, la segunda no lo hace
Tony
1
Actualicé la respuesta para tener en cuenta la zona horaria y reemplacé la segunda variación. @Tony muy buena captura, en realidad ambos eran susceptibles a la pérdida de información de zona horaria en un vistazo más de cerca. DateTime.new(now.year, now.month, now.day, 0,0,0, now.zone) != now.to_date.to_datetime
Ashoda
TIMEZONE: se puede modificar mediante la palabra clave offset en el argumento hash: DateTime.now.change ({hora: 0, min: 0, sec: 0 offset: '+02: 00'})
Ekkstein
34

No importa, lo tengo. Necesita crear una nueva fecha y hora:

DateTime.new(now.year, now.month, now.day, 0, 0, 0, 0)
Jesse Aldridge
fuente
6
Buena respuesta. Solo quería agregar que esos ceros representan HORA, MINUTO, SEGUNDO y DESPLAZAMIENTO (zona horaria) en ese orden.
d_ethier
3
Después de no lograr que esto funcione, lo aprendí con: DateTime.new(Time.now.year, Time.now.month, Time.now.day, 0, 0, 0)funciona.
Ekkstein
2
No olvides: now = DateTime.now
Abel
1
También tenga en cuenta que el último argumento debe ser una cadena de la zona horaria, por ejemplo ("- 0700") para MST, no un número entero
Donavan White
2
A menos que esté tratando con fechas históricas, NO LO USE DateTime. Tendrá problemas molestos si vive en un país que tiene horario de verano como el Reino Unido. Vea una explicación aquí. gist.github.com/pixeltrix/e2298822dd89d854444b
fatuhoku
5

Advertencia : DateTime.now.midnighty DateTime.now.beginning_of_daydevuelve el mismo valor (que es la hora cero del día actual; la medianoche no devuelve 24:00:00 como cabría esperar de su nombre).

Así que agrego esto como información adicional para cualquiera que pueda usar la respuesta aceptada para calcular la medianoche x días en el futuro.

Por ejemplo, una prueba gratuita de 14 días que debería vencer a la medianoche del día 14:

DateTime.now.midnight + 14.days

es la mañana del día 14, lo que equivale a una prueba de 13 días x (x es la parte del día que queda; si ahora es mediodía, entonces es una prueba de 13,5 días).

En realidad, necesitaría hacer esto:

DateTime.now.midnight + 15.days

para llegar a la medianoche del día 14.

Por eso siempre prefiero usar beginning_of_day, ya que son las 00:00:00. Usar la medianoche puede ser engañoso / malentendido.

rmcsharry
fuente
1

Si lo usa con frecuencia, considere instalar esta gema para mejorar el análisis de fechas:

https://github.com/mojombo/chronic

require 'chronic'

Chronic.parse('this 0:00')
wizztjh
fuente
No estoy seguro de por qué esta respuesta está marcada como correcta. Realmente no responde a la pregunta. Sé cómo analizar una cadena en una fecha. Pero me gustaría saber cómo cambiar una parte particular de una instancia de fecha determinada. Por ejemplo el año. ¿Algunas ideas? En Java, solo usaría el setter por año. Pero no funciona en Ruby :-(
Robert Reiz
1
Ya no confío en la gema crónica. Está realmente desactualizado. Tuve un problema al analizar la fecha y la hora en el tiempo de ejecución en mi aplicación, lo que resultó en la pérdida de negocios.
Vijay Meena