My favorites | Sign in
Project Home Issues Source
Repository:
Checkout   Browse   Changes   Clones  
Changes to /src/NodaTime/TimeZones/BclDateTimeZone.cs
bcc19cf8038f vs. 3a941b53ba9c Compare: vs.  Format:
Revision 3a941b53ba9c
Go to: 
Project members, sign in to write a code review
/src/NodaTime/TimeZones/BclDateTimeZone.cs   bcc19cf8038f /src/NodaTime/TimeZones/BclDateTimeZone.cs   3a941b53ba9c
1 #region Copyright and license information 1 #region Copyright and license information
2 // Copyright 2001-2009 Stephen Colebourne 2 // Copyright 2001-2009 Stephen Colebourne
3 // Copyright 2009-2012 Jon Skeet 3 // Copyright 2009-2012 Jon Skeet
4 // 4 //
5 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License. 6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at 7 // You may obtain a copy of the License at
8 // 8 //
9 // http://www.apache.org/licenses/LICENSE-2.0 9 // http://www.apache.org/licenses/LICENSE-2.0
10 // 10 //
11 // Unless required by applicable law or agreed to in writing, software 11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS, 12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and 14 // See the License for the specific language governing permissions and
15 // limitations under the License. 15 // limitations under the License.
16 #endregion 16 #endregion
17 17
18 using System; 18 using System;
19 using System.Collections.Generic; 19 using System.Collections.Generic;
20 using NodaTime.Utility; 20 using NodaTime.Utility;
21 21
22 namespace NodaTime.TimeZones 22 namespace NodaTime.TimeZones
23 { 23 {
24 /// <summary> 24 /// <summary>
25 /// Representation of a time zone converted from a <see cref="TimeZoneInfo"/> from the Base Class Library. 25 /// Representation of a time zone converted from a <see cref="TimeZoneInfo"/> from the Base Class Library.
26 /// </summary> 26 /// </summary>
27 /// <threadsafety>This type is immutable reference type. See the thread safety section of the user guide for more information.</threadsafety> 27 /// <threadsafety>This type is immutable reference type. See the thread safety section of the user guide for more information.</threadsafety>
28 public sealed class BclDateTimeZone : DateTimeZone 28 public sealed class BclDateTimeZone : DateTimeZone
29 { 29 {
30 private static readonly int TypeInitializationChecking = NodaTime.Utility.TypeInitializationChecker.RecordInitializationStart(); 30 private static readonly int TypeInitializationChecking = NodaTime.Utility.TypeInitializationChecker.RecordInitializationStart();
31 31
32 /// <summary> 32 /// <summary>
33 /// This is used to cache the last result of a call to <see cref="ForSystemDefault"/>, but it doesn't 33 /// This is used to cache the last result of a call to <see cref="ForSystemDefault"/>, but it doesn't
34 /// matter if it's out of date - we'll just create another wrapper if necessary. It's not *that* expensive to make 34 /// matter if it's out of date - we'll just create another wrapper if necessary. It's not *that* expensive to make
35 /// a few more wrappers than we need. 35 /// a few more wrappers than we need.
36 /// </summary> 36 /// </summary>
37 private static BclDateTimeZone systemDefault; 37 private static BclDateTimeZone systemDefault;
38 38
39 private readonly TimeZoneInfo bclZone; 39 private readonly TimeZoneInfo bclZone;
40 private readonly List<AdjustmentInterval> adjustmentIntervals; 40 private readonly List<AdjustmentInterval> adjustmentIntervals;
41 private readonly ZoneInterval headInterval; 41 private readonly ZoneInterval headInterval;
42 42
43 /// <summary> 43 /// <summary>
44 /// Returns the original <see cref="TimeZoneInfo"/> from which this was created. 44 /// Returns the original <see cref="TimeZoneInfo"/> from which this was created.
45 /// </summary> 45 /// </summary>
46 public TimeZoneInfo OriginalZone { get { return bclZone; } } 46 public TimeZoneInfo OriginalZone { get { return bclZone; } }
47 47
48 /// <summary> 48 /// <summary>
49 /// Returns the display name associated with the time zone, as provided by the Base Class Library. 49 /// Returns the display name associated with the time zone, as provided by the Base Class Library.
50 /// </summary> 50 /// </summary>
51 public string DisplayName { get { return OriginalZone.DisplayName; } } 51 public string DisplayName { get { return OriginalZone.DisplayName; } }
52 52
53 private BclDateTimeZone(TimeZoneInfo bclZone, Offset minOffset, Offset maxOffset, List<AdjustmentInterval> adjustmentIntervals, ZoneInterval headInterval) 53 private BclDateTimeZone(TimeZoneInfo bclZone, Offset minOffset, Offset maxOffset, List<AdjustmentInterval> adjustmentIntervals, ZoneInterval headInterval)
54 : base(bclZone.Id, bclZone.SupportsDaylightSavingTime, minOffset, maxOffset) 54 : base(bclZone.Id, bclZone.SupportsDaylightSavingTime, minOffset, maxOffset)
55 { 55 {
56 this.bclZone = bclZone; 56 this.bclZone = bclZone;
57 this.adjustmentIntervals = adjustmentIntervals; 57 this.adjustmentIntervals = adjustmentIntervals;
58 this.headInterval = headInterval; 58 this.headInterval = headInterval;
59 } 59 }
60 60
61 /// <summary> 61 /// <summary>
62 /// Returns the zone interval for the given instant in time. See <see cref="ZonedDateTime"/> for more details. 62 /// Returns the zone interval for the given instant in time. See <see cref="ZonedDateTime"/> for more details.
63 /// </summary> 63 /// </summary>
64 public override ZoneInterval GetZoneInterval(Instant instant) 64 public override ZoneInterval GetZoneInterval(Instant instant)
65 { 65 {
66 if (headInterval != null && headInterval.Contains(instant)) 66 if (headInterval != null && headInterval.Contains(instant))
67 { 67 {
68 return headInterval; 68 return headInterval;
69 } 69 }
70 // Avoid having to worry about Instant.MaxValue for the rest of the class. 70 // Avoid having to worry about Instant.MaxValue for the rest of the class.
71 if (instant == Instant.MaxValue) 71 if (instant == Instant.MaxValue)
72 { 72 {
73 return adjustmentIntervals[adjustmentIntervals.Count - 1].GetZoneInterval(instant); 73 return adjustmentIntervals[adjustmentIntervals.Count - 1].GetZoneInterval(instant);
74 } 74 }
75 75
76 int lower = 0; // Inclusive 76 int lower = 0; // Inclusive
77 int upper = adjustmentIntervals.Count; // Exclusive 77 int upper = adjustmentIntervals.Count; // Exclusive
78 78
79 while (lower < upper) 79 while (lower < upper)
80 { 80 {
81 int current = (lower + upper) / 2; 81 int current = (lower + upper) / 2;
82 var candidate = adjustmentIntervals[current]; 82 var candidate = adjustmentIntervals[current];
83 if (candidate.Start > instant) 83 if (candidate.Start > instant)
84 { 84 {
85 upper = current; 85 upper = current;
86 } 86 }
87 else if (candidate.End <= instant) 87 else if (candidate.End <= instant)
88 { 88 {
89 lower = current + 1; 89 lower = current + 1;
90 } 90 }
91 else 91 else
92 { 92 {
93 return candidate.GetZoneInterval(instant); 93 return candidate.GetZoneInterval(instant);
94 } 94 }
95 } 95 }
96 throw new InvalidOperationException 96 throw new InvalidOperationException
97 ("Instant " + instant + " did not exist in the range of adjustment intervals"); 97 ("Instant " + instant + " did not exist in the range of adjustment intervals");
98 } 98 }
99 99
100 /// <summary> 100 /// <summary>
101 /// Creates a new <see cref="BclDateTimeZone" /> from a <see cref="TimeZoneInfo"/> from the Base Class Library. 101 /// Creates a new <see cref="BclDateTimeZone" /> from a <see cref="TimeZoneInfo"/> from the Base Class Library.
102 /// </summary> 102 /// </summary>
103 /// <param name="bclZone">The original time zone to take information from.</param> 103 /// <param name="bclZone">The original time zone to take information from.</param>
104 /// <returns>A Noda Time representation of the given time zone.</returns> 104 /// <returns>A Noda Time representation of the given time zone.</returns>
105 /// <exception cref="ArgumentNullException"><paramref name="bclZone"/> is null.</exception> 105 /// <exception cref="ArgumentNullException"><paramref name="bclZone"/> is null.</exception>
106 public static BclDateTimeZone FromTimeZoneInfo(TimeZoneInfo bclZone) 106 public static BclDateTimeZone FromTimeZoneInfo(TimeZoneInfo bclZone)
107 { 107 {
108 Preconditions.CheckNotNull(bclZone, "bclZone"); 108 Preconditions.CheckNotNull(bclZone, "bclZone");
109 Offset standardOffset = Offset.FromTimeSpan(bclZone.BaseUtcOffset); 109 Offset standardOffset = Offset.FromTimeSpan(bclZone.BaseUtcOffset);
110 Offset minSavings = Offset.Zero; // Just in case we have negative savings! 110 Offset minSavings = Offset.Zero; // Just in case we have negative savings!
111 Offset maxSavings = Offset.Zero; 111 Offset maxSavings = Offset.Zero;
112 112
113 var rules = bclZone.GetAdjustmentRules(); 113 var rules = bclZone.GetAdjustmentRules();
114 if (!bclZone.SupportsDaylightSavingTime || rules.Length == 0) 114 if (!bclZone.SupportsDaylightSavingTime || rules.Length == 0)
115 { 115 {
116 var fixedInterval = new ZoneInterval(bclZone.StandardName, Instant.MinValue, Instant.MaxValue, standardOffset, Offset.Zero); 116 var fixedInterval = new ZoneInterval(bclZone.StandardName, Instant.MinValue, Instant.MaxValue, standardOffset, Offset.Zero);
117 return new BclDateTimeZone(bclZone, standardOffset, standardOffset, null, fixedInterval); 117 return new BclDateTimeZone(bclZone, standardOffset, standardOffset, null, fixedInterval);
118 } 118 }
119 var adjustmentIntervals = new List<AdjustmentInterval>(); 119 var adjustmentIntervals = new List<AdjustmentInterval>();
120 var headInterval = ComputeHeadInterval(bclZone, rules[0]); 120 var headInterval = ComputeHeadInterval(bclZone, rules[0]);
121 Instant previousEnd = headInterval != null ? headInterval.End : Instant.MinValue; 121 Instant previousEnd = headInterval != null ? headInterval.End : Instant.MinValue;
122 for (int i = 0; i < rules.Length; i++) 122 for (int i = 0; i < rules.Length; i++)
123 { 123 {
124 var rule = rules[i]; 124 var rule = rules[i];
125 ZoneRecurrence standard, daylight; 125 ZoneRecurrence standard, daylight;
126 GetRecurrences(bclZone, rule, out standard, out daylight); 126 GetRecurrences(bclZone, rule, out standard, out daylight);
127 127
128 minSavings = Offset.Min(minSavings, daylight.Savings); 128 minSavings = Offset.Min(minSavings, daylight.Savings);
129 maxSavings = Offset.Max(maxSavings, daylight.Savings); 129 maxSavings = Offset.Max(maxSavings, daylight.Savings);
130 130
131 // Find the last valid transition by working back from the end of time. It's safe to unconditionally 131 // Find the last valid transition by working back from the end of time. It's safe to unconditionally
132 // take the value here, as there must *be* some recurrences. 132 // take the value here, as there must *be* some recurrences.
133 var lastStandard = standard.PreviousOrFail(Instant.MaxValue, standardOffset, daylight.Savings); 133 // TODO(Post-V1): Tidy this up. We're basically fundamentally broken around the end of time :(
134 var lastDaylight = daylight.PreviousOrFail(Instant.MaxValue, standardOffset, Offset.Zero); 134 var oneDayBeforeTheEndOfTime = Instant.MaxValue - Duration.FromStandardDays(1);
135 var lastStandard = standard.PreviousOrFail(oneDayBeforeTheEndOfTime, standardOffset, daylight.Savings);
136 var lastDaylight = daylight.PreviousOrFail(oneDayBeforeTheEndOfTime, standardOffset, Offset.Zero);
135 bool standardIsLater = lastStandard.Instant > lastDaylight.Instant; 137 bool standardIsLater = lastStandard.Instant > lastDaylight.Instant;
136 Transition lastTransition = standardIsLater ? lastStandard : lastDaylight; 138 Transition lastTransition = standardIsLater ? lastStandard : lastDaylight;
137 Offset seamSavings = lastTransition.NewOffset - standardOffset; 139 Offset seamSavings = lastTransition.NewOffset - standardOffset;
138 string seamName = standardIsLater ? bclZone.StandardName : bclZone.DaylightName; 140 string seamName = standardIsLater ? bclZone.StandardName : bclZone.DaylightName;
139 141
140 Instant nextStart; 142 Instant nextStart;
141 // Now work out the new "previous end" - i.e. where the next adjustment interval will start. 143 // Now work out the new "previous end" - i.e. where the next adjustment interval will start.
142 if (i == rules.Length - 1) 144 if (i == rules.Length - 1)
143 { 145 {
144 nextStart = Instant.MaxValue; 146 nextStart = Instant.MaxValue;
145 } 147 }
146 else 148 else
147 { 149 {
148 var nextRule = rules[i + 1]; 150 var nextRule = rules[i + 1];
149 // TODO(Post-V1): Tidy this up (we do the same thing on the next iteration...) 151 // TODO(Post-V1): Tidy this up (we do the same thing on the next iteration...)
150 ZoneRecurrence nextStandard, nextDaylight; 152 ZoneRecurrence nextStandard, nextDaylight;
151 GetRecurrences(bclZone, nextRule, out nextStandard, out nextDaylight); 153 GetRecurrences(bclZone, nextRule, out nextStandard, out nextDaylight);
152 154
153 // If the "start of seam" transition is a transition into standard time, we want to find the 155 // If the "start of seam" transition is a transition into standard time, we want to find the
154 // first transition into daylight time in the new set of rules, and vice versa. Again, there 156 // first transition into daylight time in the new set of rules, and vice versa. Again, there
155 // must *be* a transition, as otherwise the rules are invalid. 157 // must *be* a transition, as otherwise the rules are invalid.
156 var firstRecurrence = standardIsLater ? nextDaylight : nextStandard; 158 var firstRecurrence = standardIsLater ? nextDaylight : nextStandard;
157 nextStart = firstRecurrence.NextOrFail(lastTransition.Instant, standardOffset, seamSavings).Instant; 159 nextStart = firstRecurrence.NextOrFail(lastTransition.Instant, standardOffset, seamSavings).Instant;
158 } 160 }
159 var seam = new ZoneInterval(seamName, lastTransition.Instant, nextStart, lastTransition.NewOffset, seamSavings); 161 var seam = new ZoneInterval(seamName, lastTransition.Instant, nextStart, lastTransition.NewOffset, seamSavings);
160 var adjustmentZone = new DaylightSavingsDateTimeZone("ignored", standardOffset, standard.ToInfinity(), daylight.ToInfinity()); 162 var adjustmentZone = new DaylightSavingsDateTimeZone("ignored", standardOffset, standard.ToInfinity(), daylight.ToInfinity());
161 163
162 adjustmentIntervals.Add(new AdjustmentInterval(previousEnd, adjustmentZone, seam)); 164 adjustmentIntervals.Add(new AdjustmentInterval(previousEnd, adjustmentZone, seam));
163 previousEnd = nextStart; 165 previousEnd = nextStart;
164 } 166 }
165 167
166 return new BclDateTimeZone(bclZone, standardOffset + minSavings, standardOffset + maxSavings, adjustmentIntervals, headInterval); 168 return new BclDateTimeZone(bclZone, standardOffset + minSavings, standardOffset + maxSavings, adjustmentIntervals, headInterval);
167 } 169 }
168 170
169 /// <summary> 171 /// <summary>
170 /// Work out the period of standard time (if any) before the first adjustment rule is applied. 172 /// Work out the period of standard time (if any) before the first adjustment rule is applied.
171 /// </summary> 173 /// </summary>
172 private static ZoneInterval ComputeHeadInterval(TimeZoneInfo zone, TimeZoneInfo.AdjustmentRule rule) 174 private static ZoneInterval ComputeHeadInterval(TimeZoneInfo zone, TimeZoneInfo.AdjustmentRule rule)
173 { 175 {
174 if (rule.DateStart.Year == 1) 176 if (rule.DateStart.Year == 1)
175 { 177 {
176 return null; 178 return null;
177 } 179 }
178 ZoneRecurrence firstStandard, firstDaylight; 180 ZoneRecurrence firstStandard, firstDaylight;
179 GetRecurrences(zone, rule, out firstStandard, out firstDaylight); 181 GetRecurrences(zone, rule, out firstStandard, out firstDaylight);
180 var standardOffset = Offset.FromTimeSpan(zone.BaseUtcOffset); 182 var standardOffset = Offset.FromTimeSpan(zone.BaseUtcOffset);
181 Transition firstTransition = firstDaylight.NextOrFail(Instant.MinValue, standardOffset, Offset.Zero); 183 Transition firstTransition = firstDaylight.NextOrFail(Instant.MinValue, standardOffset, Offset.Zero);
182 return new ZoneInterval(zone.StandardName, Instant.MinValue, firstTransition.Instant, standardOffset, Offset.Zero); 184 return new ZoneInterval(zone.StandardName, Instant.MinValue, firstTransition.Instant, standardOffset, Offset.Zero);
183 } 185 }
184 186
185 /// <summary> 187 /// <summary>
186 /// Converts the two adjustment rules in <paramref name="rule"/> into two ZoneRecurrences, 188 /// Converts the two adjustment rules in <paramref name="rule"/> into two ZoneRecurrences,
187 /// storing them in the out parameters. 189 /// storing them in the out parameters.
188 /// </summary> 190 /// </summary>
189 private static void GetRecurrences(TimeZoneInfo zone, TimeZoneInfo.AdjustmentRule rule, 191 private static void GetRecurrences(TimeZoneInfo zone, TimeZoneInfo.AdjustmentRule rule,
190 out ZoneRecurrence standardRecurrence, out ZoneRecurrence daylightRecurrence) 192 out ZoneRecurrence standardRecurrence, out ZoneRecurrence daylightRecurrence)
191 { 193 {
192 int startYear = rule.DateStart.Year == 1 ? int.MinValue : rule.DateStart.Year; 194 int startYear = rule.DateStart.Year == 1 ? int.MinValue : rule.DateStart.Year;
193 int endYear = rule.DateStart.Year == 9999 ? int.MaxValue : rule.DateStart.Year; 195 int endYear = rule.DateEnd.Year == 9999 ? int.MaxValue : rule.DateEnd.Year;
194 Offset daylightOffset = Offset.FromTimeSpan(rule.DaylightDelta); 196 Offset daylightOffset = Offset.FromTimeSpan(rule.DaylightDelta);
195 ZoneYearOffset daylightStart = ConvertTransition(rule.DaylightTransitionStart); 197 ZoneYearOffset daylightStart = ConvertTransition(rule.DaylightTransitionStart);
196 ZoneYearOffset daylightEnd = ConvertTransition(rule.DaylightTransitionEnd); 198 ZoneYearOffset daylightEnd = ConvertTransition(rule.DaylightTransitionEnd);
197 standardRecurrence = new ZoneRecurrence(zone.StandardName, Offset.Zero, daylightEnd, startYear, endYear); 199 standardRecurrence = new ZoneRecurrence(zone.StandardName, Offset.Zero, daylightEnd, startYear, endYear);
198 daylightRecurrence = new ZoneRecurrence(zone.DaylightName, daylightOffset, daylightStart, startYear, endYear); 200 daylightRecurrence = new ZoneRecurrence(zone.DaylightName, daylightOffset, daylightStart, startYear, endYear);
199 } 201 }
200 202
201 // Converts a TimeZoneInfo "TransitionTime" to a "ZoneYearOffset" - the two correspond pretty closely. 203 // Converts a TimeZoneInfo "TransitionTime" to a "ZoneYearOffset" - the two correspond pretty closely.
202 private static ZoneYearOffset ConvertTransition(TimeZoneInfo.TransitionTime transitionTime) 204 private static ZoneYearOffset ConvertTransition(TimeZoneInfo.TransitionTime transitionTime)
203 { 205 {
204 // Easy case - fixed day of the month. 206 // Easy case - fixed day of the month.
205 if (transitionTime.IsFixedDateRule) 207 if (transitionTime.IsFixedDateRule)
206 { 208 {
207 return new ZoneYearOffset(TransitionMode.Wall, transitionTime.Month, transitionTime.Day, 209 return new ZoneYearOffset(TransitionMode.Wall, transitionTime.Month, transitionTime.Day,
208 0, false, Offset.FromTimeSpan(transitionTime.TimeOfDay.TimeOfDay)); 210 0, false, Offset.FromTimeSpan(transitionTime.TimeOfDay.TimeOfDay));
209 } 211 }
210 212
211 // Floating: 1st Sunday in March etc. 213 // Floating: 1st Sunday in March etc.
212 int dayOfWeek = (int) BclConversions.ToIsoDayOfWeek(transitionTime.DayOfWeek); 214 int dayOfWeek = (int) BclConversions.ToIsoDayOfWeek(transitionTime.DayOfWeek);
213 int dayOfMonth; 215 int dayOfMonth;
214 bool advance; 216 bool advance;
215 // "Last" 217 // "Last"
216 if (transitionTime.Week == 5) 218 if (transitionTime.Week == 5)
217 { 219 {
218 advance = false; 220 advance = false;
219 dayOfMonth = -1; 221 dayOfMonth = -1;
220 } 222 }
221 else 223 else
222 { 224 {
223 advance = true; 225 advance = true;
224 // Week 1 corresponds to ">=1" 226 // Week 1 corresponds to ">=1"
225 // Week 2 corresponds to ">=8" etc 227 // Week 2 corresponds to ">=8" etc
226 dayOfMonth = (transitionTime.Week * 7) - 6; 228 dayOfMonth = (transitionTime.Week * 7) - 6;
227 } 229 }
228 return new ZoneYearOffset(TransitionMode.Wall, transitionTime.Month, dayOfMonth, 230 return new ZoneYearOffset(TransitionMode.Wall, transitionTime.Month, dayOfMonth,
229 dayOfWeek, advance, Offset.FromTimeSpan(transitionTime.TimeOfDay.TimeOfDay)); 231 dayOfWeek, advance, Offset.FromTimeSpan(transitionTime.TimeOfDay.TimeOfDay));
230 } 232 }
231 233
232 /// <summary> 234 /// <summary>
233 /// Interval covered by an adjustment rule. The start instant is that of the 235 /// Interval covered by an adjustment rule. The start instant is that of the
234 /// first transition reported by this rule, and the seam covers the gap between 236 /// first transition reported by this rule, and the seam covers the gap between
235 /// two adjustment rules. 237 /// two adjustment rules.
236 /// </summary> 238 /// </summary>
237 private class AdjustmentInterval 239 private class AdjustmentInterval
238 { 240 {
239 private readonly Instant start; 241 private readonly Instant start;
240 private readonly ZoneInterval seam; 242 private readonly ZoneInterval seam;
241 private readonly DaylightSavingsDateTimeZone adjustmentZone; 243 private readonly DaylightSavingsDateTimeZone adjustmentZone;
242 244
243 internal Instant Start { get { return start; } } 245 internal Instant Start { get { return start; } }
244 internal Instant End { get { return seam.End; } } 246 internal Instant End { get { return seam.End; } }
245 247
246 internal AdjustmentInterval(Instant start, DaylightSavingsDateTimeZone adjustmentZone, ZoneInterval seam) 248 internal AdjustmentInterval(Instant start, DaylightSavingsDateTimeZone adjustmentZone, ZoneInterval seam)
247 { 249 {
248 this.start = start; 250 this.start = start;
249 this.seam = seam; 251 this.seam = seam;
250 this.adjustmentZone = adjustmentZone; 252 this.adjustmentZone = adjustmentZone;
251 } 253 }
252 254
253 internal ZoneInterval GetZoneInterval(Instant instant) 255 internal ZoneInterval GetZoneInterval(Instant instant)
254 { 256 {
255 if (seam.Contains(instant)) 257 if (seam.Contains(instant))
256 { 258 {
257 return seam; 259 return seam;
258 } 260 }
259 return adjustmentZone.GetZoneInterval(instant); 261 return adjustmentZone.GetZoneInterval(instant);
260 } 262 }
261 } 263 }
262 264
263 /// <summary> 265 /// <summary>
264 /// Returns a time zone converted from the BCL representation of the system local time zone. 266 /// Returns a time zone converted from the BCL representation of the system local time zone.
265 /// If this method is called more than once, it may return the same reference multiple times if 267 /// If this method is called more than once, it may return the same reference multiple times if
266 /// the local time zone has not changed. 268 /// the local time zone has not changed.
267 /// </summary> 269 /// </summary>
268 /// <remarks> 270 /// <remarks>
269 /// When the source of a <see cref="DateTimeZoneCache"/> is set to an instance of <see cref="BclDateTimeZoneSource"/> it 271 /// When the source of a <see cref="DateTimeZoneCache"/> is set to an instance of <see cref="BclDateTimeZoneSource"/> it
270 /// is highly likely that <see cref="DateTimeZoneCache.GetSystemDefault"/> will succeed - but in 272 /// is highly likely that <see cref="DateTimeZoneCache.GetSystemDefault"/> will succeed - but in
271 /// rare cases (such as the set of system time zones changing after the source is installed, or the local zone 273 /// rare cases (such as the set of system time zones changing after the source is installed, or the local zone
272 /// not being a normal "system" one) it is possible that it wouldn't be mapped. By contrast, this method will 274 /// not being a normal "system" one) it is possible that it wouldn't be mapped. By contrast, this method will
273 /// always succeed. 275 /// always succeed.
274 /// </remarks> 276 /// </remarks>
275 /// <returns>A <see cref="BclDateTimeZone"/> wrapping the "local" (system) time zone as returned by 277 /// <returns>A <see cref="BclDateTimeZone"/> wrapping the "local" (system) time zone as returned by
276 /// <see cref="TimeZoneInfo.Local"/>.</returns> 278 /// <see cref="TimeZoneInfo.Local"/>.</returns>
277 public static BclDateTimeZone ForSystemDefault() 279 public static BclDateTimeZone ForSystemDefault()
278 { 280 {
279 TimeZoneInfo local = TimeZoneInfo.Local; 281 TimeZoneInfo local = TimeZoneInfo.Local;
280 BclDateTimeZone currentSystemDefault = systemDefault; 282 BclDateTimeZone currentSystemDefault = systemDefault;
281 283
282 // Cached copy is out of date - wrap a new one 284 // Cached copy is out of date - wrap a new one
283 if (currentSystemDefault == null || currentSystemDefault.OriginalZone != local) 285 if (currentSystemDefault == null || currentSystemDefault.OriginalZone != local)
284 { 286 {
285 currentSystemDefault = FromTimeZoneInfo(local); 287 currentSystemDefault = FromTimeZoneInfo(local);
286 systemDefault = currentSystemDefault; 288 systemDefault = currentSystemDefault;
287 } 289 }
288 // Always return our local variable; the variable may have changed again. 290 // Always return our local variable; the variable may have changed again.
289 return currentSystemDefault; 291 return currentSystemDefault;
290 } 292 }
291 293
292 /// <inheritdoc /> 294 /// <inheritdoc />
293 protected override bool EqualsImpl(DateTimeZone zone) 295 protected override bool EqualsImpl(DateTimeZone zone)
294 { 296 {
295 throw new NotImplementedException(); 297 throw new NotImplementedException();
296 } 298 }
297 299
298 /// <inheritdoc /> 300 /// <inheritdoc />
299 public override int GetHashCode() 301 public override int GetHashCode()
300 { 302 {
301 return OriginalZone.GetHashCode(); 303 return OriginalZone.GetHashCode();
302 } 304 }
303 } 305 }
304 } 306 }
Powered by Google Project Hosting