Hours of operations in different time zones - sql

I posted a similar question here: https://stackoverflow.com/questions/13923598/department-hours-of-operation-for-different-time-zones-in-sql-server
I think I added too much information to the post :)
What I am trying to do is display hours of operations in different time zones. I am having a difficult time figuring out how to display something like Mon - Fri: 630AM to 630PM (UTC -07:00 Arizona) in every other time zone. I'll get to a point (in another time zone) where Monday is no longer Monday...and I can't seem to figure out how to identify the change.
How do I convert a list of days (Monday, Tuesday, etc...) and Times to every other time zone and find the correct day to use?

Time zones are all relative. Australian Eastern Standard Time is UTC+10 and Eastern Daylight Time is UTC+11. USA Eastern Standard Time is UTC-5 and Eastern Daylight Time is UTC-4. To go from 09:00 21 Dec 2012 Australian EDT to US EST is simply DATEADD(h, -16, '09:00 21 Dec 2012'). The only real trick is knowing when Daylight savings in each zone starts and stops and which juristictions it applies in (Daylight Savings is not observed in Queensland for example).
A google search on time zones will give you the info you need to determine where they sit relative to Universal Time (UTC).
The System.Globilization namespace has everything you could need for this. The datetime class has a lot of methods too.

Related

Implementing rrule using UTC

