/// <summary>
        /// This method returns the end of the month that contains the given date.  The method has not
        /// been designed to work if the dayShift is outside the range -30 to +30.
        /// </summary>
        /// <param name="date">the date whose month end is to be returned</param>
        /// <param name="dayShift">The shift (measured in days) in the definition of monthly time steps.
        /// If the value is 0, then months are defined as ending on the last day of the standard calendar
        /// month.  If the value is 1, then months are defined as ending on the 1st day of the standard
        /// calendar month.  If the value is -1, then months are defined as ending on the day before the
        /// last day of the standard calendar month.</param>
        public static DateTime RoundMonthEnd(this DateTime date, int dayShift)
        {
            DateTime endDate = new DateTime(date.Year, date.Month, 1).AddMinutes(-1).AddDays(dayShift);

            while (endDate < date)
            {
                endDate = endDate.AddMonthsByEnd(dayShift, 1);
            }
            return(endDate);
        }
        /// <summary>
        /// This method computes the end date when given the start date, a regular time step size,
        /// and the number of time steps that should be added to the start date.
        /// </summary>
        /// <param name="startDate">The start date for the calculation</param>
        /// <param name="unit">Code for the time step units (e.g. hour, day, month...)</param>
        /// <param name="stepSize">The number of units per time step (e.g. Size=10 for 10-day time steps)</param>
        /// <param name="numSteps">The number of time steps to add to the start date</param>
        /// <returns>The end date of the calculation</returns>
        public static DateTime IncrementDate(DateTime startDate, TimeStepUnitCode unit,
                                             short stepSize, int numSteps)
        {
            DateTime calcDate;  // The end date of the calculation
            DateTime date = startDate;

            // The DateTime class's various 'Add' methods lend themselves to
            // a switch statement so that whichever units the time step is measured in,
            // we can call the corresponding 'Add' method.
            switch (unit)
            {
            case TimeStepUnitCode.Minute:
                calcDate = date.AddMinutes(stepSize * numSteps);
                break;

            case TimeStepUnitCode.Hour:
                calcDate = date.AddHours(stepSize * numSteps);
                break;

            case TimeStepUnitCode.Day:
                calcDate = date.AddDays(stepSize * numSteps);
                break;

            case TimeStepUnitCode.Week:
                calcDate = date.AddDays(stepSize * numSteps * 7);
                break;

            case TimeStepUnitCode.Month:
                // For now, we only handle monthly time steps that end on regular calendar month
                // See https://github.com/hydrologics/Oasis/issues/163
                date     = date.RoundMonthEnd(0);
                calcDate = date.AddMonthsByEnd(0, stepSize * numSteps);
                break;

            case TimeStepUnitCode.Year:
                // For now, we only handle yearly time steps that end on regular calendar year
                // See https://github.com/hydrologics/Oasis/issues/163
                date     = new DateTime(date.Year + 1, 1, 1).AddMinutes(-1);
                calcDate = date.AddYears(stepSize * numSteps);
                break;

            default:
                calcDate = date;
                break;
            }
            return(calcDate);
        }
        /// <summary>
        /// This method determines how many regular time steps are contained between the given
        /// start date and end date, when given a regular time step size.
        /// The method does not care whether the input start date comes before the input end
        /// date.  It simply returns the absolute value of the number of steps between the given dates.
        /// Please note that the returned value is not inclusive of the first time step. That is, if the
        /// start date is 1/1 and the end date is 1/1, then the number of days between the given dates
        /// is returned as zero.
        /// </summary>
        /// <param name="startDate">The date when the count begins</param>
        /// <param name="endDate">The date when the count ends</param>
        /// <param name="unit">Code for the time step units (e.g. hour, day, month...)</param>
        /// <param name="stepSize">The number of units per time step (e.g. Size=10 for 10-day time steps)</param>
        /// <returns></returns>
        public static int CountSteps(DateTime startDate, DateTime endDate,
                                     TimeStepUnitCode unit, short stepSize)
        {
            DateTime calcDate;  // Date value that will be iterated for the counting process
            int      i = 0;     // Counter for how many time steps

            // Method does not care whether the input start date comes before the input end
            // date.  It simply returns the absolute value of the number of steps between the given dates.
            if (endDate < startDate)
            {
                calcDate  = endDate;
                endDate   = startDate;
                startDate = calcDate;
            }
            calcDate = startDate;

            // The DateTime class's various 'Add' methods lend themselves to
            // a switch statement so that whichever units the time step is measured in,
            // we can call the corresponding 'Add' method.  The counting loop inside of
            // the switch statement is deliberately selected to be faster than a switch
            // statement inside of a loop.
            switch (unit)
            {
            case TimeStepUnitCode.Minute:
                for (i = 0; calcDate < endDate; i++)
                {
                    calcDate = calcDate.AddMinutes(stepSize);
                }
                break;

            case TimeStepUnitCode.Hour:
                for (i = 0; calcDate < endDate; i++)
                {
                    calcDate = calcDate.AddHours(stepSize);
                }
                break;

            case TimeStepUnitCode.Day:
                for (i = 0; calcDate < endDate; i++)
                {
                    calcDate = calcDate.AddDays(stepSize);
                }
                break;

            case TimeStepUnitCode.Week:
                for (i = 0; calcDate < endDate; i++)
                {
                    calcDate = calcDate.AddDays(stepSize * 7);
                }
                break;

            case TimeStepUnitCode.Month:
                // For now, we only handle monthly time steps that end on regular calendar month
                // See https://github.com/hydrologics/Oasis/issues/163
                calcDate = RoundMonthEnd(calcDate, 0);
                for (i = 0; calcDate < endDate; i++)
                {
                    calcDate = calcDate.AddMonthsByEnd(0, stepSize);
                }
                break;

            case TimeStepUnitCode.Year:
                // For now, we only handle yearly time steps that end on regular calendar year
                // See https://github.com/hydrologics/Oasis/issues/163
                calcDate = new DateTime(calcDate.Year + 1, 1, 1).AddMinutes(-1);
                for (i = 0; calcDate < endDate; i++)
                {
                    calcDate = calcDate.AddYears(stepSize);
                }
                break;
            }
            return(i);
        }
