Ejemplo n.º 1
0
        private ZoneInterval GetIntervalAfterGap(LocalInstant localInstant)
        {
            Instant      guess         = localInstant.MinusZeroOffset();
            ZoneInterval guessInterval = GetZoneInterval(guess);

            // If the local interval occurs before the zone interval we're looking at starts,
            // it's the one we're looking for. Otherwise, we need to find the next interval.
            if (localInstant.Minus(guessInterval.WallOffset) < guessInterval.RawStart)
            {
                return(guessInterval);
            }
            else
            {
                // Will definitely be valid - there can't be a gap after an infinite interval.
                return(GetZoneInterval(guessInterval.End));
            }
        }
Ejemplo n.º 2
0
        private ZoneInterval GetIntervalBeforeGap(LocalInstant localInstant)
        {
            Instant      guess         = localInstant.MinusZeroOffset();
            ZoneInterval guessInterval = GetZoneInterval(guess);

            // If the local interval occurs before the zone interval we're looking at starts,
            // we need to find the earlier one; otherwise this interval must come after the gap, and
            // it's therefore the one we want.
            if (localInstant.Minus(guessInterval.WallOffset) < guessInterval.RawStart)
            {
                return(GetZoneInterval(guessInterval.Start - Duration.Epsilon));
            }
            else
            {
                return(guessInterval);
            }
        }
Ejemplo n.º 3
0
        internal ZonedDateTime ResolveLocal(LocalDateTime localDateTime,
                                            [Trusted][NotNull] AmbiguousTimeResolver ambiguousResolver,
                                            [Trusted][NotNull] SkippedTimeResolver skippedResolver)
        {
            Preconditions.DebugCheckNotNull(ambiguousResolver, nameof(ambiguousResolver));
            Preconditions.DebugCheckNotNull(skippedResolver, nameof(skippedResolver));
            LocalInstant localInstant = localDateTime.ToLocalInstant();
            Instant      firstGuess   = localInstant.MinusZeroOffset();
            ZoneInterval interval     = GetZoneInterval(firstGuess);

            // Most of the time we'll go into here... the local instant and the instant
            // are close enough that we've found the right instant.
            if (interval.Contains(localInstant))
            {
                ZonedDateTime guessZoned = new ZonedDateTime(localDateTime.WithOffset(interval.WallOffset), this);
                ZoneInterval  earlier    = GetEarlierMatchingInterval(interval, localInstant);
                if (earlier != null)
                {
                    ZonedDateTime earlierZoned = new ZonedDateTime(localDateTime.WithOffset(earlier.WallOffset), this);
                    return(ambiguousResolver(earlierZoned, guessZoned));
                }
                ZoneInterval later = GetLaterMatchingInterval(interval, localInstant);
                if (later != null)
                {
                    ZonedDateTime laterZoned = new ZonedDateTime(localDateTime.WithOffset(later.WallOffset), this);
                    return(ambiguousResolver(guessZoned, laterZoned));
                }
                return(guessZoned);
            }
            else
            {
                // Our first guess was wrong. Either we need to change interval by one (either direction)
                // or we're in a gap.
                ZoneInterval earlier = GetEarlierMatchingInterval(interval, localInstant);
                if (earlier != null)
                {
                    return(new ZonedDateTime(localDateTime.WithOffset(earlier.WallOffset), this));
                }
                ZoneInterval later = GetLaterMatchingInterval(interval, localInstant);
                if (later != null)
                {
                    return(new ZonedDateTime(localDateTime.WithOffset(later.WallOffset), this));
                }
                return(skippedResolver(localDateTime, this, GetIntervalBeforeGap(localInstant), GetIntervalAfterGap(localInstant)));
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Returns complete information about how the given <see cref="LocalDateTime" /> is mapped in this time zone.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Mapping a local date/time to a time zone can give an unambiguous, ambiguous or impossible result, depending on
        /// time zone transitions. Use the return value of this method to handle these cases in an appropriate way for
        /// your use case.
        /// </para>
        /// <para>
        /// As an alternative, consider <see cref="ResolveLocal(LocalDateTime, ZoneLocalMappingResolver)"/>, which uses a caller-provided strategy to
        /// convert the <see cref="ZoneLocalMapping"/> returned here to a <see cref="ZonedDateTime"/>.
        /// </para>
        /// </remarks>
        /// <param name="localDateTime">The local date and time to map in this time zone.</param>
        /// <returns>A mapping of the given local date and time to zero, one or two zoned date/time values.</returns>
        public virtual ZoneLocalMapping MapLocal(LocalDateTime localDateTime)
        {
            LocalInstant localInstant = localDateTime.ToLocalInstant();
            Instant      firstGuess   = localInstant.MinusZeroOffset();
            ZoneInterval interval     = GetZoneInterval(firstGuess);

            // Most of the time we'll go into here... the local instant and the instant
            // are close enough that we've found the right instant.
            if (interval.Contains(localInstant))
            {
                ZoneInterval?earlier = GetEarlierMatchingInterval(interval, localInstant);
                if (earlier != null)
                {
                    return(new ZoneLocalMapping(this, localDateTime, earlier, interval, 2));
                }
                ZoneInterval?later = GetLaterMatchingInterval(interval, localInstant);
                if (later != null)
                {
                    return(new ZoneLocalMapping(this, localDateTime, interval, later, 2));
                }
                return(new ZoneLocalMapping(this, localDateTime, interval, interval, 1));
            }
            else
            {
                // Our first guess was wrong. Either we need to change interval by one (either direction)
                // or we're in a gap.
                ZoneInterval?earlier = GetEarlierMatchingInterval(interval, localInstant);
                if (earlier != null)
                {
                    return(new ZoneLocalMapping(this, localDateTime, earlier, earlier, 1));
                }
                ZoneInterval?later = GetLaterMatchingInterval(interval, localInstant);
                if (later != null)
                {
                    return(new ZoneLocalMapping(this, localDateTime, later, later, 1));
                }
                return(new ZoneLocalMapping(this, localDateTime, GetIntervalBeforeGap(localInstant), GetIntervalAfterGap(localInstant), 0));
            }
        }