Учет летнего времени в веб-приложении rails и iCal

Да, это немного сбивает меня с толку, поэтому я попытаюсь объяснить сверху!

У меня есть веб-приложение rails. Это внутреннее приложение компании, и оно будет использоваться только в Великобритании. Одной из функций приложения является управление собраниями. У встреч есть дата и время начала. В форме есть средство выбора даты/времени, которое позволяет пользователю выбрать дату и время встречи. Я сохраняю эту дату КАК ЕСТЬ в базе данных. Все встречи длятся 2 часа, поэтому время окончания просто начало + 2 часа.

Пример:

2013-06-23 6:45PM in the form is stored in the db as 2013-06-23 18:45:00
2013-12-23 6.45pm in the form is stored in the db as 2013-12-23 18:45:00

Обратите внимание, что первая дата указана во время летнего времени (BST), а вторая — во время GMT. Мне на самом деле все равно, GMT это или BST: встреча происходит в это время, абсолютно.

Внутри веб-приложения rails я просто распечатываю точную дату и время из БД — конечно, в красивом формате!

Теперь в какой-то момент я отправляю электронное письмо организатору встречи и человеку, с которым они встречаются. Это электронное письмо сообщает им дату и время встречи и т. д., а также включает файл iCal (.ics), который они могут поместить в свой календарь (обычно Outlook, но также Apple или Gmail).

Проблема, с которой я сталкиваюсь, заключается в том, что (используя приведенные выше примеры) Outlook показывает собрания следующим образом:

Meeting #1: Start: 23/06/2013 7:45pm, End: 23/06/2013 9:45pm
Meeting #2: Start: 23/12/2013 6:45pm, End: 23/12/2013 8:45pm

Обратите внимание, что он скорректировал первый из-за BST/GMT.

Текст файла .ics содержит этот код:

Встреча №1:

BEGIN:VCALENDAR
...
DTEND:20130623T204500Z
DTSTART:20130623T184500Z
...
END:VCALENDAR

Встреча №2:

BEGIN:VCALENDAR
...
DTEND:20131223T204500Z
DTSTART:20131223T184500Z
...
END:VCALENDAR

Поэтому я кодирую даты/время, используя часовой пояс Z (UTC). Я понимаю, почему Outlook неправильно конвертирует время UTC в время BST для № 1 и оставляет № 2 в покое (потому что GMT == UTC)

Мой вопрос: как мне остановить это происходит? Я хочу, чтобы время, на которое запланировано собрание, было абсолютным, фактическим временем, независимо от GMT/BST: 18:45.

Должен ли я хранить дату и время в формате UTC в БД? Как это будет сделано (я предполагаю, что это будет применяться ко всем датам, а не только к датам начала встречи). И как повторно преобразовать их обратно в фактическое время и дату, когда я отображаю их в веб-приложении?

Дополнительно: у меня есть запись в моем файле initializers/time_formats.rb, например:

:ical => "%Y%m%dT%H%M00Z" 

Таким образом, даты получаются как «20130623T184500Z». Я использую это при создании ics. И это, я думаю, проблема - если дата/время во время BST, я не хочу использовать Z, а что-то еще?


person user2563682    schedule 11.09.2013    source источник
comment
Говоря о хранении дат в формате UTC в базе данных, поле БД - это дата и время MSSQL. В этом поле нет ничего, что указывало бы на смещение UTC... Итак, как узнать, нужно ли прибавлять/вычитать час?   -  person user2563682    schedule 11.09.2013
comment
rails c d = DateTime.now => Wed, 11 Sep 2013 12:25:10 +0100 d.utc => Wed, 11 Sep 2013 11:25:10 +0000 Итак, я могу преобразовать дату в UTC перед сохранением в БД. Как отменить преобразование при извлечении?   -  person user2563682    schedule 11.09.2013
comment
Просто отметим (после некоторого прочтения, что рельсы по умолчанию используют UTC в базе данных): я нигде не настраивал какие-либо вещи, связанные с часовым поясом - это просто то, как дата/время всегда работали (сохраните их как есть), я предполагал это был по умолчанию.   -  person user2563682    schedule 11.09.2013


Ответы (2)


Ваша проблема в вашем формате даты/времени. У вас есть:

DTSTART:20130623T184500Z

в вашем файле .ics, и это соответствует 19:45 BST (поскольку британское летнее время — UTC+1).

Есть несколько вещей, которые вы должны сделать. Во-первых, вы можете просто удалить букву «Z» в конце дат. Это означает, что время наследует часовой пояс календаря или базового приложения.

Это будет работать, если предположить, что все машины, на которых работает Outlook, находятся в часовом поясе Европы/Лондона. Если нет, или если вы хотите быть немного безопаснее, вы также должны указать следующее после строки BEGIN: VCALENDAR:

X-WR-TIMEZONE:Europe/London

Это указывает часовой пояс по умолчанию для всех дат, которые не указаны явно.

Наконец, если это не работает по какой-либо причине, вам необходимо явно определить дату и время. Сначала вам нужно добавить в календарь определение часового пояса для Европы/Лондона. Необходимая информация доступна по адресу http://www.tzurl.org/zoneinfo-outlook/Europe/London.ics. Затем вам нужно убедиться, что все даты и время имеют формат:

DTSTART;TZID=Europe/London:20130623T184500

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

person Community    schedule 12.09.2013
comment
Хорошо спасибо. Я пытался добавить часовой пояс (а также определения для BST/GMT), но с тем же результатом. На самом деле я наконец-то понял, что происходит - мое приложение rails на самом деле хранит даты UTC (по умолчанию), но оно также думало, что его собственный часовой пояс - UTC! По сути, он хранил местные даты. Изменение приложения, чтобы оно знало, что оно находится в Европе/Лондоне, сделало так, что даты в БД теперь точно указаны в формате UTC, что означает, что я могу использовать формат даты Z в iCals, а Outlook и приложение rails конвертируют дату UTC обратно в фактическая дата, выбранная пользователем - Presto! - person user2563682; 16.09.2013

Извините, что отвечаю на это сам, но на случай, если кто-то еще столкнется с этим, вот что я обнаружил, было причиной моей конкретной проблемы. Обратите внимание, что ответ выше о часовых поясах также имеет смысл!

Мое приложение rails хранит дату и время UTC в БД (по умолчанию). Но оно также думало, что его собственный часовой пояс был UTC, что также, по-видимому, является значением по умолчанию.

В результате, по сути, он хранил локальные даты, в любом случае локальные для UTC. Изменение приложения, чтобы оно знало, что оно находится в Европе/Лондоне, сделало так, что все даты в БД теперь точно соответствуют UTC (это означает, что они на час позже, если я сейчас нахожусь в BST)

Теперь я могу использовать формат даты и времени Z в iCals, а Outlook и приложение rails преобразуют дату UTC обратно в фактическую дату и время для локали пользователя просмотра (Европа/Лондон для всех на данный момент). Это то, что я хотел.

person user2563682    schedule 16.09.2013