Встановити часову частину DateTime в рубіні


104

Скажімо, у мене є об'єкт дати, наприклад 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 - те саме значення, що і початковий_фа_ден. Дивіться мою відповідь, чому це може бути важливим у деяких сценаріях.
rmcsharry

1
Ваш перший чисто рубін рішення крапель часовий пояс, ваша друга НЕ
Тоні

1
Я оновив відповідь, щоб врахувати часовий пояс, і замінив другий варіант. @Тоні дуже хороший улов, вони насправді були чутливі до втрати інформації про часовий пояс при ближчому розгляді. DateTime.new(now.year, now.month, now.day, 0,0,0, now.zone) != now.to_date.to_datetime
ашода

TIMEZONE: може бути змінено зміщенням ключового слова в хеш аргументу: DateTime.now.change ({година: 0, хв: 0, сек: 0 зміщення: '+02: 00'})
Екштейн

34

Не забудьте, зрозумів. Потрібно створити новий DateTime:

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

6
Хороша відповідь. Просто хотілося додати, що ці нулі представляють HOUR, MINUTE, SECOND та OFFSET (часовий пояс) у такому порядку.
d_ethier

3
Після того, як не вдалося це зробити, я зрозумів, що з: DateTime.new(Time.now.year, Time.now.month, Time.now.day, 0, 0, 0)це працює.
Екштейн

2
Не забувайте: now = DateTime.now
Abel

1
Також зауважимо, що останнім аргументом має бути рядок часового поясу, наприклад ("- 0700") для MST, а не ціле число
Donavan White

2
Якщо ви не маєте справу з історичними датами, НЕ ВИКОРИСТОВУЙТЕ DateTime. У вас з’являться дратівливі проблеми, якщо ви живете в країні, де літній час, як Великобританія. Дивіться пояснення тут. gist.github.com/pixeltrix/e2298822dd89d854444b
fatuhoku

5

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

Тож я додаю це як додаткову інформацію для тих, хто може використати прийняту відповідь для обчислення півночі х днів у майбутньому.

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

DateTime.now.midnight + 14.days

- це ранок 14-го дня, що дорівнює випробуванню 13-денного дня (х - частина залишитого дня - якщо зараз опівдні, то це випробування 13,5 дня).

Вам фактично потрібно було б це зробити:

DateTime.now.midnight + 15.days

щоб отримати півночі 14-го дня.

З цієї причини я завжди вважаю за краще використовувати beginning_of_day, оскільки це 00:00:00. Використання опівночі може ввести в оману / неправильно зрозуміти.


1

Якщо ви використовуєте його, часто рекомендується встановити цей дорогоцінний камінь, щоб поліпшити розбір дати:

https://github.com/mojombo/chronic

require 'chronic'

Chronic.parse('this 0:00')

Я не впевнений, чому ця відповідь позначена правильною. Це насправді не відповідає на питання. Я знаю, як розібрати рядок до дати. Але я хотів би знати, як змінити певну частину певного екземпляра дати. Наприклад, рік. Якісь ідеї? У Java я би просто використовував сетер протягом року. Але в Рубі це не працює :-(
Роберт Рейз

1
Я більше не вірю хронічному самоцвіту. Це дійсно застаріло. У мене виникли проблеми з аналізом дати-часу під час роботи в моєму додатку, що призвело до втрати бізнесу.
Vijay Meena
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.