Beispiel #1
0
        public bool TryGetNext(DateTimeOffset value, TimeZoneInfo tz, out DateTimeOffset result)
        {
            if (tz is null)
            {
                throw new ArgumentNullException(nameof(tz));
            }

            result = DateTimeOffset.MinValue;
            var current       = value.DateTime;
            var acceptCurrent = false;

            // vixie cron + wikipedia
            if (tz.IsAmbiguousTime(value))
            {
                var periodEnd       = tz.GetCurrentPeriodEnd(current);
                var periodEndOffset = periodEnd.Offset;
                var periodEndValue  = periodEnd.DateTime;
                var otherOffset     = tz.GetOtherAmbigousOffset(periodEnd);

                // is DST?
                if (otherOffset != value.Offset)
                {
                    if (!TryGetNextInstant(current, acceptCurrent, out var guess))
                    {
                        return(false);
                    }
                    if (guess < periodEndValue)
                    {
                        result = new DateTimeOffset(guess, periodEndOffset);
                        return(true);
                    }

                    // start of the ambigous period
                    // Magadan Standard Time has +11 as base,
                    // but they shifted from 12 to 10 at 2014, 10, 26, 0, 0, 0
                    current       = periodEnd.ToOffset(otherOffset).DateTime;
                    acceptCurrent = true;
                }

                if (hasInterval)
                {
                    // iterate the transition period
                    if (!TryGetNextInstant(current, acceptCurrent, out var guess))
                    {
                        return(false);
                    }
                    if (guess < periodEndValue)
                    {
                        result = new DateTimeOffset(guess, otherOffset);
                        return(true);
                    }
                }

                current       = periodEndValue;
                acceptCurrent = true;
            }

            while (true)
            {
                if (!TryGetNextInstant(current, acceptCurrent, out var retval))
                {
                    return(false);
                }

                if (tz.IsInvalidTime(retval))
                {
                    current = retval;
                    continue;
                }

                result = tz.IsAmbiguousTime(retval)
                                                        ? new DateTimeOffset(retval, tz.GetCurrentPeriodEnd(retval).Offset)
                                                        : new DateTimeOffset(retval, tz.GetUtcOffset(retval));

                return(true);
            }
        }