def _in_dom_range(self, rng, year, month, day_of_month): # if either range value is negative, convert to positive by counting back from end of the month if rng.start < 0 or rng.end < 0: days_in_month = get_days_in_month(year, month) rng = rng.clone() if rng.start < 0: rng.start = days_in_month + rng.start + 1 if rng.end < 0: rng.end = days_in_month + rng.end + 1 return self._in_integer_range(rng, day_of_month, get_days_in_previous_month(year, month))
def _validate_date(self, value, index): if value.year is not None: if value.year < 1900 or value.year > 2200: raise SchyntaxParseException("Year %d is not a valid year. Must be between 1900 and 2200." % value.year, self._input, index) if value.month < 1 or value.month > 12: raise SchyntaxParseException("Month %d is not a valid month. Must be between 1 and 12." % value.month, self._input, index) year = value.year if year is None: year = 2000 # default to a leap year, if no year is specified days_in_month = get_days_in_month(year, value.month) if value.day < 1 or value.day > days_in_month: raise SchyntaxParseException("%d is not a valid day for the month specified. Must be between 1 and %d" % (value.day, days_in_month), self._input, index)
def _in_date_range(self, rng, year, month, day_of_month): if rng.is_half_open: if rng.end.day == day_of_month and rng.end.month == month and (rng.end.year is None or rng.end.year == year): return False # check if in between start and end dates if rng.start.year is not None: # absolute dates with years. both will have years or neither will. if year < rng.start.year or year > rng.end.year: return False if year == rng.start.year and self._compare_month_and_day(month, day_of_month, rng.start.month, rng.start.day) < 0: return False if year == rng.end.year and self._compare_month_and_day(month, day_of_month, rng.end.month, rng.end.day) > 0: return False elif rng.start > rng.end: # split range # "split ranges aren't allowed to have years (it wouldn't make any sense)" if month == rng.start.month or month == rng.end.month: if month == rng.start.month and day_of_month < rng.start.day: return False if month == rng.end.month and day_of_month > rng.end.day: return False elif not (month < rng.end.month or month > rng.start.month): return False else: # "not a split range, and no year information - just month and day to go on" if self._compare_month_and_day(month, day_of_month, rng.start.month, rng.start.day) < 0: return False if self._compare_month_and_day(month, day_of_month, rng.end.month, rng.end.day) > 0: 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 rng.interval == 1: # I just made nonspecified intervals unify to a 1 return True # "figure out the actual date of the low date so we know whether we're on the desired interval" if rng.start.year is not None: start_year = rng.start.year elif rng.start > rng.end and month <= rng.end.month: # "start date is from the previous year" start_year = year - 1 else: start_year = year start_day = rng.start.day # "check if start date was actually supposed to be February 29th, but isn't because of non-leap-year." if rng.start.month == 2 and rng.start.day == 29 and get_days_in_month(start_year, 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." start_day = 28 start = datetime.date(start_year, rng.start.month, start_day) current = datetime.date(year, month, day_of_month) day_count = (current - start).days return day_count % rng.interval == 0