Получить объект времени в начале дня в определенном часовом поясе

Как я могу получить рубиновый объект Time, который представляет начало дня в определенную дату в заданном часовом поясе.


person Blake Taylor    schedule 02.11.2011    source источник
comment
Просто комментарий, поскольку я ничего не знаю об обработке часовых поясов Ruby: полночь не всегда существует, и она может произойти дважды. Например, Бразилия переводит часы в полночь. Вместо этого вам, вероятно, следует найти начало дня.   -  person Jon Skeet    schedule 03.11.2011
comment
Интересный момент. Для моих целей меня интересует начало дня. Спасибо, Джон. Я обновлю вопрос.   -  person Blake Taylor    schedule 03.11.2011
comment
Каков ваш фактический вариант использования? (Я нашел этот вопрос, потому что хотел получить самую последнюю полночь в Калифорнии в формате UTC для отслеживания квот API.)   -  person David J.    schedule 01.08.2012


Ответы (4)


date = Date.today

date.to_time.in_time_zone('America/New_York').beginning_of_day

В настоящее время выводит => 2011-11-02 00:00:00 -0400

Time.now.in_time_zone('Asia/Shanghai').beginning_of_day

В настоящее время выводит => 2011-11-03 00:00:00 +0800

date = Date.today

date.to_time.in_time_zone('Asia/Shanghai').beginning_of_day

В настоящее время выводит => 2011-11-02 00:00:00 +0800

person Timothy Hunkele    schedule 03.11.2011
comment
Хотел бы я, чтобы это было так просто. К сожалению, нет гарантии, что время, которое вы получите после преобразования часового пояса, будет в тот же день. Иногда будет, а иногда нет, в зависимости от начальной и конечной зоны. Я полагаю, что мог бы сравнить компонент даты после преобразования с исходным значением и при необходимости скорректировать, но это действительно неуклюже. На что я надеюсь, так это на элегантный способ сделать это, который всегда работает. Надеюсь, в API есть что-то, я не думаю, что это сумасшедшая вещь, которую нужно делать. - person Blake Taylor; 03.11.2011
comment
Я могу не совсем понять, что вы пытаетесь сделать, но date.to_time.in_time_zone('TIMEZONE').beginning_of_day дает вам 00:00:00 UTC для исходной указанной даты. - person Timothy Hunkele; 03.11.2011
comment
Это не дает вам 0 UTC, оно дает вам 0 в часовом поясе, что предпочтительнее. Но он не делает этого до преобразования часовых поясов с помощью in_time_zone, поэтому дата больше не обязательно действительна. Вот, например, что я имею в виду. date.to_time.in_time_zone('Asia/Shanghai').midnight.in_time_zone(Time.zone).midnight #=> One day in the past.. В идеале, ruby ​​должен позволять мне делать что-то подобное. date.to_time(zone). - person Blake Taylor; 03.11.2011

В итоге я использовал метод #local для объектов ActiveSupport::TimeZone, передающих компоненты объекта Date.

# Get example date and time zone...
date = Date.today
timezone = ActiveSupport::TimeZone['America/New_York']

# Get beginning of day for date in timezone
timezone.local(date.year, date.month, date.day)
person Blake Taylor    schedule 05.11.2011

Не уверен, поможет ли это, но это дает мне время, когда мои квоты Google API сбрасываются:

# The most recent midnight in California in UTC time
def last_california_midnight
  (Time.now.utc - 7.hours).midnight + 7.hours
end

Я использую это так с Mongoid, например:

def api_calls_today
  Call.where(updated_at: { '$gte' => last_california_midnight }).count
end

Это будет работать независимо от того, в каком часовом поясе развернут код, если для Mongo установлено значение UTC.

person David J.    schedule 01.08.2012

Чтобы получить конкретный день, например. 1/2/2021 (день: 1, месяц: 2, год: 2021)

("1/2/2021").to_time.in_time_zone('Asia/Shanghai').beginning_of_day
#=> Mon, 01 Feb 2021 00:00:00.000000000 CST +08:00

Чтобы получить текущий день

Time.zone = 'Asia/Shanghai'
Time.current.beginning_of_day
#=> Mon, 12 Jul 2021 00:00:00.000000000 CST +08:00

Я всегда ссылаюсь на время, а не на дату, потому что почти уверен, что с самого начала у меня есть правильный вывод в нужном часовом поясе.

Обратите внимание, что эти два способа обеспечивают одинаковый результат форматирования. Таким образом, вы можете использовать его для дальнейшего расчета разницы во времени.

Я предпочитаю использовать Time.current вместо Time.now при определении часового пояса, что может гарантировать, что время находится в нужном вам часовом поясе. В любом случае, всегда проверяйте результат в Rails Console перед его использованием.

person Komsun K.    schedule 11.07.2021