/// <summary>
        /// In cases where we can't get a zone mapping, either because we haven't kept
        /// up to date with the standard names or because the system language isn't English,
        /// try to work out the TZDB mapping by the transitions within the next few years.
        /// We only do this for the PCL, where we can't ask a TimeZoneInfo for its ID. Unfortunately
        /// this means we may sometimes return a mapping for zones which shouldn't be mapped at all, but that's
        /// probably okay and we return null if we don't get a 70% hit rate anyway. We look at all
        /// transitions in all primary mappings for the next year.
        /// Heuristically, this seems to be good enough to get the right results in most cases.
        /// </summary>
        /// <remarks>This method is not PCL-only as we would like to test it frequently. It will
        /// never actually be called in the non-PCL release though.</remarks>
        /// <param name="zone">Zone to resolve in a best-effort fashion.</param>
        internal string GuessZoneIdByTransitionsUncached(TimeZoneInfo zone)
        {
            // Very rare use of the system clock! Windows time zone updates sometimes sacrifice past
            // accuracy for future accuracy, so let's use the current year's transitions.
            int     thisYear        = SystemClock.Instance.GetCurrentInstant().InUtc().Year;
            Instant startOfThisYear = Instant.FromUtc(thisYear, 1, 1, 0, 0);
            Instant startOfNextYear = Instant.FromUtc(thisYear + 1, 1, 1, 0, 0);
            var     candidates      = WindowsMapping.PrimaryMapping.Values.Select(ForId).ToList();
            // Would create a HashSet directly, but it appears not to be present on all versions of the PCL...
            var instants = candidates.SelectMany(z => z.GetZoneIntervals(startOfThisYear, startOfNextYear))
                           .Select(zi => Instant.Max(zi.RawStart, startOfThisYear))           // Clamp to start of interval
                           .Distinct()
                           .ToList();

            int          bestScore = -1;
            DateTimeZone bestZone  = null;

            foreach (var candidate in candidates)
            {
                int score = instants.Count(instant => Offset.FromTimeSpan(zone.GetUtcOffset(instant.ToDateTimeUtc())) == candidate.GetUtcOffset(instant));
                if (score > bestScore)
                {
                    bestScore = score;
                    bestZone  = candidate;
                }
            }
            // If we haven't hit at least 70%, it's effectively unmappable
            return(bestScore * 100 / instants.Count > 70 ? bestZone.Id : null);
        }
    private static Interval?Intersect(Interval left, Interval right)
    {
        Instant start = Instant.Max(left.Start, right.Start);
        Instant end   = Instant.Min(left.End, right.End);

        return(start < end ? new Interval(start, end) : (Interval?)null);
    }
            private void ExtendCurrentItem(Interval?timeRange)
            {
                if (!timeRange.HasValue || !CurrentItem.TimeRange.HasValue)
                {
                    return;
                }

                CurrentItem.TimeRange = new Interval(
                    Instant.Min(CurrentItem.TimeRange.Value.Start, timeRange.Value.Start),
                    Instant.Max(CurrentItem.TimeRange.Value.End, timeRange.Value.End));
            }
Example #4
0
        public void Max()
        {
            Instant x = Instant.FromUnixTimeTicks(100);
            Instant y = Instant.FromUnixTimeTicks(200);

            Assert.AreEqual(y, Instant.Max(x, y));
            Assert.AreEqual(y, Instant.Max(y, x));
            Assert.AreEqual(x, Instant.Max(x, Instant.MinValue));
            Assert.AreEqual(x, Instant.Max(Instant.MinValue, x));
            Assert.AreEqual(Instant.MaxValue, Instant.Max(Instant.MaxValue, x));
            Assert.AreEqual(Instant.MaxValue, Instant.Max(x, Instant.MaxValue));
        }
