Example #1
0
        /// <summary>
        /// Returns the PeriodField for the given unit value, or null if the values does
        /// not represent a single unit.
        /// </summary>
        private static IPeriodField GetSingleField(PeriodFieldSet fields, PeriodUnits units)
        {
            switch (units)
            {
            case PeriodUnits.Years: return(fields.Years);

            case PeriodUnits.Months: return(fields.Months);

            case PeriodUnits.Weeks: return(fields.Weeks);

            case PeriodUnits.Days: return(fields.Days);

            case PeriodUnits.Hours: return(fields.Hours);

            case PeriodUnits.Minutes: return(fields.Minutes);

            case PeriodUnits.Seconds: return(fields.Seconds);

            case PeriodUnits.Milliseconds: return(fields.Milliseconds);

            case PeriodUnits.Ticks: return(fields.Ticks);

            default: return(null);
            }
        }
Example #2
0
        public static Period Between(LocalDate start, LocalDate end, PeriodUnits units)
        {
            Preconditions.CheckArgument((units & PeriodUnits.AllTimeUnits) == 0, nameof(units), "Units contains time units: {0}", units);
            Preconditions.CheckArgument(units != 0, nameof(units), "Units must not be empty");
            Preconditions.CheckArgument((units & ~PeriodUnits.AllUnits) == 0, nameof(units), "Units contains an unknown value: {0}", units);
            CalendarSystem calendar = start.Calendar;
            Preconditions.CheckArgument(calendar.Equals(end.Calendar), nameof(end), "start and end must use the same calendar system");

            if (start == end)
            {
                return Zero;
            }

            // Optimization for single field
            switch (units)
            {
                case PeriodUnits.Years: return FromYears(DatePeriodFields.YearsField.UnitsBetween(start, end));
                case PeriodUnits.Months: return FromMonths(DatePeriodFields.MonthsField.UnitsBetween(start, end));
                case PeriodUnits.Weeks: return FromWeeks(DatePeriodFields.WeeksField.UnitsBetween(start, end));
                case PeriodUnits.Days: return FromDays(DaysBetween(start, end));
            }

            // Multiple fields
            DateComponentsBetween(start, end, units, out int years, out int months, out int weeks, out int days);
            return new Period(years, months, weeks, days);
        }
        private String GetTextForUnitPlural(PeriodUnits unit)
        {
            switch (unit)
            {
            case PeriodUnits.Days:
                return(Properties.Resources.ManyDays);

            case PeriodUnits.Hours:
                return(Properties.Resources.ManyHours);

            case PeriodUnits.Milliseconds:
                return(Properties.Resources.ManyMilliseconds);

            case PeriodUnits.Minutes:
                return(Properties.Resources.ManyMinutes);

            case PeriodUnits.Months:
                return(Properties.Resources.ManyMonths);

            case PeriodUnits.Seconds:
                return(Properties.Resources.ManySeconds);

            case PeriodUnits.Ticks:
                return(Properties.Resources.ManyTicks);

            case PeriodUnits.Weeks:
                return(Properties.Resources.ManyWeeks);

            case PeriodUnits.Years:
                return(Properties.Resources.ManyYears);

            default:
                throw new ArgumentOutOfRangeException("unit", "GetTextForUnitPlural only takes a single unit");
            }
        }
        private String GetTextForUnitSingular(PeriodUnits unit)
        {
            switch (unit)
            {
            case PeriodUnits.Days:
                return(Properties.Resources.OneDay);

            case PeriodUnits.Hours:
                return(Properties.Resources.OneHour);

            case PeriodUnits.Milliseconds:
                return(Properties.Resources.OneMillisecond);

            case PeriodUnits.Minutes:
                return(Properties.Resources.OneMinute);

            case PeriodUnits.Months:
                return(Properties.Resources.OneMonth);

            case PeriodUnits.Seconds:
                return(Properties.Resources.OneSecond);

            case PeriodUnits.Ticks:
                return(Properties.Resources.OneTick);

            case PeriodUnits.Weeks:
                return(Properties.Resources.OneWeek);

            case PeriodUnits.Years:
                return(Properties.Resources.OneYear);

            default:
                throw new ArgumentOutOfRangeException("unit", "GetTextForUnitSingular only takes a single unit");
            }
        }
Example #5
0
        public static Period Between(LocalTime start, LocalTime end, PeriodUnits units)
        {
            Preconditions.CheckArgument((units & PeriodUnits.AllDateUnits) == 0, nameof(units), "Units contains date units: {0}", units);
            Preconditions.CheckArgument(units != 0, nameof(units), "Units must not be empty");
            Preconditions.CheckArgument((units & ~PeriodUnits.AllUnits) == 0, nameof(units), "Units contains an unknown value: {0}", units);

            // We know that the difference is in the range of +/- 1 day, which is a relatively small
            // number of nanoseconds. All the operations can be done with simple long division/remainder ops,
            // so we don't need to delegate to TimePeriodField.

            long remaining = unchecked (end.NanosecondOfDay - start.NanosecondOfDay);

            // Optimization for a single unit
            switch (units)
            {
                case PeriodUnits.Hours: return FromHours(remaining / NanosecondsPerHour);
                case PeriodUnits.Minutes: return FromMinutes(remaining / NanosecondsPerMinute);
                case PeriodUnits.Seconds: return FromSeconds(remaining / NanosecondsPerSecond);
                case PeriodUnits.Milliseconds: return FromMilliseconds(remaining / NanosecondsPerMillisecond);
                case PeriodUnits.Ticks: return FromTicks(remaining / NanosecondsPerTick);
                case PeriodUnits.Nanoseconds: return FromNanoseconds(remaining);
            }

            TimeComponentsBetween(remaining, units, out long hours, out long minutes, out long seconds, out long milliseconds, out long ticks, out long nanoseconds);
            return new Period(hours, minutes, seconds, milliseconds, ticks, nanoseconds);
        }
Example #6
0
        /// <summary>
        /// Creates a new period with the given single value.
        /// </summary>
        private Period(PeriodUnits periodUnit, long value)
        {
            switch (periodUnit)
            {
            case PeriodUnits.Years: years = value; break;

            case PeriodUnits.Months: months = value; break;

            case PeriodUnits.Weeks: weeks = value; break;

            case PeriodUnits.Days: days = value; break;

            case PeriodUnits.Hours: hours = value; break;

            case PeriodUnits.Minutes: minutes = value; break;

            case PeriodUnits.Seconds: seconds = value; break;

            case PeriodUnits.Milliseconds: milliseconds = value; break;

            case PeriodUnits.Ticks: ticks = value; break;

            default: throw new ArgumentException("Unit must be singular", "periodUnit");
            }
        }
        internal PeriodUnits GetSignificantUnitsForPeriod(Period period)
        {
            var baseValues = new[] {
                new { Unit = PeriodUnits.Years, Value = period.Years },
                new { Unit = PeriodUnits.Months, Value = period.Months },
                new { Unit = PeriodUnits.Weeks, Value = period.Weeks },
                new { Unit = PeriodUnits.Days, Value = period.Days },
                new { Unit = PeriodUnits.Hours, Value = period.Hours },
                new { Unit = PeriodUnits.Minutes, Value = period.Minutes },
                new { Unit = PeriodUnits.Seconds, Value = period.Seconds },
                new { Unit = PeriodUnits.Milliseconds, Value = period.Milliseconds }
            }.ToList();

            var values = this.Parameters.DisplaySignificantZeroValueUnits
                ? baseValues.SkipWhile(a => a.Value == 0).Reverse().SkipWhile(a => a.Value == 0).Reverse().Take(this.MaxiumumNumberOfUnitsToDisplay)
                : baseValues.Where(a => a.Value != 0).Take(this.MaxiumumNumberOfUnitsToDisplay);

            PeriodUnits significantUnits = PeriodUnits.None;

            foreach (var item in values)
            {
                significantUnits = significantUnits | item.Unit;
            }

            return(significantUnits);
        }
Example #8
0
        internal override CoreMargin PrepareChart(AxisOrientation source, ChartCore chart)
        {
            // Get the current configued values from the view
            _initialDateTime = ((IDateAxisView)View).InitialDateTime;
            _period          = ((IDateAxisView)View).Period;

            return(base.PrepareChart(source, chart));
        }
Example #9
0
        public void HasDateComponent_SingleValued(PeriodUnits unit, bool hasDateComponent)
        {
            var period = new PeriodBuilder {
                [unit] = 1
            }.Build();

            Assert.AreEqual(hasDateComponent, period.HasDateComponent);
        }
        public void GetRelativeTime_UnitsToDisplay(String startLdt, String endLdt, PeriodUnits unitsToDisplay, String expectedResult)
        {
            var start = LocalDateTimePattern.ExtendedIsoPattern.Parse(startLdt).Value;
            var end   = LocalDateTimePattern.ExtendedIsoPattern.Parse(endLdt).Value;

            var result = new Humanizer(unitsToDisplay).GetRelativeTime(start, end);

            Assert.AreEqual(expectedResult, result);
        }
Example #11
0
        /// <summary>
        /// Returns the list of distinct units that are interesting to display, e.g.: Years, Months, Week, Days, Hours, Minutes, Seconds and Milliseconds.
        /// </summary>
        /// <param name="units">The units enumeration value to get the distinct units from</param>
        /// <returns></returns>
        public static IEnumerable <PeriodUnits> GetDistinctUnits(this PeriodUnits units)
        {
            foreach (var unit in Enum.GetValues(typeof(PeriodUnits))
                     .Cast <PeriodUnits>()
                     .Where(u => units.Contains(u)))
            {
                //Only return single units, compound units are ignored
                switch (unit)
                {
                case PeriodUnits.Years:
                    yield return(PeriodUnits.Years);

                    break;

                case PeriodUnits.Months:
                    yield return(PeriodUnits.Months);

                    break;

                case PeriodUnits.Weeks:
                    yield return(PeriodUnits.Weeks);

                    break;

                case PeriodUnits.Days:
                    yield return(PeriodUnits.Days);

                    break;

                case PeriodUnits.Hours:
                    yield return(PeriodUnits.Hours);

                    break;

                case PeriodUnits.Minutes:
                    yield return(PeriodUnits.Minutes);

                    break;

                case PeriodUnits.Seconds:
                    yield return(PeriodUnits.Seconds);

                    break;

                case PeriodUnits.Milliseconds:
                    yield return(PeriodUnits.Milliseconds);

                    break;

                case PeriodUnits.Ticks:
                    yield return(PeriodUnits.Ticks);

                    break;
                }
            }
        }
    /// <summary>
    /// Get a random <see cref="Period"/>. Default 1 week/7 days.
    /// </summary>
    public Period Period(Period?maximum = null, LocalDateTime?anchor = null, PeriodUnits units = global::NodaTime.PeriodUnits.AllUnits)
    {
        var anchorTime = anchor ?? LocalDateTime.Now();
        var span       = maximum ?? global::NodaTime.Period.FromDays(7);

        var periodTicks = global::NodaTime.Period.Between(anchorTime, anchorTime + span, global::NodaTime.PeriodUnits.Ticks);
        var randomTicks = global::NodaTime.Period.FromTicks(Random.Long(0, periodTicks.Ticks));

        return(global::NodaTime.Period.Between(anchorTime, anchorTime + randomTicks, units));
    }
Example #13
0
        public void BetweenLocalTimes_SingleUnit(string startText, string endText, PeriodUnits units, long expectedValue)
        {
            var start = LocalTimePattern.ExtendedIso.Parse(startText).Value;
            var end = LocalTimePattern.ExtendedIso.Parse(endText).Value;
            var actual = Period.Between(start, end, units);
            var expected = new PeriodBuilder {
                [units] = expectedValue
            }.Build();

            Assert.AreEqual(expected, actual);
        }
Example #14
0
        /// <summary>
        /// Gets or sets the value of a single unit.
        /// </summary>
        /// <param name="unit">A single value within the <see cref="PeriodUnits"/> enumeration.</param>
        /// <returns>The value of the given unit within this period builder, or zero if the unit is unset.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="unit"/> is not a single unit.</exception>
        public long this[PeriodUnits unit]
        {
            get
            {
                switch (unit)
                {
                case PeriodUnits.Years: return(Years);

                case PeriodUnits.Months: return(Months);

                case PeriodUnits.Weeks: return(Weeks);

                case PeriodUnits.Days: return(Days);

                case PeriodUnits.Hours: return(Hours);

                case PeriodUnits.Minutes: return(Minutes);

                case PeriodUnits.Seconds: return(Seconds);

                case PeriodUnits.Milliseconds: return(Milliseconds);

                case PeriodUnits.Ticks: return(Ticks);

                default: throw new ArgumentOutOfRangeException("unit", "Indexer for PeriodBuilder only takes a single unit");
                }
            }
            set
            {
                switch (unit)
                {
                case PeriodUnits.Years: Years = value; return;

                case PeriodUnits.Months: Months = value; return;

                case PeriodUnits.Weeks: Weeks = value; return;

                case PeriodUnits.Days: Days = value; return;

                case PeriodUnits.Hours: Hours = value; return;

                case PeriodUnits.Minutes: Minutes = value; return;

                case PeriodUnits.Seconds: Seconds = value; return;

                case PeriodUnits.Milliseconds: Milliseconds = value; return;

                case PeriodUnits.Ticks: Ticks = value; return;

                default: throw new ArgumentOutOfRangeException("unit", "Indexer for PeriodBuilder only takes a single unit");
                }
            }
        }
Example #15
0
        public void Between_ExtremeValues(PeriodUnits units)
        {
            // We can't use None, and Ticks will *correctly* overflow.
            if (units == PeriodUnits.None || units == PeriodUnits.Ticks)
            {
                return;
            }
            var minValue = new LocalDateTime(new LocalInstant(CalendarSystem.Iso.MinTicks));
            var maxValue = new LocalDateTime(new LocalInstant(CalendarSystem.Iso.MaxTicks));

            Period.Between(minValue, maxValue, units);
        }
Example #16
0
        public void Between_ExtremeValues(PeriodUnits units)
        {
            // We can't use None, and Nanoseconds will *correctly* overflow.
            if (units == PeriodUnits.None || units == PeriodUnits.Nanoseconds)
            {
                return;
            }
            var minValue = LocalDate.MinIsoValue.At(LocalTime.MinValue);
            var maxValue = LocalDate.MaxIsoValue.At(LocalTime.MaxValue);

            Period.Between(minValue, maxValue, units);
        }
 private String GetTextForUnit(PeriodUnits unit, String textValue)
 {
     //Depending on singular or plural, fetch different properties
     if (textValue == "1")
     {
         return(this.GetTextForUnitSingular(unit));
     }
     else
     {
         return(String.Format(this.GetTextForUnitPlural(unit), textValue));
     }
 }
Example #18
0
        public void Between_ExtremeValues(PeriodUnits units)
        {
            // We can't use None, and Ticks/Nanoseconds will *correctly* overflow.
            if (units == PeriodUnits.None || units == PeriodUnits.Ticks || units == PeriodUnits.Nanoseconds)
            {
                return;
            }
            var iso      = CalendarSystem.Iso;
            var minValue = new LocalDateTime(iso.MinYear, 1, 1, 0, 0);
            var maxValue = new LocalDateTime(iso.MaxYear, 12, 31, 23, 59, 59, 999, (int)(NodaConstants.TicksPerMillisecond - 1));

            Period.Between(minValue, maxValue, units);
        }
