There is a list of church posts with dates and names, I enter the date and get what date the post belongs to or null if the day is not a fast one.
#!/usr/bin/env python3 from datetime import datetime from collections import namedtuple DateRange = namedtuple('DateRange', 'start end') dates = { 'Великий Пост': make_date_range("14 марта – 30 апреля 2016"), 'Петров пост': make_date_range("27 июня – 11 июля 2016"), # ... } now = datetime.now() fast = next((name for name, r in dates.items() if r.start <= now < r.end), None)
fast is the name of the post or None if there is no post today (not including. .end date — use <= r.end to include the end date if necessary), where:
import re def make_date_range(date_range_string): d1, m1, d2, m2, year = re.match(r"(\d+)\s*(\w+)\s*–\s*(\d+)\s*(\w+)\s*(\d+)", date_range_string).groups() months = {'марта': 3, 'апреля': 4, 'июня': 6, 'июля': 7} # ... return DateRange(datetime(int(year), months[m1], int(d1)), datetime(int(year), months[m2], int(d2)))
Related question: Find first element in a predicate sequence
If there is a list of dates, then you can quickly find to which date range / interval the entered date belongs, using the bisect module, which performs a binary search on a sorted list :
from bisect import bisect Y = datetime.now().year seasons = [datetime(*args) for args in [ (Y, 1, 1), # winter (Y, 3, 1), # spring (Y, 6, 1), # summer (Y, 9, 1), # autumn (Y, 12, 1) # winter ]] season_names = [None, 'winter', 'spring', 'summer', 'autumn', 'winter'] index = bisect(seasons, datetime.now()) print(season_names[index]) # -> autumn