Установить временную часть DateTime в рубине

104

Скажем, у меня есть объект datetime, например DateTime.now. Я хочу установить часы и минуты на 0 (полночь). Как я могу это сделать?

Джесси Олдридж
источник

Ответы:

220

В среде Rails:

Благодаря ActiveSupport вы можете использовать:

DateTime.now.midnight
DateTime.now.beginning_of_day

ИЛИ

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

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

В чисто Ruby среде:

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

ИЛИ

now = DateTime.now
DateTime.parse(now.strftime("%Y-%m-%dT00:00:00%z"))
Ашода
источник
26
FWIW, метод смены - это часть рельсов, а не рубин. Параметры времени (час, минута, секунда) сбрасываются каскадно, поэтому, если прошел только час, тогда минута и секунда устанавливаются на 0. Если час и минута прошли, тогда секунда устанавливается на 0.
Анна
1
Имейте в виду, что DateTime.now.midnight не возвращает 24:00:00, как вы могли ожидать, он возвращает 00:00:00 - то же значение, что и start_of_day. См. Мой ответ о том, почему это может быть важно в некоторых сценариях.
rmcsharry
1
Ваше первое чисто рубиновое решение дает информацию о часовом поясе, второе - нет
Тони
2
Я обновил ответ, чтобы учесть часовой пояс, и заменил второй вариант. @ Тони, очень хороший улов, на самом деле они оба были подвержены потере информации о часовом поясе при ближайшем рассмотрении. DateTime.new(now.year, now.month, now.day, 0,0,0, now.zone) != now.to_date.to_datetime
ashoda
TIMEZONE: можно изменить с помощью смещения ключевого слова в аргументе hash: DateTime.now.change ({hour: 0, min: 0, sec: 0 offset: '+02: 00'})
Эккштейн
34

Неважно, понял. Необходимо создать новый DateTime:

DateTime.new(now.year, now.month, now.day, 0, 0, 0, 0)
Джесси Олдридж
источник
6
Хороший ответ. Просто хотел добавить, что эти нули представляют ЧАС, МИНУТУ, ВТОРОЙ и СМЕЩЕНИЕ (часовой пояс) в этом порядке.
d_ethier
3
Не сумев заставить это работать, я узнал, что DateTime.new(Time.now.year, Time.now.month, Time.now.day, 0, 0, 0)это работает.
Ekkstein
2
Не забывайте: now = DateTime.now
Абель
1
Также обратите внимание, что последний аргумент должен быть строкой часового пояса, например ("- 0700") для MST, а не целым числом
Донаван Уайт
2
Если вы не имеете дело с историческими датами, НЕ ИСПОЛЬЗУЙТЕ DateTime. У вас будут неприятные проблемы, если вы живете в стране с летним временем, например в Великобритании. См. Объяснение здесь. gist.github.com/pixeltrix/e2298822dd89d854444b
fatuhoku
5

Предупреждение : DateTime.now.midnightи DateTime.now.beginning_of_dayвернуть то же значение (это нулевой час текущего дня - полночь не возвращает 24:00:00, как можно было бы ожидать от ее имени).

Поэтому я добавляю это как дополнительную информацию для всех, кто может использовать принятый ответ для вычисления полуночи x дней в будущем.

Например, 14-дневная бесплатная пробная версия, срок действия которой истекает в полночь 14-го дня:

DateTime.now.midnight + 14.days

- утро 14-го дня, что соответствует 13-дневной пробной версии (x - оставшаяся часть дня - если сейчас полдень, то это 13,5-дневная пробная версия).

Вам действительно нужно сделать это:

DateTime.now.midnight + 15.days

чтобы получить полночь 14-го дня.

По этой причине я всегда предпочитаю использовать beginning_of_day, так как это 00:00:00. Использование полуночи может ввести в заблуждение или неправильно понять.

rmcsharry
источник
1

Если вы часто его используете, подумайте об установке этого драгоценного камня, чтобы улучшить анализ даты:

https://github.com/mojombo/chronic

require 'chronic'

Chronic.parse('this 0:00')
wizztjh
источник
Я не уверен, почему этот ответ отмечен как правильный. Это не совсем ответ на вопрос. Я знаю, как разобрать строку до даты. Но я хотел бы знать, как изменить конкретную часть данного экземпляра даты. Например год. Любые идеи? В Java я бы просто использовал сеттер в течение года. Но в Ruby это не работает :-(
Роберт Рейз
1
Я больше не доверяю хроническим драгоценным камням. Это действительно устарело. У меня возникла проблема с анализом даты и времени во время выполнения в моем приложении, что привело к потере бизнеса.
Виджей Мина,