简体   繁体   中英

How to query records in multiple time zones using their own time zones with Rails or raw SQL

Here's my issue: I have records stored in my DB with UTC time zones but! I need to query those records and return everything within a day according the record's own time zone, regardless of its UTC date.

Example?

Let's say I have a record uploaded at 00:30 on a Tuesday in America/Denver and I have a bunch of records uploaded at 00:30 on a Monday in America/Los_Angeles .

Alright, now, when I query for records made on Monday, the whole day, I'm getting that Tuesday record because 00:30 in America/Denver is technically on Monday in America/Los_Angeles . I'm running raw SQL to try and solve this in my Rails project, but... no dice.

Any help on this?

SELECT
DATE(uploaded_at AT TIME ZONE 'UTC' AT TIME ZONE areas.iso_time_zone) as uploaded_at,
count(DISTINCT photos.id)
FROM photos, areas
WHERE photos.category IN ('landscape', 'family', 'animal', 'saucy', 'feet', 'portrait')
AND photos.uploaded_at
BETWEEN '2017-03-27 00:00:00 UTC' AND '2017-04-02 23:59:59 UTC'
GROUP BY DATE(uploaded_at AT TIME ZONE 'UTC' AT TIME ZONE areas.iso_time_zone)
ORDER BY DATE(uploaded_at AT TIME ZONE 'UTC' AT TIME ZONE areas.iso_time_zone);

Use the in_time_zone method. Docs here: http://apidock.com/rails/DateTime/in_time_zone

Ex. usage:

t = foo.start_time
=> 2000-01-01 14:20:00 UTC
t.zone
=> "UTC"
t.in_time_zone("America/New_York")
=> Sat, 01 Jan 2000 09:20:00 EST -05:00

You can use this to convert the times based on their corresponding timezone thus giving you the proper range to query the UTC records.

Here I am adding on top of @bkunzi01's answer:

There is no way to find out a record's timezone now. So in your action you'll have to provide a timezone based on user's timezone or some logic.

Then use the in_time_zone method. Docs here: http://apidock.com/rails/DateTime/in_time_zone

Ex. usage:

t = foo.start_time
=> 2000-01-01 14:20:00 UTC
t.zone
=> "UTC"
t = t.in_time_zone("America/New_York").at_end_of_day
=> Sat, 01 Jan 2000 09:20:00 EST -05:00
Model.where("created_at > ?", t - 24.hours)

You can use this to convert the times based on their corresponding time zone thus giving you the proper range to query the UTC records.

Something you can do in your WHERE clause. Hope it helps.

BETWEEN IIF(TimeZone=-4,substract 4 hours to UTC time,
IIF(TimeZone=-5,substract 5 hours to UTC time,
IIF(TimeZone=-6,substract 6 hours to UTC time,
IIF(TimeZone=-7,substract 7 hours to UTC time,
IIF(TimeZone=-8,substract 8 hours to UTC time, UTC Time))))) 
AND 
IIF(TimeZone=-4,substract 4 hours to UTC time,
IIF(TimeZone=-5,substract 5 hours to UTC time,
IIF(TimeZone=-6,substract 6 hours to UTC time,
IIF(TimeZone=-7,substract 7 hours to UTC time,
IIF(TimeZone=-8,substract 8 hours to UTC time, UTC Time)))))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM