We have the following situation with a client when synchronizing Exchange calendar with EWS:
On the Win 10 client computer, calling GetTimeZoneInformation returns TIME_ZONE_ID_DAYLIGHT, i.e. 'The system is operating in the range covered by the DaylightDate member of the TIME_ZONE_INFORMATION structure.'
The StandardName is: W. Europe Standard Time
The DaylightName is: W. Europe Daylight Time
IIRC correctly, I now need to search through the Dlt entries of HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\ to determine the root key name for the time zone.
But 'W. Europe Daylight Time' is not present: There are 139 entries but none of them has a Dlt entry named 'W. Europe Daylight Time'
So my code can't convert to the proper root key name and puts 'W. Europe Daylight Time' in EWS SOAP calls like this:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:typ="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:mes="http://schemas.microsoft.com/exchange/services/2006/messages">
<soapenv:Header>
<typ:RequestServerVersion Version="Exchange2013"/>
<typ:MailboxCulture>en-US</typ:MailboxCulture>
<typ:TimeZoneContext>
<typ:TimeZoneDefinition Id="W. Europe Daylight Time"/>
</typ:TimeZoneContext>
</soapenv:Header>
<soapenv:Body>
<mes:ResolveNames ReturnFullContactData="1" SearchScope="ActiveDirectory">
<mes:UnresolvedEntry>someone#somewhere.com</mes:UnresolvedEntry>
</mes:ResolveNames>
</soapenv:Body>
</soapenv:Envelope>
... and these fail with errors like:
GetCalendarFolder (calendar): FaultInBody: A time zone with the specified ID could not be found.
Details: ErrorTimeZone Id: W. Europe Daylight Time
On the client machine, searching the registry for 'W. Europe', I find one entry that says:
RootKeyName: W. Europe Standard Time
DisplayName: (UTC+01:00) Amsterdam, Berlijn, Bern, Rome, Stockholm, Wenen
StandardName: West-Europa (standaardtijd)
DaylightName: West-Europa (zomertijd)
This machine has the following language settings:
Default system UI language : en-US
System locale : nl-NL
Default time zone : W. Europe Standard Time
Installed language(s): en-US
Type : Fully localized language.
Installed language(s): nl-NL
Type : Partially localized language, MUI type.
Fallback Languages en-US
My suspicion is that these 'localized'(?) StandardName/DaylightName registry values prevent me from properly looking up the 'W. Europe Standard Time' time zone ID.
FWIW, the Exchange server has:
TIME_ZONE_ID_DAYLIGHT
StandardName: W. Europe Standard Time
DaylightName: W. Europe Daylight Time
and does have a registry entry
RootKeyName: W. Europe Standard Time
DisplayName: (UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
StandardName: W. Europe Standard Time
DaylightName: W. Europe Daylight Time
How can I resolve this?
You've got two separate concepts mixed together.
The ID of the time zone is "W. Europe Standard Time". It isn't localized for other languages, and it does not change for daylight saving time. The same string is used to cover both standard time and daylight time, despite the word Standard being in it. (This is a common source of confusion, and is also covered in the timezone tag wiki.)
The StandardName, DaylightName, and DisplayName are localized by the OS language, and are not identifiers. They are meant for human display only. For example, the DisplayName is generally paired with the ID in drop-down lists to pick a time zone. The display name would be shown to the user, and the corresponding ID would be saved in the application. The StandardName and DaylightName are used for human display in conjunction with a specific date and time, depending on which is in effect.
That GetTimeZoneInformation returns TIME_ZONE_ID_DAYLIGHT is irrelevant. You should not be using it to mutate the name of the ID (i.e., don't replace "standard" with "daylight").
Ultimately it sounds like you just need the user's time zone id. There are lots of ways to get that. Any of the following would work:
Using the Win32 API, you can call GetDynamicTimeZoneInformation, which returns a DYNAMIC_TIME_ZONE_INFORMATION structure. The TimeZoneKeyName is the ID you should use.
You can get this directly from the registry at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation in the TimeZoneKeyName value
If you are writing .NET code, you can get it from TimeZoneInfo.Local.Id
From the command line, you can call tzutil /g
Related
I am trying to build a select element and add several timezones in United States.
Able to find EST, CST, PST timezones in us & canada, but was not able to find MST(Mountain Standard Time, UTC-7).
Regarding the official document, it says that the timeZone property can be set to any of the time zones currently supported by Windows.
If I have a look at the date/time setting on windows 10, I can see the MST timezone option.
And also if I check this document, it has not MST timezone as well.
Should I just use Mountain Standard Time although it is not in the documents?
Generally speaking, most operations in the Microsoft Graph API that work with time zones will accept any valid Windows or IANA time zone identifier.
If you like, you can call the supportedTimeZones API, to get a complete list of those that are available on the server at any time. This might be useful in such cases where a new time zone is established but not yet installed, but in most cases you can just use any of the standard lists.
A list of Windows time zone identifiers and their display names can be obtained by calling tzutil /l from a Windows command prompt. You can also do this from .NET using TimeZoneInfo.GetSystemTimeZones (using the Id and DisplayName properties).
A list of IANA time zone identifiers can be found on Wikipedia, or from a variety of other sources.
Assuming you want to build a list of time zones for the United States only (not including US Territories), you will need at minimum the following:
Using Windows IDs:
Id Windows Display Name (English)
----------------------------------------------------------------------------
"Eastern Standard Time" "(UTC-05:00) Eastern Time (US & Canada)"
"Central Standard Time" "(UTC-06:00) Central Time (US & Canada)"
"Mountain Standard Time" "(UTC-07:00) Mountain Time (US & Canada)"
"US Mountain Standard Time" "(UTC-07:00) Arizona"
"Pacific Standard Time" "(UTC-08:00) Pacific Time (US & Canada)"
"Alaskan Standard Time" "(UTC-09:00) Alaska"
"Aleutian Standard Time" "(UTC-10:00) Aleutian Islands"
"Hawaiian Standard Time" "(UTC-10:00) Hawaii"
Using IANA IDs:
"America/New_York"
"America/Chicago"
"America/Denver"
"America/Phoenix"
"America/Los_Angeles"
"America/Anchorage"
"America/Adak"
"Pacific/Honolulu"
With regard to the documentation you referred to in your question:
The list of IANA identifiers in the Graph API doc is incomplete, and IMHO that doc needs to be re-written.
The list of Windows identifiers in this doc is intentionally incomplete, as it isn't a list of every supported time zone but rather a list of the default time zone by region on a new Windows installation.
The article here:
http://msdn.microsoft.com/en-us/library/exchange/bb738399(v=exchg.80).aspx
in the section "Use Registry Key Names for TimeZoneNames", tells me that when I can create a calendar item in Exchange, I can pass it the name of a timezone. This is sort-of working, but how do I name "Eastern Daylight Time"?
Only 'US Eastern Standard Time' is accepted as valid. In works in that I schedule something for say 14:00, when it displays in my Google calendar I see it is displaying at 15:00 EDT, so it used the EST timezone I passed in. Problem is that it sends out reminder emails with the time displayed in "US Eastern Standard Time".
When: Friday, August 30, 2013 2:00 PM-3:00 PM. US Eastern Standard Time
... rest of email ...
I don't want that text like that. It should say "US Eastern Daylight Time" or something like that.
The soap request contains XML like:
<t:CalendarItem xmlns="http://schemas.microsoft.com/exchange/services/2006/types">
...
<Start>2013-08-30T14:00:00</Start>
<t:MeetingTimeZone TimeZoneName="US Eastern Standard Time"></t:MeetingTimeZone>
<t:CalendarItem>
This is Exchange Server 2007, SP1.
Here is an image of what the email looks like, in Gmail. (The times are bit different from my above example, sorry). The appointment time is correct, but it in the email body it calls it "Eastern Standard Time", which is not right -- it should be "Eastern Daylight Time" or something like that. (Note that line is part of the email body generated by the Exchange Server, it is not something made up by Gmail.)
The Windows Time Zone key you're looking for is exactly: "Eastern Standard Time". This covers the US Eastern time zone, inclusive of both Eastern Standard Time and Eastern Daylight Time. It has a display name of "(UTC-05:00) Eastern Time (US & Canada)".
This is actually one of the examples I call out in the timezone tag wiki - which you should read if you haven't already.
The other key you found "US Eastern Standard Time" is actually for the zone with the display name of "(UTC-05:00) Indiana (East)" - which is segregated for historical reasons and is now obsolete. (See the Wikipedia entry on Time in Indiana, and Microsoft's KB article on this if you are interested in why.)
If you look in the Windows Registry at HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones, you will see the valid keys. In each key, you will see the Display name that corresponds to each. This explains how they appear when you change your time zone in Windows.
With regards to Exchange Web Services, in the article you mentioned, it does talk about how you can use the key name. But it also talks about how you can pass much more information in the MeetingTimeZone element and use a display name instead.
If interoperability with Google Calendar (and others) is important, you might consider passing the IANA time zone name in the TimeZoneName attribute - in this case it would be America/New_York. You would still need to provide the <BaseOffset>, <Standard>, and <Daylight> elements, so that it will work right on Windows. See the MeetingTimeZone section in that article.
I should state that I haven't tried this approach myself, but it appears from the documentation that if you provide those elements that the TimeZoneName becomes less important to Windows but would still get passed along.
You should certainly be able to pass it using Microsoft's approach:
<MeetingTimeZone TimeZoneName="(GMT-05:00) Eastern Time (US & Canada)">
<BaseOffset>P0DT5H0M0.0S</BaseOffset>
<Standard>
<Offset>P0DT0H0M0.0S</Offset>
<RelativeYearlyRecurrence>
<DaysOfWeek>Sunday</DaysOfWeek>
<DayOfWeekIndex>First</DayOfWeekIndex>
<Month>November</Month>
</RelativeYearlyRecurrence>
<Time>02:00:00.0000000</Time>
</Standard>
<Daylight>
<Offset>-P0DT1H0M0.0S</Offset>
<RelativeYearlyRecurrence>
<DaysOfWeek>Sunday</DaysOfWeek>
<DayOfWeekIndex>Second</DayOfWeekIndex>
<Month>March</Month>
</RelativeYearlyRecurrence>
<Time>02:00:00.0000000</Time>
</Daylight>
</MeetingTimeZone>
What I'm suggesting is that you tweak it slightly by passing the IANA zone name instead and see if it behaves properly with Gmail and Google Calendar:
<MeetingTimeZone TimeZoneName="America/New_York">
<BaseOffset>P0DT5H0M0.0S</BaseOffset>
<Standard>
<Offset>P0DT0H0M0.0S</Offset>
<RelativeYearlyRecurrence>
<DaysOfWeek>Sunday</DaysOfWeek>
<DayOfWeekIndex>First</DayOfWeekIndex>
<Month>November</Month>
</RelativeYearlyRecurrence>
<Time>02:00:00.0000000</Time>
</Standard>
<Daylight>
<Offset>-P0DT1H0M0.0S</Offset>
<RelativeYearlyRecurrence>
<DaysOfWeek>Sunday</DaysOfWeek>
<DayOfWeekIndex>Second</DayOfWeekIndex>
<Month>March</Month>
</RelativeYearlyRecurrence>
<Time>02:00:00.0000000</Time>
</Daylight>
</MeetingTimeZone>
I live in a country where they change the time twice a year. That is: there is a period in the year when the offset from UTC is -3 hours (-180 mins) and other period where the offset is -4 hours (-240 mins)
Grafically:
|------- (offset = -3) -------|------- (offset is -4) -------|
start of year mid end of year
My question is:
the "timezone" is just the number representing the offset? that is: my country has two timezones? or the timezone includes this information?
This is important because I save every date in UTC timezone (offset = 0) in my database.
Should I, instead, be saving the dates with local timezone and saving their offset (at the moment of saving) too?
Here is an example of a problem I see by saving the dates with timezone UTC:
Lets say I have a system where people send messages.
I want to have a statistics section where I plot "messages sent v/s hour" (ie: "Messages sent by hour in a regular day")
Lets say there are just two messages in the whole database:
Message 1, sent in march 1, at UTC time 5 pm (local time 2 pm)
Message 2, sent in august 1, at UTC time 5 pm (local time 1 pm)
Then, if I create the plot on august 2, converting those UTC dates to local would give me: "2 messages where sent at 1 pm", which is erratic information!
From the timezone tag wiki here on StackOverflow:
TimeZone != Offset
A time zone can not be represented solely by an offset from UTC. Many
time zones have more than one offset due to "daylight savings time" or
"summer time" rules. The dates that offsets change are also part of
the rules for the time zone, as are any historical offset changes.
Many software programs, libraries, and web services disregard this
important detail, and erroneously call the standard or current offset
the "zone". This can lead to confusion, and misuse of the data. Please
use the correct terminology whenever possible.
There are two commonly used database, the Microsoft Windows time zone db, and the IANA/Olson time zone db. See the wiki for more detail.
Your specific questions:
the "timezone" is just the number representing the offset? that is: my country has two timezones? or the timezone includes this information?
You have one "time zone". It includes two "offsets".
Should I, instead, be saving the dates with local timezone and saving their offset (at the moment of saving) too?
If you are recording the precise moment an event occurred or will occur, then you should store the offset of that particular time with it. In .Net and SQL Server, this is represented using a DateTimeOffset. There are similar datatypes in other platforms. It only contains the offset information - not the time zone that the offset originated from. Commonly, it is serialized in ISO8601 format, such as:
2013-05-09T13:29:00-04:00
If you might need to edit that time, then you cannot just store the offset. Somewhere in your system, you also need to have the time zone identifier. Otherwise, you have no way to determine what the new offset should be after the edit is made. If you desire, you can store this with the value itself. Some platforms have objects for exactly this purpose - such as ZonedDateTime in NodaTime. Example:
2013-05-09T13:29:00-04:00 America/New_York
Even when storing the zone id, you still need to record the offset. This is to resolve ambiguity during a "fall-back" transition from a daylight offset to a standard offset.
Alternatively, you could store the time at UTC with the time zone name:
2013-05-09T17:29:00Z America/New_York
This would work just as well, but you'd have to apply the time zone before displaying the value to anyone. TIMESTAMP WITH TIME ZONE in Oracle and PostgreSQL work this way.
You can read more about this in this post, while .Net focused - the idea is applicable to other platforms as well. The example problem you gave is what I call "maintaining the perspective of the observer" - which is discussed in the same article.
that is: my country has two timezones? or the timezone includes this information?
The term "timezone" usually includes that information. For example, in Java, "TimeZone represents a time zone offset, and also figures out daylight savings" (link), and on Unix-like systems, the tz database contains DST information.
However, for a single timestamp, I think it's more common to give just a UTC offset than a complete time-zone identifier.
[…] in my database.
Naturally, you should consult your database's documentation, or at least indicate what database you're using, and what tools (e.g., what drivers, what languages) you're using to access it.
Here's an example of a very popular format for describing timezones (though not what Windows uses).
You can see that it's more than a simple offset. More along the lines of offsets and the set of rules (changing over time) for when to use which offset.
Task: Given every zipcode of locations in US, I need to get the exact utf_timeoffset and exact dst(daytime savings offset), but I can ignore zip_code belonging to AP/FPO/DPO.
I need take into account of the timezone differences inside each state, and also need care about the exception of Hawaii, Arizona and several zipcode in PR, VI when it comes to daylight savings between Mar 11 2013, 2:00 and Nov 3 2013, 2:00.
I wonder if there is a standard module existing in Pytz(the famous timezone s/w package), because I can't located any proper function with zip_code parameter. Besides, I am perfectly fine with other package than pytz, and also any other programming languages other than Python.
At the same time, with some handmade code, I have managed to get "time_zone name" and "utf_time offset" for each zip_code. Based on provision of some websites, I also managed to get a copy of dataset containing zip_code and their daylight savings flag. A.K.A the current dst policy for each zip_code in US)
So far It works fine, but I dont really trust my own code, didn't get a way to validate its correctness.
No, pytz do not have such a functionality. See also: Mapping US zip code to time zone
Do you have the option to use the raw ZIP code data? Because if you do, it might be very helpful to use a zip code database such as the kind you would find here. They have the ZIP code associated with specific time zones as well as daylight savings info for each one. Looks like the annual price is currently $139 for 12 monthly updates.
I don't work there but I know a lot about ZIP codes and addresses since I work at SmartyStreets.
I'm building an application which will be able to send emails at any specific local time to any place in the world.
For example, my daily schedule (localtime):
8:00 AM - Send email to John in Toronto, Canada
9:15 AM Western Standard Time (Australia) - Send email to Bob in Perth, Australia
10:12 PM - Send email to Anas in Rabat, Morocco
I want to be able to execute this code on and Amazon EC2 server in a single location (e.g. São Paulo, Brasil).
I also know that Toronto is in Eastern Standard Time, (UTC - 5h) , but from March 11, 2012 to November 4, 2012, it is in Eastern Daylight Time (UTC - 4h).
I also know that Perth is in Western Standard Time (UTC + 8h), with no daylight savings.
I also know that Rabat is in Western European Time (UTC), but from April 29,2012 to July 20,2012, and August 19,2012 to Sept 30, 2012 it is in in West European Summer Time (UTC + 1h)
To keep track of these combinations of time zone, daylight savings, et cetera, I will, of course insist that all internal server times be in UTC. However, I need some way to keep track of when and how each time-zone jurisdiction switches time zones because of Daylight Savings or (in the case of Rabat) Ramadan, and then adjust my crontabs to accommodate these changes.
Is there an authoritative web service or set of tables somewhere which would help me keep these timezone changes in sync with my desire to deliver emails at the same local time every day to users in different time zones with different switchover dates for daylight savings?
Most programming languages give you access to timezone conversion functions. The most rudimentary ones only work between UTC and the "local" timezone of the server, so you will need a full-featured one, such as pytz for Python that will let you specify a local time with a timezone name (e.g. "America/Toronto") and convert it to UTC for you. Given that, you don't need to worry about the UTC offsets of different timezones (including historical offsets if they've changed) nor DST start end end times: the library will take care of it for you. Just make sure you have the latest database, which comes in the tzdata package.
As for your crontab, you're probably best off if the local timezone on the server that runs cron is UTC, that way you can put UTC times directly in the crontab. On the other hand, depending on the volume of events that you have, I would advice just having cron run your code at regular schedules intervals (such as every 5 minutes) and then your code figures out what events need to be triggered based on the current UTC time and the contents of your database. Then it doesn't matter what the timezone of the server is.
Is there an authoritative web service or set of tables somewhere ...
No, there is nothing "authoritative", but there is something close. It's called the TZ database, and it is currently under the oversight of IANA. Its home page is here.
It is also known as tzdata, zoneinfo, timezonedb, tzdb, the Olson Database, or the IANA Time Zone Database.
There are implementations for just about every language and platform you can imagine. You can read more in the tz-link file from the tzdb, and in the timezone tag wiki, here on StackOverflow.