/// <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         = Instant.FromTrustedDuration(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);
                }