Независимое от часового пояса сравнение сроков в объеме рельсов - PullRequest
0 голосов
/ 25 августа 2018

Рассмотрим следующий случай. У меня есть модель Ваучер с полем datetime activ_due_date и моделью пользователя, которая содержит актуальную информацию о его местонахождении (часовой пояс, смещение UTC).
Я хочу проверить, запрашивает ли он активацию ваучера до установленной даты в любом из доступных часовых поясов . Например, если срок оплаты установлен на 28.08.2018 23:59 UTC Я хочу, чтобы моя область before_activation_due проверила, запрашивает ли он что-то до 28.08.2018 - 23:59 в своем текущем часовом поясе, поэтому моя дата оплаты не является фиксированной - это зависит от местоположения пользователя - в одном месте это может быть позже срока, а в другой раньше.
Я попробовал следующий подход.

модель / voucher.rb

scope :before_activation_due, lambda { |user|
  where('activation_due_date > ? ', Time.current.to_utc + user.utc_offset)
}

Мои вопросы:

  1. Это правильный подход? Если нет, то как правильно обращаться с такими случаями?

  2. Как проверить такой прицел? Текущая временная метка, вероятно, берется с сервера базы данных при сравнении даты и времени во время выполнения запроса, поэтому я не уверен, как ее смоделировать в моих спецификациях.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 26 августа 2018

Одним из подходов является преобразование activation_due_date в часовой пояс пользователя.Как вы говорите, «моя дата оплаты не является чем-то фиксированным - это зависит от местоположения пользователя».

Чтобы сделать это в качестве области, проще всего было бы использовать функции часового пояса вашей базы данных.Это зависит от того, какую базу данных вы используете, но в PostgreSQL это будет что-то вроде: -

where('activation_due_date AT TIME ZONE ? > NOW() ', user.timezone)


Еще более простым способом будет сравнение строк

where('to_char(activation_due_date, 'YYYYMMDDHH24MISS') > ?', Time.current.in_time_zone(user.timezone).strftime('%Y%m%d%H%M%S');

В этом случае мы говорим, сколько времени на стене для пользователя, и меньше ли оно времени в базе данных (которая «хранится» в UTC).

0 голосов
/ 25 августа 2018

Вы можете сохранить только часовой пояс пользователя, а не смещение, затем выполните:

where('activation_due_date > ? ', Time.now.utc.in_time_zone(user.timezone))

где часовой пояс - это любой действительный часовой пояс, показанный в

rake time:zones

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

Чтобы проверить это, вы можете вручную вставить любую дату в свою базу данных.Затем вы можете использовать драгоценный камень, такой как https://github.com/travisjeffery/timecop, чтобы путешествовать во времени к этой точке, и проверить свой прицел:

Voucher.create(activation_due_date: '2018-01-02 00:00:00')
format = '%Y-%m-%d %H:%M:%S %Z'
time = DateTime.strptime("2018-01-02 00:00:00 Central Time (US & Canada)",format)
Timecop.travel(time)
Voucher.before_activation_due.all ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...