BLUF: Having trouble implementing rrule in web app using UTC datetime variables since byweekday does not translate well between time zones. For example, when using byweekday attributes on rrules where local time zone datetime falls on a day that is not the same as the UTC equivalent of that day (because of UTC offset), the rrule "breaks" or cannot be easily shifted according to the time zone offset (i.e., the shift of day is not handled automatically).
Advice: Given multiple sites in multiple time zones accessed remotely, would it be reasonable to use local time internally according to time zone of the site and not use UTC internally?
TLDR:
I have an application that is deployed to multiple sites each in a different time zone. The application is accessed via a web app that performs user I/O according to the time zone of the site (site's local time). I am currently maintaining all datetime data internally using UTC. My recurrence rules are implemented using rrule.js (https://github.com/jakubroztocil/rrule) on the client side, and dateutil.rrule (http://labix.org/python-dateutil) on the server side.
When I have an rrule that uses a byweekday setting, the UTC offset from local to UTC is calculated correctly, but the byweekday setting is no longer correct (the byweekday day is not shifted). For example, the following rrule is supposed to be run at 11:55PM local time each Sunday (night).
DTSTART:20210411T065500Z
RRULE:FREQ=WEEKLY;UNTIL=20220101T080000Z;INTERVAL=1;WKST=MO;BYDAY=SU
UTC time is correct given a local time zone offset of -07:00 (=23:55 local time, the night before). But, the rrule set is "wrong" as the first occurrence is given as:
Sun, 11 Apr 2021 06:55:00 GMT
So that when the rrule DTSTART is shifted back to the local time zone (-07:00 offset), the rule runs or triggers the day before which is a Saturday. The rule runs at the right time but on the wrong day because the time zone hour shift is correct, but the day shift does not happen. I would rather not have to do the day shifting manually. Seems easier to just implement the internal datetimes in the target time zone. Maybe I've missed a nuance in rrule management?

Oracle SQL: At time zone does not convert properly for timestamps before 1 June 1905

I need to convert timestamps stored in my database in UTC format to SGT format (UTC + 8) before my frontend service can consume it.
The query i use is this:
SELECT DATE_OF_PURCHASE at time zone 'Asia/Singapore' FROM PROPERTY_LISTINGS;
This works fine as long as the timestamp is before 1 June 1905. Any years before that, and i get a converted timestamp thats always 25 secs behind.
An example:
1899-09-02 17:04:35.000000 in UTC
Converted back to SGT should yield:
1899-09-03 00:00:00.000000 in SGT
Running the query above using at time zone gives:
1899-09-02 23:59:35.000000 +06:55:25
Which is 25 secs off. This leads to the returned timestamp being a whole day off, which is not expected. Is there a workaround for this in SQL?
Singapore changed their timezone several times, see Singapore Standard Time.
Asia/Singapore 6:55:25 - LMT 1901 Jan 1
6:55:25 - SMT 1905 Jun 1 # Singapore M.T.
7:00 - +07 1933 Jan 1
7:00 0:20 +0720 1936 Jan 1
7:20 - +0720 1941 Sep 1
7:30 - +0730 1942 Feb 16
9:00 - +09 1945 Sep 12
7:30 - +0730 1982 Jan 1
8:00 - +08
When you check Oracle documentation then it says: The time zone offset is the difference (in hours and minutes) between local time and UTC. Looks like seconds are simply not supported /considered in time zone conversions.
Oracle uses the IANA time zone database which states:
Scope of the tz database
The tz database attempts to record the history and predicted future of
all computer-based clocks that track civil time. It organizes time
zone and daylight saving time data by partitioning the world into
timezones whose clocks all agree about timestamps that occur after the
POSIX Epoch (1970-01-01 00:00:00 UTC). The database labels each
timezone with a notable location and records all known clock
transitions for that location. Although 1970 is a somewhat-arbitrary
cutoff, there are significant challenges to moving the cutoff earlier
even by a decade or two, due to the wide variety of local practices
before computer timekeeping became prevalent.
Clock transitions before 1970 are recorded for each timezone, because
most systems support timestamps before 1970 and could misbehave if
data entries were omitted for pre-1970 transitions. However, the
database is not designed for and does not suffice for applications
requiring accurate handling of all past times everywhere, as it would
take far too much effort and guesswork to record all details of
pre-1970 civil timekeeping. Although some information outside the
scope of the database is collected in a file backzone that is
distributed along with the database proper, this file is less reliable
and does not necessarily follow database guidelines.
I don't think there is an easy solution.

SnowFlake Convert_timezone function format mapping

Problem
My 24 timezone codes are like EAT, ICT, NZT and I need to use the SnowFlake Convert_timezone function to convert the American Eastern time to the timezone that the records have. But SnowFlake Convert_timezone function only supports timezone in standard iana.org time zones format. So what is the best way to map my 24 time zone to the right formate so that the function can work as expected?
I did not figure out how to set up the standard iana.org time zones database and how to convert my time zone code into theirs, please help! thanks in advance!
Sample code
Convert_timezone('American/New_York', my_time_zone_code, my_timestamp) as normalized_time
Error
Unknown timezone: PST
EAT
East Africa Time, or EAT, is a time zone used in eastern Africa. The time zone is three hours ahead of UTC (UTC+03:00), which is the same as Moscow Time, Arabia Standard Time, Further-eastern European Time and Eastern European Summer Time.
Can be safely mapped with snowflake time as below
Africa/Nairobi
ICT
Indochina Time (ICT) is 7 hours ahead of Coordinated Universal Time (UTC).
Iana Timezones where ICT is currently observed.
Can be safely mapped with snowflake time as
Asia/Ho_Chi_Minh
Asia/Bangkok
Asia/Phnom_Penh
Asia/Vientiane
NZT
Most of the time of NZT will be associated with below two zones, to covert it to snowflake standards you have to
divide these zones based on location either one of them
Pacific/Auckland
Pacific/Chatham
Hope this will help
Thanks
Palash
As per Snowflake documentation currently PDT timezone is not supported.
https://docs.snowflake.com/en/sql-reference/parameters.html
However you can follow below link to set system timezone preference.
https://support.snowflake.net/s/question/0D50Z00007MilHISAZ/snowflake-system-timezone-preference

Trying to reformat timestamp in postgresql

I can't seem to find a question/answer that works for what I'm trying to achieve. Currently, this is how my DB outputs a timestamp:
2015-08-18T19:43:04.738-06:00
However, I would like it to appear as such in the column:
2015-08-18T19:43:04.738 America/Denver
Google has recently changed their formatting options and instead of downloading the output and performing a find/replace, I want an output that doesn't require additional work. I looked on SO and have tried using trim and replace but having no luck.
Thanks for the help in advance!
For whatever reason, the one we've used since February (third from the bottom) no longer works.
2015-08-18T19:43:04.738-06:00 is not quite the right format. Google does not accept milliseconds (which is annoying if they don't just ignore it). You need to send 2015-08-18T19:43:04-06:00. They may have become more strict in what they accept.
Try date_trunc('second', yourtime).
It's not possible to accurately translate an offset like -0600 to a time zone like America/Denver. They say two different things.
-0600 says, with absolute certainty, that this time is 6 hours behind UTC. 12:00:00-06:00 and 18:00:00Z (Z represents UTC) are the same time.
America/Denver means to interpret this timestamp under the rules applicable to the city of Denver, Colorado, USA at that time. To figure out what time it is in UTC you need to look up the offset rules for Denver, Colorado, USA. The offset will change depending on the time of year, usually because of daylight savings time. Because the rules change, it's important to apply the rules as they were at that time.
For example, 2006-03-15 12:00 America/Denver is -0700. But the next year on 2007-03-15 12:00 America/Denver is -0600. Between 2006 and 2007 the daylight savings time rules in the US changed.
Whereas -06:00 avoids all that and simply says the time is offset from UTC by six hours.
You could fake it by simply replacing the offset with America/Denver. So long as you're only sending recent times that should work. You'll be off by at most an hour. But don't do that.
Unless Google Ads specifically needs a time zone there's no point in sending them one. Internally, Postgres is storing your times in UTC anyway and translating them to your server's time zone, America/Denver. Send Google UTC. And, as noted above, chop off the milliseconds.
select date_trunc('second', '2015-08-18T19:43:04.738-06:00'::timestamp with time zone at time zone 'UTC') as datetime;
datetime
---------------------
2015-08-19 01:43:04

Calculate Daylight Savings Time (DST) on SQL/Database level

My location in Sydney, Australia. The dates that I explain will be in UK or Australia date format.
Observe the following:
2010-04-15 04:30:00.000 => 15/04/2010 14:30:00 EST (UK date format - Add 10 hours)
2010-11-05 01:00:00.000 => 05/11/2010 12:00:00 EST (UK date format - Add 11 hours)
Both these times are retrieved from the database in UTC format and then calculated on the Web level whether +10 or +11 hour is applicable.
In Australia, Daylight Savings Time (DST) transition dates vary year by year. The transition dates are usually Early April and Late October.
So how accurate would the Web calculation be? If this year the transition date is a few days later (say 03/04/2010), but the Web calculation bases on a fixed date (say 01/04/2010), wouldn't that mean that the days in between will be off by 1 hour when displayed (due to the fixed calculation nature to a specific day of the month)?
I believe the transition dates is not pre-determined and is actually announced to the public. Is that assumption true?
If not (that means the DST dates are pre-determined), would I be able to do the calculation outside the Web level (on the SQL/Database level)?
The database is SQL Server 2005 and I'm using Report Definition Language (RDL) to display the fields in UTC time. If SQL/database level is not the best way, how do I work out +10 or +11 and format the time accordingly to show the right time?
Thank you.
The database is a bad choice for it: it has less information than c# or .net to work it out. .net uses the registry which is kept upto date periodically by patches. SQL Server would have to have a table with date ranges and offsets.
The transitions are fixed because of scheduling (flights, trains ,whatever). IIRC it only changed once at short notice recently in Australia for some Olympic games and it caused chaos around the world. In 2007 the US changed but this was known in advance.
By fixed, it's the "last Sunday" type fixed even if the date varies.
I would leave it in the web code: the DB does not know where your caller is for example, the web site can work it out.
The problem is whoever wrote this app does not quite understand UTC, its value, and how to use it. The database is the correct location for the dat, but the system is not using UTC as intended.
If you use UTC, then all your date arithmetic should use UTC. In the database. It is currently using a saved UTC and then converting at some (doesn't matter if seciond tier or third) other layer; some other library. Half UTC, and Half something else. Have you considered historic dates, as in what is the DATEDIFF() between 15 Feb 2010 and today ?
This eliminates the concern re DST in Australia or Greenland.; and concern re what date/time the changeover actually happens. Everyone is using Greenwich Mean Time for that particular day.
Do all you date arithmetic in the db, in UTC. And display the result (only) in the local time zone, which as you have it, is the web layer, based on the user.
Many systems have dropped that last step altogether, and display in UTC only, regardless of the user's time zone.
The database can handle DST for you. Use its time zone conversion functions to go from whatever zone you stored the dates in to whatever zone you want to get for the user.
MySQL has CONVERT_TZ(), I don't know what other RDBMS's have.