Exemple #4
0
        public void AddMonthsByEnd_30c()
        {
            DateTime d = new DateTime(1959, 3, 30);

            Assert.AreEqual(d, d.AddMonthsByEnd(30, 0));

            Assert.AreEqual(new DateTime(1959, 4, 30), d.AddMonthsByEnd(30, 1));
            Assert.AreEqual(new DateTime(1959, 5, 30), d.AddMonthsByEnd(30, 2));
            Assert.AreEqual(new DateTime(1960, 3, 1), d.AddMonthsByEnd(30, 11));
            Assert.AreEqual(new DateTime(1960, 3, 30), d.AddMonthsByEnd(30, 12));
            Assert.AreEqual(new DateTime(1960, 4, 30), d.AddMonthsByEnd(30, 13));
            Assert.AreEqual(new DateTime(1960, 5, 30), d.AddMonthsByEnd(30, 14));
            Assert.AreEqual(new DateTime(1960, 6, 30), d.AddMonthsByEnd(30, 15));

            Assert.AreEqual(new DateTime(1959, 3, 2), d.AddMonthsByEnd(30, -1));
            Assert.AreEqual(new DateTime(1959, 1, 30), d.AddMonthsByEnd(30, -2));
            Assert.AreEqual(new DateTime(1958, 4, 30), d.AddMonthsByEnd(30, -11));
            Assert.AreEqual(new DateTime(1958, 3, 30), d.AddMonthsByEnd(30, -12));
            Assert.AreEqual(new DateTime(1958, 3, 2), d.AddMonthsByEnd(30, -13));
        }