Example #19
0
        public static string GetTimeBetween(DateTime startTime, DateTime endTime, PeriodUnits pu, bool label)
        {
            // https://nodatime.org/2.4.x/userguide/rationale

            LocalDateTime start  = new LocalDateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, startTime.Minute, startTime.Second);
            LocalDateTime end    = new LocalDateTime(endTime.Year, endTime.Month, endTime.Day, endTime.Hour, endTime.Minute, endTime.Second);
            Period        period = Period.Between(start, end, pu);

            string s = string.Empty;

            if ((pu & PeriodUnits.Years) != 0)
            {
                s = s + string.Format("{0}{1}{2}", string.IsNullOrEmpty(s) ? "" : " ", period.Years, label ? " Years" : "");
            }

            if ((pu & PeriodUnits.Months) != 0)
            {
                s = s + string.Format("{0}{1}{2}", string.IsNullOrEmpty(s) ? "" : " ", period.Months, label ? " Months" : "");
            }

            if ((pu & PeriodUnits.Weeks) != 0)
            {
                s = s + string.Format("{0}{1}{2}", string.IsNullOrEmpty(s) ? "" : " ", period.Weeks, label ? " Weeks" : "");
            }

            if ((pu & PeriodUnits.Days) != 0)
            {
                s = s + string.Format("{0}{1}{2}", string.IsNullOrEmpty(s) ? "" : " ", period.Days, label ? " Days" : "");
            }

            if ((pu & PeriodUnits.Hours) != 0)
            {
                s = s + string.Format("{0}{1}{2}", string.IsNullOrEmpty(s) ? "" : " ", period.Hours, label ? " Hours" : "");
            }

            if ((pu & PeriodUnits.Minutes) != 0)
            {
                s = s + string.Format("{0}{1}{2}", string.IsNullOrEmpty(s) ? "" : " ", period.Minutes, label ? " Minutes" : "");
            }

            if ((pu & PeriodUnits.Seconds) != 0)
            {
                s = s + string.Format("{0}{1}{2}", string.IsNullOrEmpty(s) ? "" : " ", period.Seconds, label ? " Seconds" : "");
            }

            return(s);
        }
Example #20
0
        public void BetweenYearMonth_SingleUnit(string startText, string endText, PeriodUnits units, int expectedValue)
        {
            var start = YearMonthPattern.Iso.Parse(startText).Value;
            var end = YearMonthPattern.Iso.Parse(endText).Value;
            var forward = Period.Between(start, end, units);
            var expectedForward = new PeriodBuilder {
                [units] = expectedValue
            }.Build();

            Assert.AreEqual(expectedForward, forward);
            var backward = Period.Between(end, start, units);
            var expectedBackward = new PeriodBuilder {
                [units] = -expectedValue
            }.Build();

            Assert.AreEqual(expectedBackward, backward);
        }
Example #21
0
        /// <summary>
        /// Returns the period between a start and an end date/time, using only the given units.
        /// </summary>
        /// <remarks>
        /// If <paramref name="end"/> is before <paramref name="start" />, each property in the returned period
        /// will be negative. If the given set of units cannot exactly reach the end point (e.g. finding
        /// the difference between 1am and 3:15am in hours) the result will be such that adding it to <paramref name="start"/>
        /// will give a value between <paramref name="start"/> and <paramref name="end"/>. In other words,
        /// any rounding is "towards start"; this is true whether the resulting period is negative or positive.
        /// </remarks>
        /// <param name="start">Start date/time</param>
        /// <param name="end">End date/time</param>
        /// <param name="units">Units to use for calculations</param>
        /// <exception cref="ArgumentException"><paramref name="units"/> is empty or contained unknown values.</exception>
        /// <exception cref="ArgumentException"><paramref name="start"/> and <paramref name="end"/> use different calendars.</exception>
        /// <returns>The period between the given date/times, using the given units.</returns>
        public static Period Between(LocalDateTime start, LocalDateTime end, PeriodUnits units)
        {
            Preconditions.CheckArgument(units != 0, "units", "Units must not be empty");
            Preconditions.CheckArgument((units & ~PeriodUnits.AllUnits) == 0, "units", "Units contains an unknown value: {0}", units);
            CalendarSystem calendar = start.Calendar;

            Preconditions.CheckArgument(calendar.Equals(end.Calendar), "end", "start and end must use the same calendar system");

            LocalInstant startLocalInstant = start.LocalInstant;
            LocalInstant endLocalInstant   = end.LocalInstant;

            if (startLocalInstant == endLocalInstant)
            {
                return(Zero);
            }

            PeriodFieldSet fields = calendar.PeriodFields;

            // Optimization for single field
            var singleField = GetSingleField(fields, units);

            if (singleField != null)
            {
                long value = singleField.Subtract(end.LocalInstant, start.LocalInstant);
                return(new Period(units, value));
            }

            // Multiple fields
            long[] values = new long[ValuesArraySize];

            LocalInstant remaining     = startLocalInstant;
            int          numericFields = (int)units;

            for (int i = 0; i < ValuesArraySize; i++)
            {
                if ((numericFields & (1 << i)) != 0)
                {
                    var field = GetFieldForIndex(fields, i);
                    values[i] = field.Subtract(endLocalInstant, remaining);
                    remaining = field.Add(remaining, values[i]);
                }
            }
            return(new Period(values));
        }
