Ejemplo n.º 1
0
 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",
     ),
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
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
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
def mon(a):
    monday = str(today + rdelta.relativedelta(weekday=rdelta.MO(a)))
    output = monday[8:10] + '/' + monday[5:7] + '/' + monday[2:4]
    return output
Ejemplo n.º 9
0
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")
Ejemplo n.º 10
0
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("__"):
Ejemplo n.º 11
0
# 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
Ejemplo n.º 12
0
 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",
     )
Ejemplo n.º 13
0
 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",
     )
Ejemplo n.º 14
0
        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)))
Ejemplo n.º 15
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",
     )
Ejemplo n.º 16
0
 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
Ejemplo n.º 17
0
    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
Ejemplo n.º 19
0
    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")
Ejemplo n.º 20
0
 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",
     )
Ejemplo n.º 21
0
 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))
Ejemplo n.º 22
0
 def next_last_monday():
     now = date.today()
     day = now + relativedelta.relativedelta(month=now.month + 1,
                                             weekday=relativedelta.MO(1))
     return day
Ejemplo n.º 23
0
 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))
Ejemplo n.º 24
0
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
Ejemplo n.º 25
0
 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",
     )
Ejemplo n.º 26
0
 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",
     )
Ejemplo n.º 27
0
    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
Ejemplo n.º 28
0
        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)