Пример #1
0
        private static void CompileDateArgument(IrGroup irGroup, ArgumentNode arg)
        {
            IrDate irStart;
            IrDate?irEnd   = null;
            var    isSplit = false;

            if (arg.IsWildcard)
            {
                irStart = new IrDate(null, 1, 1);
                irEnd   = new IrDate(null, 12, 31);
            }
            else
            {
                var start = (DateValueNode)arg.Range.Start;
                irStart = new IrDate(start.Year, start.Month, start.Day);

                if (arg.Range.End != null)
                {
                    var end = (DateValueNode)arg.Range.End;
                    irEnd = new IrDate(end.Year, end.Month, end.Day);
                }
                else if (arg.HasInterval)
                {
                    // if there is an interval, but no end value specified, then the end value is implied
                    irEnd = new IrDate(null, 12, 31);
                }

                // check for split range (spans January 1) - not applicable for dates with explicit years
                if (irEnd.HasValue && !start.Year.HasValue)
                {
                    if (irStart.Month >= irEnd.Value.Month &&
                        (irStart.Month > irEnd.Value.Month || irStart.Day > irEnd.Value.Day))
                    {
                        isSplit = true;
                    }
                }
            }

            var irArg = new IrDateRange(irStart, irEnd, arg.HasInterval ? arg.IntervalValue : 0, isSplit, arg.Range?.IsHalfOpen ?? false);

            (arg.IsExclusion ? irGroup.DatesExcluded : irGroup.Dates).Add(irArg);
        }
Пример #2
0
        private static void CompileDateArgument(IrGroup irGroup, ArgumentNode arg)
        {
            IrDate irStart;
            IrDate? irEnd = null;
            var isSplit = false;

            if (arg.IsWildcard)
            {
                irStart = new IrDate(null, 1, 1);
                irEnd = new IrDate(null, 12, 31);
            }
            else
            {
                var start = (DateValueNode)arg.Range.Start;
                irStart = new IrDate(start.Year, start.Month, start.Day);

                if (arg.Range.End != null)
                {
                    var end = (DateValueNode)arg.Range.End;
                    irEnd = new IrDate(end.Year, end.Month, end.Day);
                }
                else if (arg.HasInterval)
                {
                    // if there is an interval, but no end value specified, then the end value is implied
                    irEnd = new IrDate(null, 12, 31);
                }

                // check for split range (spans January 1) - not applicable for dates with explicit years
                if (irEnd.HasValue && !start.Year.HasValue)
                {
                    if (irStart.Month >= irEnd.Value.Month &&
                        (irStart.Month > irEnd.Value.Month || irStart.Day > irEnd.Value.Day))
                    {
                        isSplit = true;
                    }
                }
            }

            var irArg = new IrDateRange(irStart, irEnd, arg.HasInterval ? arg.IntervalValue : 0, isSplit, arg.Range?.IsHalfOpen ?? false);
            (arg.IsExclusion ? irGroup.DatesExcluded : irGroup.Dates).Add(irArg);
        }
Пример #3
0
        private static bool InDateRange(IrDateRange range, int year, int month, int dayOfMonth)
        {
            // first, check if this is actually a range
            if (!range.IsRange)
            {
                // not a range, so just to a straight comparison
                if (range.Start.Month != month || range.Start.Day != dayOfMonth)
                    return false;

                if (range.DatesHaveYear && range.Start.Year != year)
                    return false;

                return true;
            }

            if (range.IsHalfOpen)
            {
                // check if this is the last date in a half-open range
                var end = range.End;
                if (end.Day == dayOfMonth && end.Month == month && (!range.DatesHaveYear || end.Year == year))
                    return false;
            }

            // check if in-between start and end dates.
            if (range.DatesHaveYear)
            {
                // when we have a year, the check is much simpler because the range can't be split
                if (year < range.Start.Year || year > range.End.Year)
                    return false;

                if (year == range.Start.Year && CompareMonthAndDay(month, dayOfMonth, range.Start.Month, range.Start.Day) == -1)
                    return false;

                if (year == range.End.Year && CompareMonthAndDay(month, dayOfMonth, range.End.Month, range.End.Day) == 1)
                    return false;
            }
            else if (range.IsSplit) // split ranges aren't allowed to have years (it wouldn't make any sense)
            {
                if (month == range.Start.Month || month == range.End.Month)
                {
                    if (month == range.Start.Month && dayOfMonth < range.Start.Day)
                        return false;

                    if (month == range.End.Month && dayOfMonth > range.End.Day)
                        return false;
                }
                else if (!(month < range.End.Month || month > range.Start.Month))
                {
                    return false;
                }
            }
            else
            {
                // not a split range, and no year information - just month and day to go on
                if (CompareMonthAndDay(month, dayOfMonth, range.Start.Month, range.Start.Day) == -1)
                    return false;

                if (CompareMonthAndDay(month, dayOfMonth, range.End.Month, range.End.Day) == 1)
                    return false;
            }

            // If we get here, then we're definitely somewhere within the range.
            // If there's no interval, then there's nothing else we need to check
            if (!range.HasInterval)
                return true;

            // figure out the actual date of the low date so we know whether we're on the desired interval
            int startYear;
            if (range.DatesHaveYear)
            {
                startYear = range.Start.Year;
            }
            else if (range.IsSplit && month <= range.End.Month)
            {
                // start date is from the previous year
                startYear = year - 1;
            }
            else
            {
                startYear = year;
            }

            var startDay = range.Start.Day;

            // check if start date was actually supposed to be February 29th, but isn't because of non-leap-year.
            if (range.Start.Month == 2 && range.Start.Day == 29 && DateTime.DaysInMonth(startYear, 2) != 29)
            {
                // bump the start day back to February 28th so that interval schemes work based on that imaginary date
                // but seriously, people should probably just expect weird results if they're doing something that stupid.
                startDay = 28;
            }

            var start = new DateTimeOffset(startYear, range.Start.Month, startDay, 0, 0, 0, TimeSpan.Zero);
            var current = new DateTimeOffset(year, month, dayOfMonth, 0, 0, 0, TimeSpan.Zero);
            var dayCount = Math.Round((current - start).TotalDays);

            return (dayCount % range.Interval) == 0;
        }