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