I'm trying to find a simple yet robust way to convert time between arbitrary time zones.
UPDATE 1: I don't understand why this has been downvoted. I've made my research and explored the possibilities. This problem is not as trivial as it might seem. If you think that the function shall look like bTime = aTime + 3
, then please reconsider. Timezones and DSTs are in a state of constant flux. Read this for reference: list of pending / proposed timezone changes. Note that some countries are actually changing their timezones, not just DST settings! And Brazil changed the date on which they change their clocks to winter time! A static lookup table would be broken very quickly by all those changes.
UPDATE 2: I'm not looking into a quick and dirty hack, I can come up with that myself, thank you very much. I'm not getting paid to write something and forget about it; I'd like to create a function once that could be safely used by other people for different internal projects without the maintenance nightmare. Hardcoding constants that are known to change once in a while is a very bad software design (think Y2K bug caused by a very, very old piece of code).
UPDATE 3: This database looks good (although I'm not sure if it's stable enough): https://timezonedb.com/api They even have a TZ conversion call - exactly what I need! I will probably try to parse XML from VBA and share my results.
This: http://www.cpearson.com/excel/TimeZoneAndDaylightTime.aspx explains only how to convert betwen my (current) TZ and another TZ.
Those two SO articles (Getting Windows Time Zone Information (C++/MFC) and How do you get info for an arbitrary time zone in Windows?) talk about getting the information from the registry.
That sounds a bit too convoluted and time-consuming; moreover, it appears that Windows stores TZs in their "full names" (such as (UTC-08:00) Pacific Time (US & Canada)
) and I'd rather refer to TZs using abbreviations (such as EDT).
UPDATE: moreover, relying on Windows registry could also be unsafe: different users might have different versions and some might not be up to date. That would mean a report run by two persons might provide two different results!
Is there a simpler way that will also be robust? Writing a lookup table could work for some time but then it will be broken when a government decides to abolish DST or change anything else.
Maybe get a list of TZs from Internet and parse it?.. Would that be safe enough?..
The API at
https://timezonedb.com/references/convert-time-zone
is indeed a great place to get the correct worldwide time, timezone, and timezone-offset between two locations, taking into account past/future Daylight Savings changes.A problem with your suggested method of specifying only the Time Zone Abbreviations (such as "convert PST to EST") is that this API takes your zones literally, even if they are incorrect.
So, if Toronto is currently on
EDT
but you specifyEST
, you'll probably get the incorrect time. Using "full names" like(UTC-08:00) Pacific Time (US & Canada)
would have the same issue.A way around that is to specify the time zone names like
America/Vancouver
(as listed here), or else specify the city, country and/or region name with the appropriate parameters.I wrote a function to figure it out but it only applies to certain countries (see further down).
What time was it in Toronto last Halloween at 11:11pm Vancouver time?
Result: (Default is
XML
butJSON
is also available.)Getting the data programmatically:
There are plenty of options and lookup methods you will have to decide upon, but here's one example using a VBA Function:
You could also download static files (in
SQL
orCSV
format) here instead of caling the API, and the page also has sample queries. However use caution: it's easier to make mistakes with Daylight Savings (as mentioned above).I made a dummy account to get the "demo" used in the examples, but you should get your own (free) key for long-term use. (I'm not responsible if it gets locked out from over-use!)
An good alternative Time Zone API is Google Maps Time Zone API. The difference is that you specify Latitude & Longitude.
It seems to work just fine without a keyYou'll need to register for a key.Result:
Determining when Daylight Savings is in effect
Below is a function I put together so I could "trust" the Daylight Savings (DST) values I was getting from a different API, however (as discussed by others) the rules have no pattern plus are constantly changing country by country, even town by town in some parts of the world, so this only will work in countries where:
The applicable countries are Bahamas, Bermuda, Canada, Cuba, Haiti, St. Pierre & United States. (Source: Daylight saving time by country**)
And a couple examples of how I could use function
IsDST
*:Finally one more alternative is an API that I use to for polling current/future/historical weather data for various purposes — and also happens to provide Timezone Offset — is DarkSky.
It queries by latitude/longitude and is free (up to 1000 calls/day) and provides "ultra-accurate weather data" (more-so in the USA, where it predicts weather down to the minute and to the square-yard! — but quite accurate I've seen for the unpredictable Canadian West Coast Canada!)
Response is in JSON only, and the very last line is Time Zone Offset versus UTC/GMT time.
Im afraid anything to do with timezones is never a simple task (ask any web designer and they will say it is a massive challenge)
there are 2 ways to solve your problem
1) The Easy way - Create a central list which all other workbooks are linked to. This can be saved on SharePoint or on a shared drive, then all you have to do is update this one table
2) The hard way - Use a website API to get the latest timezone data. https://www.amdoren.com/ is a good site, you can get a free API key by signing up. The only issue is you then have to parse the Json file from the website. This isn't easy but if you google "vba parse json" you will find some solutions (it generally requires importing some libraries and using other peoples code as a starting point)
Hope you find the right solution, and if you do might be worth sharing it as im sure there will be others with same issue.