-
Notifications
You must be signed in to change notification settings - Fork 234
Working with time zones
When constructing a Calendar
, you may wish to give it a time zone. Behind the scenes, time zone operations use NodaTime to do the heavy lifting for date/time conversions, and any time zone string that NodaTime supports will work.
var calendar = new Calendar();
calendar.AddTimeZone(new VTimeZone("America/New_York"));
In the general case in date and time programming, it's not really possible to express rules about future times using UTC as your starting point if your target time zone isn't also UTC. Time zones are socio-political, and the rules change.
To that end, the solution is to express your CalDateTime
s with local time zones. Once you've done that, GetOccurrences()
will compute the recurrence set correctly.
var start = DateTime.Parse("2017-02-01 11:00");
var end = start.AddHours(1);
var dailyUntilSummer = new RecurrencePattern(FrequencyType.Daily, 1)
{
Until = DateTime.Parse("2017-07-01 12:00"),
};
var calendarEvent = new CalendarEvent
{
Start = new CalDateTime(start, "America/New_York"),
End = new CalDateTime(end, "America/New_York"),
RecurrenceRules = new List<RecurrencePattern> { dailyUntilSummer },
};
var calendar = new Calendar();
calendar.Events.Add(calendarEvent);
var occurrences = calendar.GetOccurrences(start, start.AddMonths(6))
.Select(o => new {Local = o.Period.StartTime, Utc = o.Period.StartTime.AsUtc})
.OrderBy(o => o.Local)
.ToList();
If you set a breakpoint after occurrences
, and look at its contents, you'll see that on March 12, the UTC time goes from 16:00 to 15:00 while the local time remains stable. On March 12, America/New_York went from UTC-5 to UTC-4 when the clocks changed:
{ Local = {3/10/2017 11:00:00 AM America/New_York}, Utc = {3/10/2017 4:00:00 PM} }
{ Local = {3/11/2017 11:00:00 AM America/New_York}, Utc = {3/11/2017 4:00:00 PM} }
{ Local = {3/12/2017 11:00:00 AM America/New_York}, Utc = {3/12/2017 3:00:00 PM} }
{ Local = {3/13/2017 11:00:00 AM America/New_York}, Utc = {3/13/2017 3:00:00 PM} }
Sometimes you may need to get a representation of a Start
or End
time to another time zone. You can do this with ToTimeZone()
, which does NOT change the time zone of the original CalDateTime
:
var calendarEvent = new CalendarEvent
{
Start = new CalDateTime(DateTime.Now, "America/New_York"), // IANA time zone
// ...
}
// but you want to know what time that is in Canberra, Australia:
var inCanberra = calendarEvent.Start.ToTimeZone("Australia/Canberra");
// You can also convert to time zones in different time zone databases:
// Libya Standard Time is a Windows time zone
var inLibya = calendarEvent.Start.ToTimeZone("Libya Standard Time");