Example #22
0
        /// <summary>
        /// Common code to perform the time parts of the Between methods for long-representable nanos.
        /// </summary>
        /// <param name="totalNanoseconds">Number of nanoseconds to compute the units of</param>
        /// <param name="units">Units to compute</param>
        /// <param name="hours">(Out) Hours component of result</param>
        /// <param name="minutes">(Out) Minutes component of result</param>
        /// <param name="seconds">(Out) Seconds component of result</param>
        /// <param name="milliseconds">(Out) Milliseconds component of result</param>
        /// <param name="ticks">(Out) Ticks component of result</param>
        /// <param name="nanoseconds">(Out) Nanoseconds component of result</param>
        private static void TimeComponentsBetween(long totalNanoseconds, PeriodUnits units,
            out long hours, out long minutes, out long seconds, out long milliseconds, out long ticks, out long nanoseconds)
        {
            hours = UnitsBetween(PeriodUnits.Hours, NanosecondsPerHour);
            minutes = UnitsBetween(PeriodUnits.Minutes, NanosecondsPerMinute);
            seconds = UnitsBetween(PeriodUnits.Seconds, NanosecondsPerSecond);
            milliseconds = UnitsBetween(PeriodUnits.Milliseconds, NanosecondsPerMillisecond);
            ticks = UnitsBetween(PeriodUnits.Ticks, NanosecondsPerTick);
            nanoseconds = UnitsBetween(PeriodUnits.Nanoseconds, 1);

            long UnitsBetween(PeriodUnits mask, long nanosecondsPerUnit)
            {
                if ((mask & units) == 0)
                {
                    return 0;
                }
                return Math.DivRem(totalNanoseconds, nanosecondsPerUnit, out totalNanoseconds);
            }
        }
        /// <summary>
        /// Returns a new period with only the specified units.
        /// </summary>
        /// <param name="period">The period whose values should be used.</param>
        /// <param name="units">The units that should be taken from the given period.</param>
        /// <returns>A new period with only the specified units.</returns>
        public static Period OnlyWith(this Period period, PeriodUnits units = PeriodUnits.AllUnits)
        {
            var builder = new PeriodBuilder();

            if (units.HasFlag(PeriodUnits.Years))
            {
                builder.Years = period.Years;
            }
            if (units.HasFlag(PeriodUnits.Months))
            {
                builder.Months = period.Months;
            }
            if (units.HasFlag(PeriodUnits.Weeks))
            {
                builder.Weeks = period.Weeks;
            }
            if (units.HasFlag(PeriodUnits.Days))
            {
                builder.Days = period.Days;
            }
            if (units.HasFlag(PeriodUnits.Hours))
            {
                builder.Hours = period.Hours;
            }
            if (units.HasFlag(PeriodUnits.Minutes))
            {
                builder.Minutes = period.Minutes;
            }
            if (units.HasFlag(PeriodUnits.Seconds))
            {
                builder.Seconds = period.Seconds;
            }
            if (units.HasFlag(PeriodUnits.Milliseconds))
            {
                builder.Milliseconds = period.Milliseconds;
            }
            if (units.HasFlag(PeriodUnits.Ticks))
            {
                builder.Ticks = period.Ticks;
            }

            return(builder.Build());
        }
        /// <inheritdoc/>
        public string ToDelimitedString()
        {
            System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;
            string separator = IsSubcomponent ? Configuration.SubcomponentSeparator : Configuration.ComponentSeparator;

            return(string.Format(
                       culture,
                       StringHelper.StringFormatSequence(0, 11, separator),
                       RepeatPatternCode?.ToDelimitedString(),
                       CalendarAlignment,
                       PhaseRangeBeginValue.HasValue ? PhaseRangeBeginValue.Value.ToString(Consts.NumericFormat, culture) : null,
                       PhaseRangeEndValue.HasValue ? PhaseRangeEndValue.Value.ToString(Consts.NumericFormat, culture) : null,
                       PeriodQuantity.HasValue ? PeriodQuantity.Value.ToString(Consts.NumericFormat, culture) : null,
                       PeriodUnits?.ToDelimitedString(),
                       InstitutionSpecifiedTime,
                       Event,
                       EventOffsetQuantity.HasValue ? EventOffsetQuantity.Value.ToString(Consts.NumericFormat, culture) : null,
                       EventOffsetUnits?.ToDelimitedString(),
                       GeneralTimingSpecification
                       ).TrimEnd(separator.ToCharArray()));
        }