Exemple #5
0
        public void AddMonthsByEnd_2c()
        {
            DateTime d = new DateTime(1959, 3, 2);

            Assert.AreEqual(d, d.AddMonthsByEnd(2, 0));

            Assert.AreEqual(new DateTime(1959, 4, 2), d.AddMonthsByEnd(2, 1));
            Assert.AreEqual(new DateTime(1959, 5, 2), d.AddMonthsByEnd(2, 2));
            Assert.AreEqual(new DateTime(1960, 3, 2), d.AddMonthsByEnd(2, 12));
            Assert.AreEqual(new DateTime(1960, 4, 2), d.AddMonthsByEnd(2, 13));
            Assert.AreEqual(new DateTime(1960, 5, 2), d.AddMonthsByEnd(2, 14));
            Assert.AreEqual(new DateTime(1960, 6, 2), d.AddMonthsByEnd(2, 15));

            Assert.AreEqual(new DateTime(1959, 2, 2), d.AddMonthsByEnd(2, -1));
            Assert.AreEqual(new DateTime(1959, 1, 2), d.AddMonthsByEnd(2, -2));
            Assert.AreEqual(new DateTime(1958, 4, 2), d.AddMonthsByEnd(2, -11));
            Assert.AreEqual(new DateTime(1958, 3, 2), d.AddMonthsByEnd(2, -12));
            Assert.AreEqual(new DateTime(1958, 2, 2), d.AddMonthsByEnd(2, -13));
        }
Exemple #6
0
        public void AddMonthsByEnd_1b()
        {
            DateTime d = new DateTime(1960, 3, 1);

            Assert.AreEqual(d, d.AddMonthsByEnd(1, 0));

            Assert.AreEqual(new DateTime(1960, 4, 1), d.AddMonthsByEnd(1, 1));
            Assert.AreEqual(new DateTime(1960, 5, 1), d.AddMonthsByEnd(1, 2));
            Assert.AreEqual(new DateTime(1961, 3, 1), d.AddMonthsByEnd(1, 12));
            Assert.AreEqual(new DateTime(1961, 4, 1), d.AddMonthsByEnd(1, 13));
            Assert.AreEqual(new DateTime(1961, 5, 1), d.AddMonthsByEnd(1, 14));
            Assert.AreEqual(new DateTime(1961, 6, 1), d.AddMonthsByEnd(1, 15));

            Assert.AreEqual(new DateTime(1960, 2, 1), d.AddMonthsByEnd(1, -1));
            Assert.AreEqual(new DateTime(1960, 1, 1), d.AddMonthsByEnd(1, -2));
            Assert.AreEqual(new DateTime(1959, 4, 1), d.AddMonthsByEnd(1, -11));
            Assert.AreEqual(new DateTime(1959, 3, 1), d.AddMonthsByEnd(1, -12));
            Assert.AreEqual(new DateTime(1959, 2, 1), d.AddMonthsByEnd(1, -13));
        }
Exemple #7
0
        public void AddMonthsByEnd_0c()
        {
            DateTime d = new DateTime(1959, 2, 28);

            Assert.AreEqual(d, d.AddMonthsByEnd(0, 0));

            Assert.AreEqual(new DateTime(1959, 3, 31), d.AddMonthsByEnd(0, 1));
            Assert.AreEqual(new DateTime(1959, 4, 30), d.AddMonthsByEnd(0, 2));
            Assert.AreEqual(new DateTime(1960, 2, 29), d.AddMonthsByEnd(0, 12));
            Assert.AreEqual(new DateTime(1960, 3, 31), d.AddMonthsByEnd(0, 13));
            Assert.AreEqual(new DateTime(1960, 4, 30), d.AddMonthsByEnd(0, 14));
            Assert.AreEqual(new DateTime(1960, 5, 31), d.AddMonthsByEnd(0, 15));

            Assert.AreEqual(new DateTime(1959, 1, 31), d.AddMonthsByEnd(0, -1));
            Assert.AreEqual(new DateTime(1958, 12, 31), d.AddMonthsByEnd(0, -2));
            Assert.AreEqual(new DateTime(1958, 3, 31), d.AddMonthsByEnd(0, -11));
            Assert.AreEqual(new DateTime(1958, 2, 28), d.AddMonthsByEnd(0, -12));
            Assert.AreEqual(new DateTime(1958, 1, 31), d.AddMonthsByEnd(0, -13));
        }