Example #5
0
        public void Max()
        {
            Instant x = new Instant(100);
            Instant y = new Instant(200);

            Assert.AreEqual(y, Instant.Max(x, y));
            Assert.AreEqual(y, Instant.Max(y, x));
            Assert.AreEqual(x, Instant.Max(x, Instant.MinValue));
            Assert.AreEqual(x, Instant.Max(Instant.MinValue, x));
            Assert.AreEqual(Instant.MaxValue, Instant.Max(Instant.MaxValue, x));
            Assert.AreEqual(Instant.MaxValue, Instant.Max(x, Instant.MaxValue));
        }
Example #6
0
        public void Max()
        {
            Instant x = Instant.FromTicksSinceUnixEpoch(100);
            Instant y = Instant.FromTicksSinceUnixEpoch(200);

            Assert.AreEqual(y, Instant.Max(x, y));
            Assert.AreEqual(y, Instant.Max(y, x));
            Assert.AreEqual(x, Instant.Max(x, Instant.MinValue));
            Assert.AreEqual(x, Instant.Max(Instant.MinValue, x));
            Assert.AreEqual(Instant.MaxValue, Instant.Max(Instant.MaxValue, x));
            Assert.AreEqual(Instant.MaxValue, Instant.Max(x, Instant.MaxValue));
        }
        public virtual void SupportsMax(List <TestEntity <Instant> > testEntities)
        {
            AddToDatabase(testEntities.ToArray());

            var testValue = Instant.Max(testEntities[0].TestProperty, testEntities[0].TestComponent.TestComponentProperty);

            ExecuteWithQueryable(q =>
            {
                var foundEntities = q.Where(x => Instant.Max(x.TestProperty, x.TestComponent.TestComponentProperty) == testValue).Select(x => new { ExposedProperty = Instant.Max(x.TestProperty, x.TestComponent.TestComponentProperty) }).ToList();
                foundEntities.Should().HaveCount(1);
                foundEntities[0].ExposedProperty.Should().Be(testValue);
            });
        }
    /// <summary>
    /// Get a random date between start and end.
    /// </summary>
    public Instant Between(Instant start, Instant end)
    {
        var min = Instant.Min(start, end);
        var max = Instant.Max(start, end);

        var total = max - min;

        var partTicks = Random.Double() * total.TotalTicks;

        var part = Duration.FromTicks(partTicks);

        return(min + part);
    }
    /// <summary>
    /// Get a random date between start and end.
    /// </summary>
    public ZonedDateTime Between(ZonedDateTime start, ZonedDateTime end)
    {
        //TODO: check for mis matched zones?
        var min = Instant.Min(start.ToInstant(), end.ToInstant());
        var max = Instant.Max(start.ToInstant(), end.ToInstant());

        var total = max - min;

        var partTicks = Random.Double() * total.TotalTicks;

        var part = Duration.FromTicks(partTicks);

        return(new(min + part, start.Zone));
    }
