/// <summary>
        /// Retrieves information about the sales quarter based on the period number and the year.
        /// </summary>
        /// <param name="period">
        /// The period you wish to get quarter information for.
        /// </param>
        /// <param name="year">
        /// The year you wish to get quarter information for.
        /// </param>
        /// <returns>
        /// Quarter
        /// </returns>
        public static Quarter GetQuarter(int period, int year)
        {
            // Make sure the period passed in is valid.
            ValidatePeriod(period);

            // Divide the period by 3, round up to the nearest whole number.
            var quarterNumber = (int) Math.Ceiling((decimal) period/3);

            // Make sure the quarter is valid.
            ValidateQuarter(quarterNumber);

            var returnValue = new Quarter
            {
                Year = year,
                Number = quarterNumber
            };

            var dateRange = new DateRange();

            // Return different values for the rest of the object depending on what the quarter number is.
            switch (returnValue.Number)
            {
                case 1:
                    returnValue.Name = "Spring";
                    dateRange.StartDate = GetPeriodDateRange(1, year).StartDate;
                    dateRange.EndDate = GetPeriodDateRange(3, year).EndDate;
                    break;
                case 2:
                    returnValue.Name = "Summer";
                    dateRange.StartDate = GetPeriodDateRange(4, year).StartDate;
                    dateRange.EndDate = GetPeriodDateRange(6, year).EndDate;
                    break;
                case 3:
                    returnValue.Name = "Fall";
                    dateRange.StartDate = GetPeriodDateRange(7, year).StartDate;
                    dateRange.EndDate = GetPeriodDateRange(9, year).EndDate;
                    break;
                case 4:
                    returnValue.Name = "Winter";
                    dateRange.StartDate = GetPeriodDateRange(10, year).StartDate;
                    dateRange.EndDate = GetPeriodDateRange(12, year).EndDate;
                    break;
            }

            returnValue.DateRange = dateRange;

            return returnValue;
        }
 /// <summary>
 /// Exception thrown for date ranges where the start date is after the end date.
 /// </summary>
 /// <param name="dateRange">
 /// the DateRange that caused the exception.
 /// </param>
 public InvalidDateRangeException(DateRange dateRange)
     : base(String.Format("Start date must be before end date. Dates: {0} - {1}", dateRange.StartDate, dateRange.EndDate))
 {
 }
        /* The Merchandise calendar year is a 52 week year starting in February. It's calculated by
         * taking the first full Sunday to Saturday week in February with less than four days from
         * January in it. If, after the 52 weeks have been calculated, there are still more than three
         * days from January of the next calenday year left, an extra, 53rd week is added to the
         * merchandise calendar. This happens every five or six years to account for the one day
         * discrepancy between the merchandise calendar year and the normal calendar year. */
        private void SetDateRange(int year)
        {
            // Merchandise calendar starts in February.
            var firstDayOfFeb = new DateTime(year, 2, 1);

            // Integer representing the day of the week for the first of February.
            var firstFebDayOfWeek = (int)firstDayOfFeb.DayOfWeek;
            var nextYear = year + 1;

            /* Subtract days until you get to Sunday, which is the start of a merchandise calendar week.
             * This is your start date for the year, except when... */
            var startDate = firstDayOfFeb.AddDays((0 - firstFebDayOfWeek));

            /* ...February 1st falls on Thu - Sat, meaning there are more than three days from January in the
             * first week, also meaning the year before was a 53 week year. In that case, add a week
             * to the start date. */
            if (firstFebDayOfWeek > 3)
                startDate = startDate.AddDays(7);

            /* Add 52 weeks' worth of days (364) to the start date to get the end date, taking into
             * account the start day constitutes one of them (-1). */
            var endDate = startDate.AddDays(363);

            /* If the end date is January 27th of next year or earlier, there will be more than 3 January
             * days at the beginning of the next year and another week needs to be added to account for this. */
            if (endDate <= new DateTime(nextYear, 1, 27))
            {
                endDate = endDate.AddDays(7);
                ExtraWeek = true;
            }
            else
            {
                ExtraWeek = false;
            }

            DateRange = new DateRange
            {
                StartDate = startDate,
                EndDate = endDate.Add(new TimeSpan(0, 23, 59, 59, 999))
            };
        }
 private static void ValidateDateRange(DateRange dateRange)
 {
     if (dateRange.StartDate > dateRange.EndDate)
         throw new InvalidDateRangeException(dateRange);
 }
        /// <summary>
        /// Retrieves all Merchandise Dates between the startDate and endDate
        /// </summary>
        /// <param name="startDate">
        /// The start date.
        /// </param>
        /// <param name="endDate">
        /// The end date.
        /// </param>
        /// <returns>
        /// IEnumerable&lt;MerchandiseDate&gt;
        /// </returns>
        public static IEnumerable<MerchandiseDate> GetMerchandiseDatesBetween(DateTime startDate, DateTime endDate)
        {
            DateRange dateRange = new DateRange();
            dateRange.EndDate = endDate;
            dateRange.StartDate = startDate;

            return GetMerchandiseDatesBetween(dateRange);
        }
        /// <summary>
        /// Retrieves all Merchandise Dates within the dateRange
        /// </summary>
        /// <param name="dateRange">
        /// The date range you wish to get the list of dates for.
        /// </param>
        /// <returns>
        /// IEnumerable&lt;MerchandiseDate&gt;
        /// </returns>
        public static IEnumerable<MerchandiseDate> GetMerchandiseDatesBetween(DateRange dateRange)
        {
            List<MerchandiseDate> merchandiseDateList = new List<MerchandiseDate>();

            for (DateTime date = dateRange.StartDate; date <= dateRange.EndDate; date = date.AddDays(1))
            {
                int week = DateFunctions.GetWeek(date);

                int period = DateFunctions.GetPeriod(week);

                int month = (period + 1);

                if (month == 13)
                { month = 1; }

                Quarter quarter = DateFunctions.GetQuarter(date);

                MerchandiseDate merchandiseDate = new MerchandiseDate();
                merchandiseDate.Date = date;
                merchandiseDate.DayOfYear = DateFunctions.GetDayOfYear(date);
                merchandiseDate.Period = DateFunctions.GetPeriod(week);
                merchandiseDate.PeriodName = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(month);
                merchandiseDate.Quarter = quarter.Number;
                merchandiseDate.QuarterName = quarter.Name;
                merchandiseDate.Week = week;
                merchandiseDate.Year = DateFunctions.GetYear(date);

                merchandiseDateList.Add(merchandiseDate);
            }

            return merchandiseDateList;
        }
 /// <summary>
 /// Exception thrown for date ranges where the start date is after the end date.
 /// </summary>
 /// <param name="dateRange">
 /// the DateRange that caused the exception.
 /// </param>
 public InvalidDateRangeException(DateRange dateRange) :
     base(String.Format("Start date must be before end date. Dates: {0} - {1}", dateRange.StartDate, dateRange.EndDate))
 {
 }
        /// <summary>
        /// Returns a list of DateTime representing all calendar days between two dates.
        /// </summary>
        /// <param name="dateRange">
        /// The date range you wish to get the list of dates for.
        /// </param>
        /// <returns>
        /// IEnumerable&lt;DateTime&gt;
        /// </returns>
        public static IEnumerable <DateTime> GetAllDatesBetween(this DateRange dateRange)
        {
            ValidateDateRange(dateRange);

            return(GetAllDatesBetween(dateRange.StartDate, dateRange.EndDate));
        }