Example #25
0
 public static PeriodUnits GetSmallestSingleUnit(this PeriodUnits units)
 {
     if (units.Contains(PeriodUnits.Milliseconds))
     {
         return(PeriodUnits.Milliseconds);
     }
     else if (units.Contains(PeriodUnits.Seconds))
     {
         return(PeriodUnits.Seconds);
     }
     else if (units.Contains(PeriodUnits.Minutes))
     {
         return(PeriodUnits.Minutes);
     }
     else if (units.Contains(PeriodUnits.Hours))
     {
         return(PeriodUnits.Hours);
     }
     else if (units.Contains(PeriodUnits.Days))
     {
         return(PeriodUnits.Days);
     }
     else if (units.Contains(PeriodUnits.Weeks))
     {
         return(PeriodUnits.Weeks);
     }
     else if (units.Contains(PeriodUnits.Months))
     {
         return(PeriodUnits.Months);
     }
     else if (units.Contains(PeriodUnits.Years))
     {
         return(PeriodUnits.Years);
     }
     else
     {
         throw new ArgumentOutOfRangeException("unit");
     }
 }
        //TODO A few unit tests to be added here, just to make a point :-)
        internal PeriodUnits GetLastUnitToDisplay(PeriodUnits significantUnits)
        {
            if ((this.UnitsToDisplay & significantUnits & PeriodUnits.Milliseconds) == PeriodUnits.Milliseconds)
            {
                return(PeriodUnits.Milliseconds);
            }
            else if ((this.UnitsToDisplay & significantUnits & PeriodUnits.Seconds) == PeriodUnits.Seconds)
            {
                return(PeriodUnits.Seconds);
            }
            else if ((this.UnitsToDisplay & significantUnits & PeriodUnits.Minutes) == PeriodUnits.Minutes)
            {
                return(PeriodUnits.Minutes);
            }
            else if ((this.UnitsToDisplay & significantUnits & PeriodUnits.Hours) == PeriodUnits.Hours)
            {
                return(PeriodUnits.Hours);
            }
            else if ((this.UnitsToDisplay & significantUnits & PeriodUnits.Days) == PeriodUnits.Days)
            {
                return(PeriodUnits.Days);
            }
            else if ((this.UnitsToDisplay & significantUnits & PeriodUnits.Weeks) == PeriodUnits.Weeks)
            {
                return(PeriodUnits.Weeks);
            }
            else if ((this.UnitsToDisplay & significantUnits & PeriodUnits.Months) == PeriodUnits.Months)
            {
                return(PeriodUnits.Months);
            }
            else if ((this.UnitsToDisplay & significantUnits & PeriodUnits.Years) == PeriodUnits.Years)
            {
                return(PeriodUnits.Years);
            }

            //If nothing was found, there is no common unit between UnitsToDisplay and significantsUnits... Let's simply return the smallest unit in UnitsToDisplay.
            return(this.UnitsToDisplay.GetSmallestSingleUnit());
        }
Example #27
0
 public void Between_ExtremeValues(PeriodUnits units)
 {
     // We can't use None, and Ticks/Nanoseconds will *correctly* overflow.
     if (units == PeriodUnits.None || units == PeriodUnits.Ticks || units== PeriodUnits.Nanoseconds)
     {
         return;
     }
     var iso = CalendarSystem.Iso;
     var minValue = new LocalDateTime(iso.MinYear, 1, 1, 0, 0);
     var maxValue = new LocalDateTime(iso.MaxYear, 12, 31, 23, 59, 59, 999, (int) (NodaConstants.TicksPerMillisecond - 1));
     Period.Between(minValue, maxValue, units);
 }
Example #28
0
        /// <summary>
        /// Common code to perform the date parts of the Between methods.
        /// </summary>
        /// <param name="start">Start date</param>
        /// <param name="end">End date</param>
        /// <param name="units">Units to compute</param>
        /// <param name="years">(Out) Year component of result</param>
        /// <param name="months">(Out) Months component of result</param>
        /// <param name="weeks">(Out) Weeks component of result</param>
        /// <param name="days">(Out) Days component of result</param>
        /// <returns>The resulting date after adding the result components to <paramref name="start"/> (to
        /// allow further computations to be made)</returns>
        private static LocalDate DateComponentsBetween(LocalDate start, LocalDate end, PeriodUnits units,
            out int years, out int months, out int weeks, out int days)
        {
            LocalDate result = start;
            years = UnitsBetween(units & PeriodUnits.Years, ref result, end, DatePeriodFields.YearsField);
            months = UnitsBetween(units & PeriodUnits.Months, ref result, end, DatePeriodFields.MonthsField);
            weeks = UnitsBetween(units & PeriodUnits.Weeks, ref result, end, DatePeriodFields.WeeksField);
            days = UnitsBetween(units & PeriodUnits.Days, ref result, end, DatePeriodFields.DaysField);

            int UnitsBetween(PeriodUnits maskedUnits, ref LocalDate startDate, LocalDate endDate, IDatePeriodField dateField)
            {
                if (maskedUnits == 0)
                {
                    return 0;
                }
                int value = dateField.UnitsBetween(startDate, endDate);
                startDate = dateField.Add(startDate, value);
                return value;
            }
            return result;
        }