Example #10
0
        private static void DumpZone(DateTimeZone zone, TextWriter output, int fromYear, int toYear)
        {
            output.WriteLine(zone.Id);
            var start = Instant.FromUtc(fromYear, 1, 1, 0, 0);
            // Exclusive upper bound
            var end = Instant.FromUtc(toYear + 1, 1, 1, 0, 0);

            foreach (var interval in zone.GetZoneIntervals(start, end))
            {
                output.WriteLine("{0}  {1}  {2}",
                                 DateTimePattern.Format(Instant.Max(start, interval.Start)),
                                 OffsetPattern.Format(interval.StandardOffset),
                                 OffsetPattern.Format(interval.Savings));
            }

            output.WriteLine();
        }
        /// <summary>
        /// In cases where we can't get a zone mapping directly, we try to work out a good fit
        /// by checking the transitions within the next few years.
        /// This can happen if the Windows data isn't up-to-date, or if we're on a system where
        /// TimeZoneInfo.Local.Id just returns "local", or if TimeZoneInfo.Local is a custom time
        /// zone for some reason. We return null if we don't get a 70% hit rate.
        /// We look at all transitions in all canonical IDs for the next 5 years.
        /// Heuristically, this seems to be good enough to get the right results in most cases.
        /// This method used to only be called in the PCL build, but it seems reasonable enough to
        /// call it if we can't get an exact match anyway.
        /// </summary>
        /// <param name="zone">Zone to resolve in a best-effort fashion.</param>
        internal string GuessZoneIdByTransitionsUncached(TimeZoneInfo zone)
        {
            // See https://github.com/nodatime/nodatime/issues/686 for performance observations.
            // If this were going to be called a lot, we could optimize further - but as it is,
            // there's not much point.
            // Very rare use of the system clock! Windows time zone updates sometimes sacrifice past
            // accuracy for future accuracy, so let's use the current year's transitions.
            int     thisYear        = SystemClock.Instance.GetCurrentInstant().InUtc().Year;
            Instant startOfThisYear = Instant.FromUtc(thisYear, 1, 1, 0, 0);
            Instant startOfNextYear = Instant.FromUtc(thisYear + 5, 1, 1, 0, 0);
            var     candidates      = CanonicalIdMap.Values.Select(ForId).ToList();
            var     instants        = candidates.SelectMany(z => z.GetZoneIntervals(startOfThisYear, startOfNextYear))
                                      .Select(zi => Instant.Max(zi.RawStart, startOfThisYear)) // Clamp to start of interval
                                      .Distinct()
                                      .ToList();
            var bclOffsets = instants.Select(instant => Offset.FromTimeSpan(zone.GetUtcOffset(instant.ToDateTimeUtc()))).ToList();
            // For a zone to be mappable, at most 30% of the checks must fail
            // - so if we get to that number (or whatever our "best" so far is)
            // we know we can stop for any particular zone.
            int          lowestFailureScore = (instants.Count * 30) / 100;
            DateTimeZone bestZone           = null;

            foreach (var candidate in candidates)
            {
                int failureScore = 0;
                for (int i = 0; i < instants.Count; i++)
                {
                    if (candidate.GetUtcOffset(instants[i]) != bclOffsets[i])
                    {
                        failureScore++;
                        if (failureScore == lowestFailureScore)
                        {
                            break;
                        }
                    }
                }
                if (failureScore < lowestFailureScore)
                {
                    lowestFailureScore = failureScore;
                    bestZone           = candidate;
                }
            }
            return(bestZone?.Id);
        }
    static Duration GetAvailableOverlap(
        LocalDate date,
        Availability avail1,
        Availability avail2)
    {
        // TODO: Check that the rules of InZoneLeniently are what you want.
        // Be careful, as you could end up with an end before a start...
        var start1 = (date + avail1.Start).InZoneLeniently(avail1.Zone);
        var end1   = (date + avail1.End).InZoneLeniently(avail1.Zone);

        var start2 = (date + avail2.Start).InZoneLeniently(avail2.Zone);
        var end2   = (date + avail2.End).InZoneLeniently(avail2.Zone);

        var latestStart = Instant.Max(start1.ToInstant(), start2.ToInstant());
        var earliestEnd = Instant.Min(end1.ToInstant(), end2.ToInstant());

        // Never return a negative duration... return zero of there's no overlap.
        // Noda Time should have Duration.Max really...
        var overlap = earliestEnd - latestStart;

        return(overlap < Duration.Zero ? Duration.Zero : overlap);
    }
Example #13
0
 private void MutateState(JournalEntry entry)
 {
     State.Operations.AddLast(entry);
     entry.JournalOperation.Mutate(State);
     LastUpdate = Instant.Max(LastUpdate, entry.Timestamp);
 }
 public virtual void SupportsMaxFromParameter(Instant testInstant)
 {
     SupportsPropertyOrMethod(x => Instant.Max(x, testInstant));
 }
 private Instant GetEffectiveStart(ZoneInterval zoneInterval) =>
 CheckOption(options, Options.MatchStartAndEndTransitions)
         ? zoneInterval.RawStart : Instant.Max(zoneInterval.RawStart, interval.Start);