def _get_last_monday_midnight(time: datetime) -> datetime: """Given a datetime, gets the most recent midnight on a Monday.""" return time - relativedelta.relativedelta( hour=0, minute=0, second=0, microsecond=0, weekday=relativedelta.MO(-1) )
def get_spring_bank_holiday(self, year): day = date(year, 5, 30) + rd.relativedelta(weekday=rd.MO(-1)) if year in (2012, 2002): day = date(year, 6, 4) if year in (1977,): day = date(year, 6, 6) return Holiday( day, "Spring Bank Holiday", indication="Last Monday in May", ),
def get_variable_days(self, year): days = super().get_variable_days(year) days.append( Holiday( date(year, 2, 1) + rd.relativedelta(weekday=rd.MO(1)), "Constitution Day", )) days.append( Holiday( date(year, 3, 1) + rd.relativedelta(weekday=rd.MO(3)), "Benito Juárez's birthday", )) days.append( Holiday( date(year, 11, 1) + rd.relativedelta(weekday=rd.MO(3)), "Revolution Day", )) return days
def get_datetime(t): # get start and end of this week week_s = t + relativedelta.relativedelta( hour=0, minute=0, second=0, weekday=relativedelta.MO(-1)) week_e = t + relativedelta.relativedelta( hour=23, minute=59, second=59, weekday=relativedelta.SU(0)) month_s = t + relativedelta.relativedelta( hour=0, minute=0, second=0, day=1) month_e = t + relativedelta.relativedelta( hour=23, minute=59, second=59, day=1, months=1, days=-1) day_s = t + relativedelta.relativedelta(hour=0, minute=0, second=0) day_e = t + relativedelta.relativedelta(hour=23, minute=59, second=59) return week_s, week_e, month_s, month_e, day_s, day_e
def get_early_may_bank_holiday(self, year): """ Return Early May bank holiday """ day = date(year, 5, 1) + rd.relativedelta(weekday=rd.MO(1)) desc = "Early May Bank Holiday" indication = "1st Monday in May" # Special case in 2020, for the 75th anniversary of the end of WWII. if year == 2020: day = date(year, 5, 8) desc += " (VE day)" indication = "VE day" return Holiday(day, desc, indication=indication)
def meetup_day(year, month, targetday, targetweek): weekdays = dict(zip(list(calendar.day_name), range(7))) steps = dict(zip(['1st', '2nd', '3rd', '4th', 'last'], range(7, 36, 7))) steps['teenth'] = 19 targetday = weekdays[targetday] getDay = { 0: relativedelta.MO(-1), 1: relativedelta.TU(-1), 2: relativedelta.WE(-1), 3: relativedelta.TH(-1), 4: relativedelta.FR(-1), 5: relativedelta.SA(-1), 6: relativedelta.SU(-1), } d = datetime.date(year, month, 1) + relativedelta.relativedelta( day=steps[targetweek], weekday=getDay[targetday]) return d
def all_weekdays(year, month, week, day_of_week): dt = date(year, month, 1) if week == 'last': clean_week = int(-1) if month == 1 or month == 3 or month == 5 or month == 7 or month == 8 or month == 10 or month == 12: day_offset = 31 elif month == 2: day_offset = 28 else: day_offset = 30 else: clean_week = +int(week.strip("stndrh")) day_offset = 0 if day_of_week == 'Monday': the_date = dt + rdelta.relativedelta(days=day_offset, weekday=rdelta.MO(clean_week)) return the_date elif day_of_week == 'Tuesday': the_date = dt + rdelta.relativedelta(days=day_offset, weekday=rdelta.TU(clean_week)) return the_date elif day_of_week == 'Wednesday': the_date = dt + rdelta.relativedelta(days=day_offset, weekday=rdelta.WE(clean_week)) return the_date elif day_of_week == 'Thursday': the_date = dt + rdelta.relativedelta(days=day_offset, weekday=rdelta.TH(clean_week)) return the_date elif day_of_week == 'Friday': the_date = dt + rdelta.relativedelta(days=day_offset, weekday=rdelta.FR(clean_week)) return the_date elif day_of_week == 'Saturday': the_date = dt + rdelta.relativedelta(days=day_offset, weekday=rdelta.SA(clean_week)) return the_date elif day_of_week == 'Sunday': the_date = dt + rdelta.relativedelta(days=day_offset, weekday=rdelta.SU(clean_week)) return the_date
def mon(a): monday = str(today + rdelta.relativedelta(weekday=rdelta.MO(a))) output = monday[8:10] + '/' + monday[5:7] + '/' + monday[2:4] return output
def get_n_mondays_ago(n): today = datetime.now() n_mondays_ago = relativedelta.relativedelta(weekday=relativedelta.MO(-n)) return (today - n_mondays_ago).strftime("%Y-%m-%d")
import logging import os from datetime import datetime from dateutil import relativedelta from functools import wraps from time import sleep from zeep import Client DATETIME_STRING_FMT = "%Y-%m-%d" one_sunday_ago = relativedelta.relativedelta(weekday=relativedelta.SU(-5)) last_sunday_string = (datetime.now() + one_sunday_ago).strftime(DATETIME_STRING_FMT) two_mondays_ago = relativedelta.relativedelta(weekday=relativedelta.MO(-6)) two_mondays_ago_string = (datetime.now() - two_mondays_ago).strftime(DATETIME_STRING_FMT) RETRY_ATTEMPTS = 2 class BaseJobDivaClient: def __init__(self, service): self.username = os.environ["JOBDIVA_USERNAME"] self.password = os.environ["JOBDIVA_PASSWORD"] self.logger = logging.getLogger(f"JobDivaClient - {service}") self._client = Client( f"https://ws.jobdiva.com/axis2-1.6.1/services/{service}?wsdl") for method_name in dir(self._client.service): if not method_name.startswith("__"):
# Basis of the recurring repeat modified from: https://stackoverflow.com/questions/2295765/generating-recurring-dates-using-python # Import date modules: import dateutil.rrule as dr import dateutil.parser as dp import dateutil.relativedelta as drel import datetime # Import @33MHz and @thrrgilag's library for interacting with pnut.io: import pnutpy start=dp.parse("01/01/2018") # First Monday in January 2018 # Setup a list of dates, adjust count to something larger, in multiples of 12 (momths): rr = dr.rrule(dr.MONTHLY,byweekday=drel.MO(1),dtstart=start, count=12) # What's today's date?: t = datetime.date.today() t = t.strftime('%d/%m/%Y') x = ([d.strftime('%d/%m/%Y') for d in rr[::1]]) # If today is a week to go until #ThemeMonday: pnut_message = '' n = 0 while n <= 11: tmprev = (x[n]) if tmprev == t: pnut_message = 'There\'s a week to go until #ThemeMonday. Let\'s suggest themes and start a poll before the weekend!' n += 1
def get_national_memorial_day(self, year): return Holiday( date(year, 5, 31) + rd.relativedelta(weekday=rd.MO(-1)), self.national_memorial_day_label, indication="Last Monday in May", )
def get_presidents_day(self, year): return Holiday( date(year, 2, 1) + rd.relativedelta(weekday=rd.MO(3)), self.presidents_day_label, indication="3rd Monday in February", )
arr_localized = dep_localized + self.duration dest_tz = pytz.timezone(self.destination.tz) arr_asdest = dest_tz.normalize( arr_localized.astimezone(dest_tz)) # DST normalize return datetime.combine(arr_asdest.date(), arr_asdest.time()) generator = FlightGenerator(flight_id='AA123', origin=airports['ATL'], destination=airports['SVO'], duration=timedelta(hours=13, minutes=25)) # third Monday of every month in 2018 flights = generator.generate_flights( dr.rrule(freq=dr.WEEKLY, byweekday=relativedelta.MO(3), dtstart=datetime(2018, 1, 1, 10, 30, 0), count=12)) flights += generator.generate_flights( dr.rrule(freq=dr.HOURLY, interval=3, dtstart=datetime(2019, 1, 1, 15, 0, 0), count=3)) flights += generator.generate_flights( dr.rrule(freq=dr.HOURLY, byhour=[10, 13], dtstart=datetime(2019, 2, 1, 15, 0, 0), until=datetime(2019, 2, 4, 15, 0, 0)))
def get_queens_birthday(self, year): return Holiday( date(year, 6, 1) + rd.relativedelta(weekday=rd.MO(1)), "Queen's Birthday", indication="First Monday in June", )
def next_last_monday(): now = datetime.datetime.utcnow() day = now + relativedelta.relativedelta(month=now.month + 1, weekday=relativedelta.MO(-1)) day.replace(hour=6, minute=0, second=0, microsecond=0) return day
print( make_python_call_string(subject, script, "-t", subject, font=trackfont)) print(make_python_call_string("mark", script, "-m")) print(make_python_call_string("cancel", script, "-c")) print(make_python_call_string("end", script, "-e")) print('---') now = datetime.datetime.now() four_hours_ago = now - datetime.timedelta(hours=4) last_24_hours = now - datetime.timedelta(days=1) last_day = four_hours_ago.replace(hour=4, minute=0, second=0, microsecond=0) last_week = now - datetime.timedelta(days=7) delta = relativedelta.relativedelta(weekday=relativedelta.MO(-1), hour=4, minute=0, second=0, microsecond=0) last_workweek = four_hours_ago + delta splice_tables("Last 24 hours", "Today", interface.get_progress(last_24_hours), interface.get_progress(last_day)) print(interface.get_total(last_24_hours) + subfont) print(interface.get_total(last_day) + subfont + " alternate=true") splice_tables("Last 7 Days", "Last Work Week", interface.get_progress(last_week), interface.get_progress(last_workweek)) print(interface.get_total(last_week) + subfont)
def lambda_handler(): dynamodb = boto3.resource( 'dynamodb', region_name='eu-west-1', endpoint_url="https://dynamodb.eu-west-1.amazonaws.com") table = dynamodb.Table('PlantersMeasurements') planterId = "e0221623-fb88-4fbd-b524-6f0092463c93" utcNow = datetime.utcnow() now = decimal.Decimal(utcNow.timestamp()) dayAgo = decimal.Decimal( (utcNow + timedelta(hours=-(utcNow.hour))).timestamp()) response = table.query( # ProjectionExpression="#yr, title, info.genres, info.actors[0]", # ExpressionAttributeNames={ "#yr": "year" }, # Expression Attribute Names for Projection Expression only. KeyConditionExpression=Key('planterId').eq(planterId) & Key('timeStamp').between(dayAgo, now)) plots = { "daily": { "soilHumidity": { 'labels': [], "datasets": [{ 'data': [] }] }, "uvIntensity": { 'labels': [], "datasets": [{ 'data': [] }] }, "ambientTemperatureCelsius": { 'labels': [], "datasets": [{ 'data': [] }] } }, "weekly": { "soilHumidity": { 'labels': [], "datasets": [{ 'data': [] }] }, "uvIntensity": { 'labels': [], "datasets": [{ 'data': [] }] }, "ambientTemperatureCelsius": { 'labels': [], "datasets": [{ 'data': [] }] } } } items = response["Items"] print(len(items)) h = datetime.fromtimestamp(items[0]["timeStamp"]).hour last = datetime.fromtimestamp(items[len(items) - 1]["timeStamp"]) hoursCount = last.hour + 1 print('last ', last) print('first ', datetime.fromtimestamp(items[0]["timeStamp"])) plots["daily"]["soilHumidity"]["datasets"][0]["data"] = [None] * hoursCount plots["daily"]["soilHumidity"]["labels"] = [""] * hoursCount plots["daily"]["soilHumidity"]["labels"][0] = "0" plots["daily"]["soilHumidity"]["labels"][h - 1] = f"{last.hour:0}" plots["daily"]["uvIntensity"]["datasets"][0]["data"] = [None] * hoursCount plots["daily"]["uvIntensity"]["labels"] = [""] * hoursCount plots["daily"]["uvIntensity"]["labels"][0] = "0" plots["daily"]["uvIntensity"]["labels"][h - 1] = f"{last.hour:0}" plots["daily"]["ambientTemperatureCelsius"]["datasets"][0]["data"] = [ None ] * hoursCount plots["daily"]["ambientTemperatureCelsius"]["labels"] = [""] * hoursCount plots["daily"]["ambientTemperatureCelsius"]["labels"][0] = "0" plots["daily"]["ambientTemperatureCelsius"]["labels"][h - 1] = f"{last.hour:0}" my_sum = [0, 0, 0] count = 0 for i in items: date = datetime.fromtimestamp(i["timeStamp"]) soilHumidity = i["soilHumidity"] uvIntensity = i["uvIntesity"] ambientTemperatureCelsius = i["ambientTemperatureCelsius"] if h != date.hour or date == last: if date == last: my_sum[0] = my_sum[0] + soilHumidity my_sum[1] = my_sum[1] + uvIntensity my_sum[2] = my_sum[2] + ambientTemperatureCelsius count = count + 1 plots["daily"]["soilHumidity"]["datasets"][0]["data"][h] = (round( my_sum[0] / count, 2)) plots["daily"]["uvIntensity"]["datasets"][0]["data"][h] = (round( my_sum[1] / count, 2)) plots["daily"]["ambientTemperatureCelsius"]["datasets"][0]["data"][ h] = (round(my_sum[2] / count, 2)) h = date.hour my_sum = [0, 0, 0] count = 0 my_sum[0] = my_sum[0] + soilHumidity my_sum[1] = my_sum[1] + uvIntensity my_sum[2] = my_sum[2] + ambientTemperatureCelsius count = count + 1 now = decimal.Decimal(utcNow.timestamp()) today = datetime.today() past_monday = today + rdelta.relativedelta(days=-1, weekday=rdelta.MO(-1)) past_monday = decimal.Decimal( past_monday.replace(hour=00, minute=00).timestamp()) response = table.query( # ProjectionExpression="#yr, title, info.genres, info.actors[0]", # ExpressionAttributeNames={ "#yr": "year" }, # Expression Attribute Names for Projection Expression only. KeyConditionExpression=Key('planterId').eq(planterId) & Key('timeStamp').between(past_monday, now)) days = {} items = response['Items'] count = 0 for i in items: date = datetime.fromtimestamp(i["timeStamp"]) soilHumidity = i["soilHumidity"] uvIntensity = i["uvIntesity"] ambientTemperatureCelsius = i["ambientTemperatureCelsius"] #add day to dict if dayNameFromWeekday(date.weekday()) not in days: days[dayNameFromWeekday(date.weekday())] = dict( soilHumidity={"sum": []}, uvIntensity={"sum": []}, ambientTemperatureCelsius={"sum": []}) days[dayNameFromWeekday(date.weekday())]['soilHumidity']['sum'].append( float(soilHumidity)) days[dayNameFromWeekday(date.weekday())]['uvIntensity']['sum'].append( float(uvIntensity)) if ambientTemperatureCelsius > 0 and ambientTemperatureCelsius < 50: days[dayNameFromWeekday( date.weekday())]['ambientTemperatureCelsius']['sum'].append( float(ambientTemperatureCelsius)) for val in days: days[val]['soilHumidity']['max'] = decimal.Decimal( str(float(max(days[val]['soilHumidity']['sum'])))) days[val]['soilHumidity']['min'] = decimal.Decimal( str(float(min(days[val]['soilHumidity']['sum'])))) i = decimal.Decimal( str( float( sum(days[val]['soilHumidity']['sum']) / len(days[val]['soilHumidity']['sum'])))) days[val]['soilHumidity']['avg'] = i days[val]['uvIntensity']['max'] = decimal.Decimal( str(float(max(days[val]['uvIntensity']['sum'])))) days[val]['uvIntensity']['min'] = decimal.Decimal( str(float(min(days[val]['uvIntensity']['sum'])))) days[val]['uvIntensity']['avg'] = decimal.Decimal( str( float( sum(days[val]['uvIntensity']['sum']) / len(days[val]['uvIntensity']['sum'])))) days[val]['ambientTemperatureCelsius']['max'] = decimal.Decimal( str( float("{:.2f}".format( max(days[val]['ambientTemperatureCelsius']['sum']))))) days[val]['ambientTemperatureCelsius']['min'] = decimal.Decimal( str( float("{:.2f}".format( min(days[val]['ambientTemperatureCelsius']['sum']))))) days[val]['ambientTemperatureCelsius']['avg'] = float("{:.2f}".format( sum(days[val]['ambientTemperatureCelsius']['sum']))) / float( "{:.2f}".format( len(days[val]['ambientTemperatureCelsius']['sum']))) days[val]['ambientTemperatureCelsius']['avg'] = decimal.Decimal( str(days[val]['ambientTemperatureCelsius']['avg'])) days[val]['uvIntensity']['sum'] = [] days[val]['soilHumidity']['sum'] = [] days[val]['ambientTemperatureCelsius']['sum'] = [] plots["weekly"] = days planters = dynamodb.Table('Test_Planters') response = planters.update_item(Key={'UUID': planterId}, UpdateExpression="set plots = :p", ExpressionAttributeValues={ ':p': plots, }, ReturnValues="UPDATED_NEW") return response
def OnActionMenu(self, event=None): id = event.GetId() dateJour = datetime.date.today() if id == ID_AUJOURDHUI: self.SetDate(dateJour) if id == ID_HIER: self.SetDate(dateJour - datetime.timedelta(days=1)) if id == ID_DEMAIN: self.SetDate(dateJour + datetime.timedelta(days=1)) # Semaine if id == ID_SEMAINE_ACTUELLE + 1: date = dateJour + relativedelta.relativedelta( weekday=relativedelta.MO(-1)) self.SetDate(date) if id == ID_SEMAINE_ACTUELLE + 2: date = dateJour + relativedelta.relativedelta( weekday=relativedelta.MO(-1)) self.SetDate(date + datetime.timedelta(days=6)) if id == ID_SEMAINE_PRECEDENTE + 1: date = dateJour + relativedelta.relativedelta( weekday=relativedelta.SU(-1)) self.SetDate(date - datetime.timedelta(days=6)) if id == ID_SEMAINE_PRECEDENTE + 2: date = dateJour + relativedelta.relativedelta( weekday=relativedelta.SU(-1)) self.SetDate(date) if id == ID_SEMAINE_SUIVANTE + 1: date = dateJour + relativedelta.relativedelta( weekday=relativedelta.MO(+1)) self.SetDate(date) if id == ID_SEMAINE_SUIVANTE + 2: date = dateJour + relativedelta.relativedelta( weekday=relativedelta.MO(+1)) self.SetDate(date + datetime.timedelta(days=6)) # Mois if id == ID_MOIS_ACTUEL + 1: self.SetDate(datetime.date(dateJour.year, dateJour.month, 1)) if id == ID_MOIS_ACTUEL + 2: mois = calendar.monthrange(dateJour.year, dateJour.month) self.SetDate(datetime.date(dateJour.year, dateJour.month, mois[1])) if id == ID_MOIS_PRECEDENT + 1: date = dateJour + relativedelta.relativedelta(months=-1) self.SetDate(datetime.date(date.year, date.month, 1)) if id == ID_MOIS_PRECEDENT + 2: date = dateJour + relativedelta.relativedelta(months=-1) mois = calendar.monthrange(date.year, date.month) self.SetDate(datetime.date(date.year, date.month, mois[1])) if id == ID_MOIS_SUIVANT + 1: date = dateJour + relativedelta.relativedelta(months=+1) self.SetDate(datetime.date(date.year, date.month, 1)) if id == ID_MOIS_SUIVANT + 2: date = dateJour + relativedelta.relativedelta(months=+1) mois = calendar.monthrange(date.year, date.month) self.SetDate(datetime.date(date.year, date.month, mois[1])) # Année if id == ID_ANNEE_ACTUELLE + 1: self.SetDate(datetime.date(dateJour.year, 1, 1)) if id == ID_ANNEE_ACTUELLE + 2: self.SetDate(datetime.date(dateJour.year, 12, 31)) if id == ID_ANNEE_PRECEDENTE + 1: date = dateJour + relativedelta.relativedelta(years=-1) self.SetDate(datetime.date(date.year, 1, 1)) if id == ID_ANNEE_PRECEDENTE + 2: date = dateJour + relativedelta.relativedelta(years=-1) self.SetDate(datetime.date(date.year, 12, 31)) if id == ID_ANNEE_SUIVANTE + 1: date = dateJour + relativedelta.relativedelta(years=+1) self.SetDate(datetime.date(date.year, 1, 1)) if id == ID_ANNEE_SUIVANTE + 2: date = dateJour + relativedelta.relativedelta(years=+1) self.SetDate(datetime.date(date.year, 12, 31)) if id == ID_AIDE: from Utils import UTILS_Aide UTILS_Aide.Aide("Slectionnerunedate")
def get_labour_day(self, year): return Holiday( date(year, 10, 1) + rd.relativedelta(weekday=rd.MO(4)), "Labour Day", indication="Fourth Monday in October", )
def last_monday(calc_from, number): """Finds the last Monday of the calc-from day's month""" return calc_from + relativedelta.relativedelta( day=31, weekday=relativedelta.MO(-1))
def next_last_monday(): now = date.today() day = now + relativedelta.relativedelta(month=now.month + 1, weekday=relativedelta.MO(1)) return day
def get_martin_luther_king_date(self, year): if year < 1985: raise ValueError( "Martin Luther King Day became a holiday in 1985" ) return date(year, 1, 1) + rd.relativedelta(weekday=rd.MO(3))
class CoreCalendar: FIXED_HOLIDAYS = () WEEKEND_DAYS = () observance_shift = dict(weekday=rd.MO(1)) """ The shift for the observance of a holiday defined as keyword parameters to a rd.relativedelta instance. By default, holidays are shifted to the Monday following the weekend. """ def __init__(self): self._holidays = {} @classproperty def name(cls): class_name = cls.__name__ if cls.__doc__: doc = cls.__doc__.split('\n') doc = map(lambda s: s.strip(), doc) return next(s for s in doc if s) return class_name def get_fixed_holidays(self, year): """Return the fixed days according to the FIXED_HOLIDAYS class property """ fixed_holidays = map( Holiday._from_fixed_definition, self.FIXED_HOLIDAYS, ) return [day.replace(year=year) for day in fixed_holidays] def get_variable_days(self, year): return [] def get_calendar_holidays(self, year): """Get calendar holidays. If you want to override this, please make sure that it **must** return a list of tuples (date, holiday_name).""" return self.get_fixed_holidays(year) + self.get_variable_days(year) def holidays(self, year=None): """Computes holidays (non-working days) for a given year. Return a 2-item tuple, composed of the date and a label.""" if not year: year = date.today().year if year in self._holidays: return self._holidays[year] # Here we process the holiday specific calendar days = self.get_calendar_holidays(year) days = map(Holiday._from_resolved_definition, days) temp_calendar = tuple(days) # it is sorted self._holidays[year] = sorted(temp_calendar) return self._holidays[year] def get_holiday_label(self, day): """Return the label of the holiday, if the date is a holiday""" day = cleaned_date(day) return {day: label for day, label in self.holidays(day.year) }.get(day) def get_observed_date(self, holiday): """ The date the holiday is observed for this calendar. If the holiday occurs on a weekend, it may be observed on another day as indicated by the observance_shift. The holiday may also specify an 'observe_after' such that it is always shifted after a preceding holiday. For example, Boxing day is always observed after Christmas Day is observed. """ # observance_shift may be overridden in the holiday itself shift = getattr(holiday, 'observance_shift', self.observance_shift) if callable(shift): return shift(holiday, self) shift = shift or {} delta = rd.relativedelta(**shift) should_shift = holiday.weekday() in self.get_weekend_days() shifted = holiday + delta if should_shift else holiday precedent = getattr(holiday, 'observe_after', None) while precedent and shifted <= self.get_observed_date(precedent): shifted += timedelta(days=1) return shifted def holidays_set(self, year=None): "Return a quick date index (set)" return set(self.holidays(year)) def get_weekend_days(self): """Return a list (or a tuple) of weekdays that are *not* working days. e.g: return (SAT, SUN,) """ if self.WEEKEND_DAYS: return self.WEEKEND_DAYS else: raise NotImplementedError("Your Calendar class must provide " "WEEKEND_DAYS or implement the " "`get_weekend_days` method") def is_working_day(self, day, extra_working_days=None, extra_holidays=None): """Return True if it's a working day. In addition to the regular holidays, you can add exceptions. By providing ``extra_working_days``, you'll state that these dates **are** working days. By providing ``extra_holidays``, you'll state that these dates **are** holidays, even if not in the regular calendar holidays (or weekends). Please note that the ``extra_working_days`` list has priority over the ``extra_holidays`` list. """ day = cleaned_date(day) if extra_working_days: extra_working_days = tuple(map(cleaned_date, extra_working_days)) if extra_holidays: extra_holidays = tuple(map(cleaned_date, extra_holidays)) # Extra lists exceptions if extra_working_days and day in extra_working_days: return True # Regular rules if day.weekday() in self.get_weekend_days(): return False if extra_holidays and day in extra_holidays: return False return not self.is_observed_holiday(day) def is_holiday(self, day, extra_holidays=None): """Return True if it's an holiday. In addition to the regular holidays, you can add exceptions. By providing ``extra_holidays``, you'll state that these dates **are** holidays, even if not in the regular calendar holidays (or weekends). """ day = cleaned_date(day) if extra_holidays: extra_holidays = tuple(map(cleaned_date, extra_holidays)) if extra_holidays and day in extra_holidays: return True return day in self.holidays_set(day.year) def is_observed_holiday(self, day): """Return True if it's an observed holiday. """ observed = set(map(self.get_observed_date, self.holidays(day.year))) return day in observed def add_working_days(self, day, delta, extra_working_days=None, extra_holidays=None, keep_datetime=False): """Add `delta` working days to the date. You can provide either a date or a datetime to this function that will output a ``date`` result. You can alter this behaviour using the ``keep_datetime`` option set to ``True``. the ``delta`` parameter might be positive or negative. If it's negative, you may want to use the ``sub_working_days()`` method with a positive ``delta`` argument. By providing ``extra_working_days``, you'll state that these dates **are** working days. By providing ``extra_holidays``, you'll state that these dates **are** holidays, even if not in the regular calendar holidays (or weekends). Please note that the ``extra_working_days`` list has priority over the ``extra_holidays`` list. """ day = cleaned_date(day, keep_datetime) if extra_working_days: extra_working_days = tuple(map(cleaned_date, extra_working_days)) if extra_holidays: extra_holidays = tuple(map(cleaned_date, extra_holidays)) days = 0 temp_day = day day_added = 1 if delta >= 0 else -1 delta = abs(delta) while days < delta: temp_day = temp_day + timedelta(days=day_added) if self.is_working_day(temp_day, extra_working_days=extra_working_days, extra_holidays=extra_holidays): days += 1 return temp_day def sub_working_days(self, day, delta, extra_working_days=None, extra_holidays=None, keep_datetime=False): """ Substract `delta` working days to the date. This method is a shortcut / helper. Users may want to use either:: cal.add_working_days(my_date, -7) cal.sub_working_days(my_date, 7) The other parameters are to be used exactly as in the ``add_working_days`` method. A negative ``delta`` argument will be converted into its absolute value. Hence, the two following calls are equivalent:: cal.sub_working_days(my_date, -7) cal.sub_working_days(my_date, 7) As in ``add_working_days()`` you can set the parameter ``keep_datetime`` to ``True`` to make sure that if your ``day`` argument is a ``datetime``, the returned date will also be a ``datetime`` object. """ delta = abs(delta) return self.add_working_days( day, -delta, extra_working_days, extra_holidays, keep_datetime=keep_datetime) def find_following_working_day(self, day): """Looks for the following working day, if not already a working day. **WARNING**: this function doesn't take into account the calendar holidays, only the days of the week and the weekend days parameters. """ day = cleaned_date(day) while day.weekday() in self.get_weekend_days(): day = day + timedelta(days=1) return day @staticmethod def get_nth_weekday_in_month(year, month, weekday, n=1, start=None): """Get the nth weekday in a given month. e.g: >>> # the 1st monday in Jan 2013 >>> Calendar.get_nth_weekday_in_month(2013, 1, MON) datetime.date(2013, 1, 7) >>> # The 2nd monday in Jan 2013 >>> Calendar.get_nth_weekday_in_month(2013, 1, MON, 2) datetime.date(2013, 1, 14) """ # If start is `None` or Falsy, no need to check and clean if start: start = cleaned_date(start) day = date(year, month, 1) if start: day = start counter = 0 while True: if day.month != month: # Don't forget to break if "n" is too big return None if day.weekday() == weekday: counter += 1 if counter == n: break day = day + timedelta(days=1) return day @staticmethod def get_last_weekday_in_month(year, month, weekday): """Get the last weekday in a given month. e.g: >>> # the last monday in Jan 2013 >>> Calendar.get_last_weekday_in_month(2013, 1, MON) datetime.date(2013, 1, 28) """ day = date(year, month, monthrange(year, month)[1]) while True: if day.weekday() == weekday: break day = day - timedelta(days=1) return day @staticmethod def get_first_weekday_after(day, weekday): """Get the first weekday after a given day. If the day is the same weekday, the same day will be returned. >>> # the first monday after Apr 1 2015 >>> Calendar.get_first_weekday_after(date(2015, 4, 1), MON) datetime.date(2015, 4, 6) >>> # the first tuesday after Apr 14 2015 >>> Calendar.get_first_weekday_after(date(2015, 4, 14), TUE) datetime.date(2015, 4, 14) """ day_delta = (weekday - day.weekday()) % 7 day = day + timedelta(days=day_delta) return day def get_working_days_delta(self, start, end, include_start=False): """ Return the number of working day between two given dates. The order of the dates provided doesn't matter. In the following example, there are 5 days, because of the week-end: >>> cal = WesternCalendar() # does not include easter monday >>> day1 = date(2018, 3, 29) >>> day2 = date(2018, 4, 5) >>> cal.get_working_days_delta(day1, day2) 5 In France, April 1st 2018 is a holiday because it's Easter monday: >>> from calendra.europe import France >>> cal = France() >>> cal.get_working_days_delta(day1, day2) 4 This method should even work if your ``start`` and ``end`` arguments are datetimes. By default, if the day after you start is not a working day, the count will start at 0. If include_start is set to true, this day will be taken into account. Example: >>> from dateutil.parser import parse >>> cal = France() >>> day_1 = parse('09/05/2018 00:01', dayfirst=True) >>> day_2 = parse('10/05/2018 19:01', dayfirst=True) # holiday in france >>> cal.get_working_days_delta(day_1, day_2) 0 >>> cal.get_working_days_delta(day_1, day_2, include_start=True) 1 """ start = cleaned_date(start) end = cleaned_date(end) if start == end: return 0 if start > end: start, end = end, start # Starting count here count = 1 if include_start and self.is_working_day(start) else 0 while start < end: start += timedelta(days=1) if self.is_working_day(start): count += 1 return count def _get_ical_period(self, period=None): """ Return a usable period for iCal export Default period is [2000, 2030] """ # Default value. if not period: period = [2000, 2030] # Make sure it's a usable iterable if type(period) not in (list, tuple): raise ICalExportRangeError( "Incorrect Range type. Must be list or tuple.") # Taking the extremes period = [min(period), max(period)] # check for internal types check_types = map(type, period) check_types = map(lambda x: x != int, check_types) if any(check_types): raise ICalExportRangeError( "Incorrect Range boundaries. Must be int.") return period def _get_ical_target_path(self, target_path): """ Return target path for iCal export. Note ---- If `target_path` does not have one of the extensions `.ical`, `.ics`, `.ifb`, or `.icalendar`, the extension `.ics` is appended to the path. Returns ------- None. Examples -------- >>> from calendra.europe import Austria >>> cal = Austria() >>> cal._get_ical_target_path('austria') 'austria.ics' """ if not target_path: raise ICalExportTargetPathError( "Incorrect target path. It must not be empty") if isdir(target_path): raise ICalExportTargetPathError( "Incorrect target path. It must not be a directory" ) ical_extensions = ['.ical', '.ics', '.ifb', '.icalendar'] if os.path.splitext(target_path)[1] not in ical_extensions: target_path += '.ics' return target_path def export_to_ical(self, period=[2000, 2030], target_path=None): """ Export the calendar to iCal (RFC 5545) format. Parameters ---------- period: [int, int] start and end year (inclusive) of calendar Default is [2000, 2030] target_path: str the name or path of the exported file. If this argument is missing, the function will return the ical content. """ first_year, last_year = self._get_ical_period(period) if target_path: # Generate filename path before calculate the holidays target_path = self._get_ical_target_path(target_path) # fetch holidays holidays = [] for year in range(first_year, last_year + 1): holidays.extend(self.holidays(year)) # initialize icalendar ics = [ 'BEGIN:VCALENDAR', 'VERSION:2.0', # current RFC5545 version f'PRODID:-//workalendar//ical {__version__}//EN' ] common_timestamp = datetime.utcnow().strftime('%Y%m%dT%H%M%SZ') dtstamp = 'DTSTAMP;VALUE=DATE-TIME:%s' % common_timestamp # add an event for each holiday for holiday in holidays: date_ = self.get_observed_date(holiday) ics.extend([ 'BEGIN:VEVENT', 'SUMMARY:%s' % holiday.name, 'DTSTART;VALUE=DATE:%s' % date_.strftime('%Y%m%d'), dtstamp, f'UID:{date_}{holiday.name}@peopledoc.github.io/workalendar', 'END:VEVENT', ]) # add footer ics.append('END:VCALENDAR\n') # last line with a trailing \n # Transform this list into text lines ics = "\n".join(ics) if target_path: # save iCal file with open(target_path, 'w+') as export_file: export_file.write(ics) return return ics
def get_columbus_day(self, year): return Holiday( date(year, 10, 1) + rd.relativedelta(weekday=rd.MO(2)), self.columbus_day_label, indication="2nd Monday in October", )
def get_late_summer_bank_holiday(self, year): return Holiday( date(year, 8, 31) + rd.relativedelta(weekday=rd.MO(-1)), "Late Summer Bank Holiday", indication="Last Monday in August", )
def get_variable_days(self, year): # usual variable days days = super().get_variable_days(year) days += [ self.get_veterans_day(year), self.get_national_memorial_day(year), Holiday( date(year, 9, 1) + rd.relativedelta(weekday=rd.MO(1)), "Labor Day", indication="1st Monday in September", ), Holiday( date(year, 11, 1) + rd.relativedelta(weekday=rd.TH(4)), "Thanksgiving Day", indication="4th Thursday in November", ), ] # Martin Luther King's Day started only in 1985 if year >= 1985: days.append(self.get_martin_luther_king_day(year)) if self.include_mardi_gras: days.append(self.get_mardi_gras(year)) if self.include_federal_presidents_day: days.append(self.get_presidents_day(year)) if self.include_lincoln_birthday: days.append(self.get_lincoln_birthday(year)) if self.include_cesar_chavez_day: days.extend(self.get_cesar_chavez_days(year)) if self.include_patriots_day: days.append(self.get_patriots_day(year)) if self.include_columbus_day: days.append(self.get_columbus_day(year)) if self.include_confederation_day: days.append(self.get_confederate_day(year)) if self.include_jefferson_davis_birthday: days.append(self.get_jefferson_davis_birthday(year)) ind = "January 20 (or 21st if Sunday) following an election year" if self.include_inauguration_day: # Is it a "Inauguration year"? if UnitedStates.is_presidential_year(year - 1): days.append( Holiday( self.get_inauguration_date(year), "Inauguration Day", indication=ind, ), ) if self.include_election_day_every_year: days.append(self.get_election_day(year)) elif self.include_election_day_even: if (year % 2) == 0: days.append(self.get_election_day(year)) if self.include_thanksgiving_friday: days.append( self.get_thanksgiving_friday(year) ) return days
yearday, nlyearday: Set the yearday or the non-leap year day (jump leap days). These are converted to day/month/leapdays information. """ r2 = relativedelta(parse("20200310"), parse("20200201")) print(r2) r3 = parse("20200101") - relativedelta(months=1) print(r3) r4 = parse("20200330") - relativedelta(months=1) #2020-02-29 00:00:00, 30超过2月的日期,会自动这只为最后一天 print(r4) #先用month替换,再减去months r5 = parse("20200330") - relativedelta(months=1, month=5) print(r5) #获取下一个周一 r6 = parse("20200324") + relativedelta(weekday=rd.MO(+1)) r7 = parse("20200324") - relativedelta(weekday=rd.MO(+1)) #与日期是加上还是减去relativedelta没有关系 print(r6, r7) #获取上一个周一 r8 = parse("20200324") + relativedelta(weekday=rd.MO(-1)) print(r8) #day超过,会默认给最后一天;其他的year,month等会报错 r9 = parse("20200323") + relativedelta(day=40) print(r9)