Example #29
0
        /// <summary>
        /// Returns the period between a start and an end date/time, using only the given units.
        /// </summary>
        /// <remarks>
        /// If <paramref name="end"/> is before <paramref name="start" />, each property in the returned period
        /// will be negative. If the given set of units cannot exactly reach the end point (e.g. finding
        /// the difference between 1am and 3:15am in hours) the result will be such that adding it to <paramref name="start"/>
        /// will give a value between <paramref name="start"/> and <paramref name="end"/>. In other words,
        /// any rounding is "towards start"; this is true whether the resulting period is negative or positive.
        /// </remarks>
        /// <param name="start">Start date/time</param>
        /// <param name="end">End date/time</param>
        /// <param name="units">Units to use for calculations</param>
        /// <exception cref="ArgumentException"><paramref name="units"/> is empty or contained unknown values.</exception>
        /// <exception cref="ArgumentException"><paramref name="start"/> and <paramref name="end"/> use different calendars.</exception>
        /// <returns>The period between the given date/times, using the given units.</returns>
        public static Period Between(LocalDateTime start, LocalDateTime end, PeriodUnits units)
        {
            Preconditions.CheckArgument(units != 0, nameof(units), "Units must not be empty");
            Preconditions.CheckArgument((units & ~PeriodUnits.AllUnits) == 0, nameof(units), "Units contains an unknown value: {0}", units);
            CalendarSystem calendar = start.Calendar;
            Preconditions.CheckArgument(calendar.Equals(end.Calendar), nameof(end), "start and end must use the same calendar system");

            if (start == end)
            {
                return Zero;
            }

            // Adjust for situations like "days between 5th January 10am and 7th Janary 5am" which should be one
            // day, because if we actually reach 7th January with date fields, we've overshot.
            // The date adjustment will always be valid, because it's just moving it towards start.
            // We need this for all date-based period fields. We could potentially optimize by not doing this
            // in cases where we've only got time fields...
            LocalDate endDate = end.Date;
            if (start < end)
            {
                if (start.TimeOfDay > end.TimeOfDay)
                {
                    endDate = endDate.PlusDays(-1);
                }
            }
            else if (start > end && start.TimeOfDay < end.TimeOfDay)
            {
                endDate = endDate.PlusDays(1);
            }

            // Optimization for single field
            switch (units)
            {
                case PeriodUnits.Years: return FromYears(DatePeriodFields.YearsField.UnitsBetween(start.Date, endDate));
                case PeriodUnits.Months: return FromMonths(DatePeriodFields.MonthsField.UnitsBetween(start.Date, endDate));
                case PeriodUnits.Weeks: return FromWeeks(DatePeriodFields.WeeksField.UnitsBetween(start.Date, endDate));
                case PeriodUnits.Days: return FromDays(DaysBetween(start.Date, endDate));
                case PeriodUnits.Hours: return FromHours(TimePeriodField.Hours.UnitsBetween(start, end));
                case PeriodUnits.Minutes: return FromMinutes(TimePeriodField.Minutes.UnitsBetween(start, end));
                case PeriodUnits.Seconds: return FromSeconds(TimePeriodField.Seconds.UnitsBetween(start, end));
                case PeriodUnits.Milliseconds: return FromMilliseconds(TimePeriodField.Milliseconds.UnitsBetween(start, end));
                case PeriodUnits.Ticks: return FromTicks(TimePeriodField.Ticks.UnitsBetween(start, end));
                case PeriodUnits.Nanoseconds: return FromNanoseconds(TimePeriodField.Nanoseconds.UnitsBetween(start, end));
            }

            // Multiple fields
            LocalDateTime remaining = start;
            int years = 0, months = 0, weeks = 0, days = 0;
            if ((units & PeriodUnits.AllDateUnits) != 0)
            {
                LocalDate remainingDate = DateComponentsBetween(
                    start.Date, endDate, units, out years, out months, out weeks, out days);
                remaining = new LocalDateTime(remainingDate, start.TimeOfDay);
            }
            if ((units & PeriodUnits.AllTimeUnits) == 0)
            {
                return new Period(years, months, weeks, days);
            }

            // The remainder of the computation is with fixed-length units, so we can do it all with
            // Duration instead of Local* values. We don't know for sure that this is small though - we *could*
            // be trying to find the difference between 9998 BC and 9999 CE in nanoseconds...
            // Where we can optimize, do everything with long arithmetic (as we do for Between(LocalTime, LocalTime)).
            // Otherwise (rare case), use duration arithmetic.
            long hours, minutes, seconds, milliseconds, ticks, nanoseconds;
            var duration = end.ToLocalInstant().TimeSinceLocalEpoch - remaining.ToLocalInstant().TimeSinceLocalEpoch;
            if (duration.IsInt64Representable)
            {
                TimeComponentsBetween(duration.ToInt64Nanoseconds(), units, out hours, out minutes, out seconds, out milliseconds, out ticks, out nanoseconds);
            }
            else
            {
                hours = UnitsBetween(PeriodUnits.Hours, TimePeriodField.Hours);
                minutes = UnitsBetween(PeriodUnits.Minutes, TimePeriodField.Minutes);
                seconds = UnitsBetween(PeriodUnits.Seconds, TimePeriodField.Seconds);
                milliseconds = UnitsBetween(PeriodUnits.Milliseconds, TimePeriodField.Milliseconds);
                ticks = UnitsBetween(PeriodUnits.Ticks, TimePeriodField.Ticks);
                nanoseconds = UnitsBetween(PeriodUnits.Ticks, TimePeriodField.Nanoseconds);
            }
            return new Period(years, months, weeks, days, hours, minutes, seconds, milliseconds, ticks, nanoseconds);

            long UnitsBetween(PeriodUnits mask, TimePeriodField timeField)
            {
                if ((mask & units) == 0)
                {
                    return 0;
                }
                long value = timeField.GetUnitsInDuration(duration);
                duration -= timeField.ToDuration(value);
                return value;
            }
        }
