/// <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)); }
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)); }
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)); }
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)); }
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); }
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);