17 using System.Collections.Generic;
19 using System.Runtime.CompilerServices;
21 using NodaTime.TimeZones;
32 private static readonly
long DateTimeMaxValueTicks = DateTime.MaxValue.Ticks;
34 private long _nextDiscontinuity;
35 private long _currentOffsetTicks;
36 private readonly DateTimeZone _timeZone;
37 private readonly Queue<long> _discontinuities;
44 get {
return _timeZone; }
60 utcEndTime += TimeSpan.FromDays(2*365);
62 var start = DateTimeZone.Utc.AtLeniently(LocalDateTime.FromDateTime(utcStartTime));
63 var end = DateTimeZone.Utc.AtLeniently(LocalDateTime.FromDateTime(utcEndTime));
64 var zoneIntervals = _timeZone.GetZoneIntervals(start.ToInstant(), end.ToInstant()).ToList();
68 if (zoneIntervals.Count == 1 && zoneIntervals[0].HasStart && zoneIntervals[0].Start == Instant.MinValue && zoneIntervals[0].End == Instant.MaxValue)
71 _discontinuities =
new Queue<long>();
72 _nextDiscontinuity = DateTime.MaxValue.Ticks;
73 _currentOffsetTicks = _timeZone.GetUtcOffset(Instant.FromDateTimeUtc(DateTime.UtcNow)).Ticks;
78 _discontinuities =
new Queue<long>(zoneIntervals.Select(GetDateTimeUtcTicks));
79 _nextDiscontinuity = _discontinuities.Dequeue();
80 _currentOffsetTicks = _timeZone.GetUtcOffset(Instant.FromDateTimeUtc(
new DateTime(_nextDiscontinuity - 1, DateTimeKind.Utc))).Ticks;
89 [MethodImpl(MethodImplOptions.AggressiveInlining)]
93 while (utcTime.Ticks >= _nextDiscontinuity && _nextDiscontinuity != DateTimeMaxValueTicks)
96 _nextDiscontinuity = _discontinuities.Count == 0
97 ? DateTime.MaxValue.Ticks
98 : _discontinuities.Dequeue();
101 var offset = _timeZone.GetUtcOffset(Instant.FromDateTimeUtc(
new DateTime(_nextDiscontinuity - 1, DateTimeKind.Utc)));
102 _currentOffsetTicks = offset.Ticks;
105 return _currentOffsetTicks;
113 [MethodImpl(MethodImplOptions.AggressiveInlining)]
120 var currentEndTimeTicks = localTime.Ticks;
121 var currentEndTimeUtc =
new DateTime(currentEndTimeTicks - _currentOffsetTicks);
123 var emitTimeUtcTicks = currentEndTimeTicks - offsetTicks;
124 while (emitTimeUtcTicks > _nextDiscontinuity)
128 emitTimeUtcTicks = currentEndTimeTicks - offsetTicks;
131 return new DateTime(emitTimeUtcTicks);
140 return _nextDiscontinuity;
149 [MethodImpl(MethodImplOptions.AggressiveInlining)]
158 private static long GetDateTimeUtcTicks(ZoneInterval zoneInterval)
163 if (!zoneInterval.HasStart || zoneInterval.Start == Instant.MinValue)
return 1;
164 if (zoneInterval.HasStart && zoneInterval.Start == Instant.MaxValue)
return DateTime.MaxValue.Ticks;
165 if (zoneInterval.HasStart)
return zoneInterval.Start.ToDateTimeUtc().Ticks;