Example #30
0
        public void Between_LocalDateTime_AwkwardTimeOfDayWithSingleUnit(string startText, string endText, PeriodUnits units, int expectedForward, int expectedBackward)
        {
            LocalDateTime start   = LocalDateTimePattern.ExtendedIso.Parse(startText).Value;
            LocalDateTime end     = LocalDateTimePattern.ExtendedIso.Parse(endText).Value;
            Period        forward = Period.Between(start, end, units);

            Assert.AreEqual(expectedForward, forward.ToBuilder()[units]);
            Period backward = Period.Between(end, start, units);

            Assert.AreEqual(expectedBackward, backward.ToBuilder()[units]);
        }
Example #31
0
 public static string GetTimeSinceStart(DetailReadModel d, PeriodUnits pu, bool label)
 {
     return(GetTimeBetween(d.StartTime.Value, DateTime.Now, pu, label));
 }
Example #32
0
 public void HasDateComponent_SingleValued(PeriodUnits unit, bool hasDateComponent)
 {
     var period = new PeriodBuilder {[unit] = 1 }.Build();
     Assert.AreEqual(hasDateComponent, period.HasDateComponent);
 }        
Example #33
0
 /// <summary>
 /// Gets or sets the value of a single unit.
 /// </summary>
 /// <remarks>
 /// <para>
 /// The type of this indexer is <see cref="System.Int64"/> for uniformity, but any date unit (year, month, week, day) will only ever have a value
 /// in the range of <see cref="System.Int32"/>.
 /// </para>
 /// <para>
 /// For the <see cref="PeriodUnits.Nanoseconds"/> unit, the value is converted to <c>Int64</c> when reading from the indexer, causing it to
 /// fail if the value is out of range (around 250 years). To access the values of very large numbers of nanoseconds, use the <see cref="Nanoseconds"/>
 /// property directly.
 /// </para>
 /// </remarks>
 /// <param name="unit">A single value within the <see cref="PeriodUnits"/> enumeration.</param>
 /// <value>The value of the given unit within this period builder, or zero if the unit is unset.</value>
 /// <exception cref="ArgumentOutOfRangeException"><paramref name="unit"/> is not a single unit, or a value is provided for a date unit which is outside the range of <see cref="System.Int32"/>.</exception>
 public long this[PeriodUnits unit]
 {
     get
     {
         switch (unit)
         {
             case PeriodUnits.Years: return Years;
             case PeriodUnits.Months: return Months;
             case PeriodUnits.Weeks: return Weeks;
             case PeriodUnits.Days: return Days;
             case PeriodUnits.Hours: return Hours;
             case PeriodUnits.Minutes: return Minutes;
             case PeriodUnits.Seconds: return Seconds;
             case PeriodUnits.Milliseconds: return Milliseconds;
             case PeriodUnits.Ticks: return Ticks;
             case PeriodUnits.Nanoseconds: return Nanoseconds;
             default: throw new ArgumentOutOfRangeException(nameof(unit), "Indexer for PeriodBuilder only takes a single unit");
         }
     }
     set
     {
         if ((unit & PeriodUnits.AllDateUnits) != 0)
         {
             Preconditions.CheckArgumentRange(nameof(value), value, int.MinValue, int.MaxValue);
         }
         switch (unit)
         {
             case PeriodUnits.Years: Years = (int) value; return;
             case PeriodUnits.Months: Months = (int) value; return;
             case PeriodUnits.Weeks: Weeks = (int) value; return;
             case PeriodUnits.Days: Days = (int) value; return;
             case PeriodUnits.Hours: Hours = value; return;
             case PeriodUnits.Minutes: Minutes = value; return;
             case PeriodUnits.Seconds: Seconds = value; return;
             case PeriodUnits.Milliseconds: Milliseconds = value; return;
             case PeriodUnits.Ticks: Ticks = value; return;
             case PeriodUnits.Nanoseconds: Nanoseconds = value; return;
             default: throw new ArgumentOutOfRangeException(nameof(unit), "Indexer for PeriodBuilder only takes a single unit");
         }
     }
 }
Example #34
0
 public void Between_LocalDateTime_AwkwardTimeOfDayWithSingleUnit(string startText, string endText, PeriodUnits units, int expectedForward, int expectedBackward)
 {
     LocalDateTime start = LocalDateTimePattern.ExtendedIsoPattern.Parse(startText).Value;
     LocalDateTime end = LocalDateTimePattern.ExtendedIsoPattern.Parse(endText).Value;
     Period forward = Period.Between(start, end, units);
     Assert.AreEqual(expectedForward, forward.ToBuilder()[units]);
     Period backward = Period.Between(end, start, units);
     Assert.AreEqual(expectedBackward, backward.ToBuilder()[units]);
 }