0

I'm working with a Rail 5.2 application witch deals with Location records and associated OpeningHour records. The OpeningHour model contains the fields day (enum), starts_at (time) and ends_at (time).

When I run the below, Rails converts Time.now from the local timezone (+08:00) to UTC time before it compared the times with that of any OpeningHour records. Because the starts_at and ends_at fields are stored as times without timezones, the timezones used in the query don't line up.

Location.opening_hours.where("start_at <= ? AND ends_at >= ?", Time.now, Time.now).any?

What's the best way to tell Rails not to convert to UTC time before comparing as the times in the database are already in localtime?

Any help would be much appreciated!

simonlehmann
  • 852
  • 1
  • 10
  • 27
  • Try to call `Time.current` instead of `Time.now` – fongfan999 May 11 '18 at 06:05
  • @fongfan999 Thanks for your response. I tried calling `Time.current` as you suggested, but it still ends up converting it to UTC first.. – simonlehmann May 11 '18 at 06:09
  • @fongfan999 I see, Perhaps I was unclear in my question. The `starts_at` and `ends_at` fields are stored as times without timezones (i.e: `09:00:00` or `17:00:00). Times shouldn't be converted to UTC before comparing, because the times are already stored in the local timezone. – simonlehmann May 11 '18 at 06:13
  • _"times in the database are already in localtime"_ – Rails expects all database times to be in UTC. How did you store the `OpeningHour` records? They should have been converted accordingly. – Stefan May 11 '18 at 06:17
  • @Stefan if that's the case, then the times are not being converted to UTC before they are created.. Solving that will re-allign the timezones for accurate comparison, though it seems illogical to me that a location's opening hours 09:00:00 to 17:00:00 in the +08:00 timezone are stored in the database as `01:00:00` to `09:00:00`, and the converted back to compare.. I can see all kinds of cases where storing times in UTC would be absolutely essential, but in this case, wouldn't it be more logical and more simple to just store opening hours in the` Location`'s local timezone? – simonlehmann May 11 '18 at 06:48
  • That way, if a user was to view a listing in a completely different timezone to the `Location`'s local timezone, it would still display 09:00:00 to 17:00:00. It would be obvious to users that the timezone displayed was the `Location`'s local timezone, not necessarily the user's timezone - just the same as times that are shown on airline tickets are always in the particular location's local timezone. – simonlehmann May 11 '18 at 06:52
  • You can add inside your config file `config.active_record.default_timezone` set to `:local` ( and define `config.time_zone = "My TimeZone"`). You can check [here](https://stackoverflow.com/questions/6118779/how-to-change-default-timezone-for-active-record-in-rails) – Sovalina May 11 '18 at 07:03
  • Is there a way to set the ActiveRecord timezone to `:local` at a model level only? – simonlehmann May 11 '18 at 07:13

1 Answers1

2

If you config your local timezone in your application.rb as config.time_zone = "My TimeZone" then you can use Time.zone.now to reach times in your local timezone:

Location.opening_hours.where("start_at <= ? AND ends_at >= ?", Time.zone.now, Time.zone.now).any?
Sovalina
  • 5,410
  • 4
  • 22
  • 39