internal PrecalculatedDateTimeZone([NotNull] string id, [NotNull] ZoneInterval[] intervals, IZoneIntervalMapWithMinMax tailZone)
     : base(id, false,
            ComputeOffset(intervals, tailZone, Offset.Min),
            ComputeOffset(intervals, tailZone, Offset.Max))
 {
     this.periods       = intervals;
     this.tailZone      = tailZone;
     this.tailZoneStart = intervals[intervals.Length - 1].RawEnd; // We want this to be AfterMaxValue for tail-less zones.
     if (tailZone != null)
     {
         // Cache a "clamped" zone interval for use at the start of the tail zone.
         firstTailZoneInterval = tailZone.GetZoneInterval(tailZoneStart).WithStart(tailZoneStart);
     }
     ValidatePeriods(intervals, tailZone);
 }
 internal PrecalculatedDateTimeZone([NotNull] string id, [NotNull] ZoneInterval[] intervals, IZoneIntervalMapWithMinMax tailZone)
     : base(id, false,
            ComputeOffset(intervals, tailZone, Offset.Min),
            ComputeOffset(intervals, tailZone, Offset.Max))
 {
     this.tailZone = tailZone;
     this.periods = intervals;
     this.tailZone = tailZone;
     this.tailZoneStart = intervals[intervals.Length - 1].RawEnd; // We want this to be AfterMaxValue for tail-less zones.
     if (tailZone != null)
     {
         // Cache a "clamped" zone interval for use at the start of the tail zone.
         firstTailZoneInterval = tailZone.GetZoneInterval(tailZoneStart).WithStart(tailZoneStart);
     }
     ValidatePeriods(intervals, tailZone);
 }
        // Reasonably simple way of computing the maximum/minimum offset
        // from either periods or transitions, with or without a tail zone.
        private static Offset ComputeOffset([NotNull] ZoneInterval[] intervals,
                                            IZoneIntervalMapWithMinMax tailZone,
                                            OffsetAggregator aggregator)
        {
            Preconditions.CheckNotNull(intervals, nameof(intervals));
            Preconditions.CheckArgument(intervals.Length > 0, nameof(intervals), "No intervals specified");
            Offset ret = intervals[0].WallOffset;

            for (int i = 1; i < intervals.Length; i++)
            {
                ret = aggregator(ret, intervals[i].WallOffset);
            }
            if (tailZone != null)
            {
                // Effectively a shortcut for picking either tailZone.MinOffset or
                // tailZone.MaxOffset
                Offset bestFromZone = aggregator(tailZone.MinOffset, tailZone.MaxOffset);
                ret = aggregator(ret, bestFromZone);
            }
            return(ret);
        }
 // Reasonably simple way of computing the maximum/minimum offset
 // from either periods or transitions, with or without a tail zone.
 private static Offset ComputeOffset([NotNull] ZoneInterval[] intervals,
     IZoneIntervalMapWithMinMax tailZone,
     OffsetAggregator aggregator)
 {
     Preconditions.CheckNotNull(intervals, nameof(intervals));
     Preconditions.CheckArgument(intervals.Length > 0, nameof(intervals), "No intervals specified");
     Offset ret = intervals[0].WallOffset;
     for (int i = 1; i < intervals.Length; i++)
     {
         ret = aggregator(ret, intervals[i].WallOffset);
     }
     if (tailZone != null)
     {
         // Effectively a shortcut for picking either tailZone.MinOffset or
         // tailZone.MaxOffset
         Offset bestFromZone = aggregator(tailZone.MinOffset, tailZone.MaxOffset);
         ret = aggregator(ret, bestFromZone);
     }
     return ret;
 }