-
Notifications
You must be signed in to change notification settings - Fork 247
Make the time zone resolver plugable #732
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
e6d3cb7
Test: Update affected test cases to use well-known time zones to avoi…
minichma 96e3358
Stop resolving unknown tzids to the local timezone.
minichma ea2bcf2
Move time zone resolving logic to `DefaultTimeZoneResolver`
minichma 1937bbc
Make time zone resolving configurable.
minichma File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,7 @@ BEGIN:VCALENDAR | |
| PRODID:-//Microsoft Corporation//Outlook 11.0 MIMEDIR//EN VERSION:2.0 | ||
| METHOD:PUBLISH | ||
| BEGIN:VTIMEZONE | ||
| TZID:Sarajewo, Skopie, Warszawa, Zagrzeb | ||
| TZID:Europe/Warsaw | ||
| BEGIN:STANDARD | ||
| DTSTART:20071028T030000 | ||
| RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10 | ||
|
|
@@ -20,8 +20,8 @@ END:DAYLIGHT | |
| END:VTIMEZONE | ||
| BEGIN:VEVENT | ||
| ORGANIZER:MAILTO:[email protected] | ||
| DTSTART;TZID="Sarajewo, Skopie, Warszawa, Zagrzeb":20080103T170000 | ||
| DTEND;TZID="Sarajewo, Skopie, Warszawa, Zagrzeb":20080103T173000 | ||
| DTSTART;TZID="Europe/Warsaw":20080103T170000 | ||
| DTEND;TZID="Europe/Warsaw":20080103T173000 | ||
| RRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=TH;WKST=MO | ||
| TRANSP:OPAQUE | ||
| SEQUENCE:0 | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| // | ||
| // Copyright ical.net project maintainers and contributors. | ||
| // Licensed under the MIT license. | ||
| // | ||
|
|
||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Threading; | ||
| using NodaTime; | ||
| using NodaTime.TimeZones; | ||
|
|
||
| namespace Ical.Net; | ||
|
|
||
| public static class DefaultTimeZoneResolver | ||
| { | ||
| private static Dictionary<string, string> InitializeWindowsMappings() | ||
| => TzdbDateTimeZoneSource.Default.WindowsMapping.PrimaryMapping | ||
| .ToDictionary(k => k.Key, v => v.Value, StringComparer.OrdinalIgnoreCase); | ||
|
|
||
| private static readonly Lazy<Dictionary<string, string>> _windowsMapping | ||
| = new Lazy<Dictionary<string, string>>(InitializeWindowsMappings, LazyThreadSafetyMode.PublicationOnly); | ||
|
|
||
| /// <summary> | ||
| /// Use this method to turn a raw string into a NodaTime DateTimeZone. It searches all time zone providers (IANA, BCL, serialization, etc) to see if | ||
| /// the string matches. If it doesn't, it walks each provider, and checks to see if the time zone the provider knows about is contained within the | ||
| /// target time zone string. Some older icalendar programs would generate nonstandard time zone strings, and this secondary check works around | ||
| /// that. | ||
minichma marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /// </summary> | ||
| /// <param name="tzId">A BCL, IANA, or serialization time zone identifier</param> | ||
| /// <exception cref="ArgumentException">Processing failed</exception> | ||
| /// <remarks>The DateTimeZone if found or null otherwise.</remarks> | ||
| public static DateTimeZone GetZone(string tzId) | ||
| { | ||
| var exMsg = $"Unrecognized time zone id {tzId}"; | ||
|
|
||
| if (string.IsNullOrWhiteSpace(tzId)) | ||
| { | ||
| return DateTimeZoneProviders.Tzdb.GetSystemDefault(); | ||
| } | ||
|
|
||
| if (tzId.StartsWith("/", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| tzId = tzId.Substring(1, tzId.Length - 1); | ||
| } | ||
|
|
||
| var zone = DateTimeZoneProviders.Tzdb.GetZoneOrNull(tzId); | ||
| if (zone != null) | ||
| { | ||
| return zone; | ||
| } | ||
|
|
||
| if (_windowsMapping.Value.TryGetValue(tzId, out var ianaZone)) | ||
| { | ||
| return DateTimeZoneProviders.Tzdb.GetZoneOrNull(ianaZone) ?? throw new ArgumentException(exMsg); | ||
| } | ||
|
|
||
| zone = NodaTime.Xml.XmlSerializationSettings.DateTimeZoneProvider.GetZoneOrNull(tzId); | ||
| if (zone != null) | ||
| { | ||
| return zone; | ||
| } | ||
|
|
||
| // US/Eastern is commonly represented as US-Eastern | ||
| var newTzId = tzId.Replace("-", "/"); | ||
| zone = NodaTime.Xml.XmlSerializationSettings.DateTimeZoneProvider.GetZoneOrNull(newTzId); | ||
| if (zone != null) | ||
| { | ||
| return zone; | ||
| } | ||
|
|
||
| var providerId = DateTimeZoneProviders.Tzdb.Ids.FirstOrDefault(tzId.Contains); | ||
| if (providerId != null) | ||
| { | ||
| return DateTimeZoneProviders.Tzdb.GetZoneOrNull(providerId) ?? throw new ArgumentException(exMsg); | ||
| } | ||
|
|
||
| if (_windowsMapping.Value.Keys | ||
| .Where(tzId.Contains) | ||
| .Any(pId => _windowsMapping.Value.TryGetValue(pId, out ianaZone)) | ||
| ) | ||
| { | ||
| return DateTimeZoneProviders.Tzdb.GetZoneOrNull(ianaZone!) ?? throw new ArgumentException(exMsg); | ||
| } | ||
|
|
||
| providerId = NodaTime.Xml.XmlSerializationSettings.DateTimeZoneProvider.Ids.FirstOrDefault(tzId.Contains); | ||
| if (providerId != null) | ||
| { | ||
| return NodaTime.Xml.XmlSerializationSettings.DateTimeZoneProvider.GetZoneOrNull(providerId) ?? throw new ArgumentException(exMsg); | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| internal static readonly DateTimeZone LocalDateTimeZone = DateTimeZoneProviders.Tzdb.GetSystemDefault(); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| // | ||
| // Copyright ical.net project maintainers and contributors. | ||
| // Licensed under the MIT license. | ||
| // | ||
|
|
||
| using System; | ||
| using NodaTime; | ||
|
|
||
| namespace Ical.Net; | ||
|
|
||
| public static class TimeZoneResolvers | ||
| { | ||
| /// <summary> | ||
| /// The default time zone resolver. | ||
| /// </summary> | ||
| public static Func<string, DateTimeZone> Default => tzId => DefaultTimeZoneResolver.GetZone(tzId); | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets a function that returns the NodaTime DateTimeZone for the given TZID. | ||
| /// </summary> | ||
| public static Func<string, DateTimeZone> TimeZoneResolver { get; set; } = Default; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