/// <summary> /// Creates a hash table node with all the information for this period. /// We start off by finding the interval for the start of the period, and /// then repeatedly check whether that interval ends after the end of the /// period - at which point we're done. If not, find the next interval, create /// a new node referring to that interval and the previous interval, and keep going. /// </summary> internal static HashCacheNode CreateNode(int period, IZoneIntervalMap map) { var periodStart = new Instant((long)period << PeriodShift); var periodEnd = new Instant((long)(period + 1) << PeriodShift); var interval = map.GetZoneInterval(periodStart); var node = new HashCacheNode(interval, period, null); // Keep going while the current interval ends before the period. while (interval.End < periodEnd) { interval = map.GetZoneInterval(interval.End); node = new HashCacheNode(interval, period, node); } return(node); }
/// <summary> /// Gets the zone offset period for the given instant. Null is returned if no period is /// defined by the time zone for the given instant. /// </summary> /// <param name="instant">The Instant to test.</param> /// <returns>The defined ZoneOffsetPeriod or null.</returns> public ZoneInterval GetZoneInterval(Instant instant) { int period = instant.DaysSinceEpoch >> PeriodShift; int index = period & CachePeriodMask; var node = instantCache[index]; if (node == null || node.Period != period) { node = HashCacheNode.CreateNode(period, map); instantCache[index] = node; } // Note: moving this code into an instance method in HashCacheNode makes a surprisingly // large performance difference. while (node.Previous != null && node.Interval.RawStart > instant) { node = node.Previous; } return(node.Interval); }
/// <summary> /// Creates a hash table node with all the information for this period. /// We start off by finding the interval for the start of the period, and /// then repeatedly check whether that interval ends after the end of the /// period - at which point we're done. If not, find the next interval, create /// a new node referring to that interval and the previous interval, and keep going. /// </summary> internal static HashCacheNode CreateNode(int period, IZoneIntervalMap map) { var days = period << PeriodShift; var periodStart = new Instant(new Duration(Math.Max(days, Instant.MinDays), 0L)); var nextPeriodStartDays = days + (1 << PeriodShift); var interval = map.GetZoneInterval(periodStart); var node = new HashCacheNode(interval, period, null); // Keep going while the current interval ends before the period. // (We only need to check the days, as every period lands on a // day boundary.) // If the raw end is the end of time, the condition will definitely // evaluate to false. while (interval.RawEnd.DaysSinceEpoch < nextPeriodStartDays) { interval = map.GetZoneInterval(interval.End); node = new HashCacheNode(interval, period, node); } return(node); }
/// <summary> /// Initializes a new instance of the <see cref="HashCacheNode"/> class. /// </summary> /// <param name="interval">The zone interval.</param> /// <param name="period"></param> /// <param name="previous">The previous <see cref="HashCacheNode"/> node.</param> private HashCacheNode(ZoneInterval interval, int period, HashCacheNode previous) { this.Period = period; this.Interval = interval; this.Previous = previous; }
/// <summary> /// Initializes a new instance of the <see cref="HashCacheNode"/> class. /// </summary> /// <param name="interval">The zone interval.</param> /// <param name="period"></param> /// <param name="previous">The previous <see cref="HashCacheNode"/> node.</param> private HashCacheNode(ZoneInterval interval, int period, HashCacheNode previous) { this.Period = period; this.Interval = interval; this.Previous = previous; }
/// <summary> /// Creates a hash table node with all the information for this period. /// We start off by finding the interval for the start of the period, and /// then repeatedly check whether that interval ends after the end of the /// period - at which point we're done. If not, find the next interval, create /// a new node referring to that interval and the previous interval, and keep going. /// </summary> internal static HashCacheNode CreateNode(int period, IZoneIntervalMap map) { var days = period << PeriodShift; var periodStart = new Instant(new Duration(Math.Max(days, Instant.MinDays), 0L)); var nextPeriodStartDays = days + (1 << PeriodShift); var interval = map.GetZoneInterval(periodStart); var node = new HashCacheNode(interval, period, null); // Keep going while the current interval ends before the period. // (We only need to check the days, as every period lands on a // day boundary.) // If the raw end is the end of time, the condition will definitely // evaluate to false. while (interval.RawEnd.DaysSinceEpoch < nextPeriodStartDays) { interval = map.GetZoneInterval(interval.End); node = new HashCacheNode(interval, period, node); } return node; }
/// <summary> /// Creates a hash table node with all the information for this period. /// We start off by finding the interval for the start of the period, and /// then repeatedly check whether that interval ends after the end of the /// period - at which point we're done. If not, find the next interval, create /// a new node referring to that interval and the previous interval, and keep going. /// </summary> internal static HashCacheNode CreateNode(int period, DateTimeZone zone) { var periodStart = new Instant((long)period << PeriodShift); var periodEnd = new Instant((long)(period + 1) << PeriodShift); var interval = zone.GetZoneInterval(periodStart); var node = new HashCacheNode(interval, period, null); // Keep going while the current interval ends before the period. while (interval.End < periodEnd) { interval = zone.GetZoneInterval(interval.End); node = new HashCacheNode(interval, period, node); } return node; }