Split UK holiday code into own file
This commit is contained in:
		
							parent
							
								
									74e135e9c3
								
							
						
					
					
						commit
						84ea916747
					
				| 
						 | 
				
			
			@ -1,22 +1,18 @@
 | 
			
		|||
import asyncio
 | 
			
		||||
import configparser
 | 
			
		||||
import json
 | 
			
		||||
import operator
 | 
			
		||||
import os
 | 
			
		||||
import typing
 | 
			
		||||
import warnings
 | 
			
		||||
from datetime import date, datetime, time, timedelta
 | 
			
		||||
from time import time as unixtime
 | 
			
		||||
 | 
			
		||||
import dateutil
 | 
			
		||||
import dateutil.parser
 | 
			
		||||
import dateutil.tz
 | 
			
		||||
import holidays
 | 
			
		||||
import httpx
 | 
			
		||||
import lxml
 | 
			
		||||
import pytz
 | 
			
		||||
import yaml
 | 
			
		||||
from dateutil.easter import easter
 | 
			
		||||
from dateutil.relativedelta import FR, relativedelta
 | 
			
		||||
 | 
			
		||||
from . import (
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +28,7 @@ from . import (
 | 
			
		|||
    sun,
 | 
			
		||||
    thespacedevs,
 | 
			
		||||
    travel,
 | 
			
		||||
    uk_holiday,
 | 
			
		||||
    waste_schedule,
 | 
			
		||||
)
 | 
			
		||||
from .types import Event
 | 
			
		||||
| 
						 | 
				
			
			@ -62,51 +59,6 @@ config.read(config_filename)
 | 
			
		|||
data_dir = config.get("data", "dir")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def next_uk_mothers_day(input_date: date) -> date:
 | 
			
		||||
    """Calculate the date of the next UK Mother's Day from the current date."""
 | 
			
		||||
    current_year = input_date.year
 | 
			
		||||
 | 
			
		||||
    easter_date = easter(current_year)
 | 
			
		||||
 | 
			
		||||
    # Calculate the date of Mother's Day, which is the fourth Sunday of Lent
 | 
			
		||||
    mothers_day = easter_date + timedelta(weeks=3)
 | 
			
		||||
 | 
			
		||||
    # Check if Mother's Day has already passed this year
 | 
			
		||||
    if input_date > mothers_day:
 | 
			
		||||
        # If it has passed, calculate for the next year
 | 
			
		||||
        easter_date = easter(current_year + 1)
 | 
			
		||||
        mothers_day = easter_date + timedelta(weeks=3)
 | 
			
		||||
 | 
			
		||||
    return mothers_day
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def next_uk_fathers_day(input_date: date) -> date:
 | 
			
		||||
    """Calculate the date of the next UK Father's Day from the current date."""
 | 
			
		||||
    # Get the current date
 | 
			
		||||
    # Calculate the day of the week for the current date (0 = Monday, 6 = Sunday)
 | 
			
		||||
    current_day_of_week = input_date.weekday()
 | 
			
		||||
 | 
			
		||||
    # Calculate the number of days until the next Sunday
 | 
			
		||||
    days_until_sunday = (6 - current_day_of_week) % 7
 | 
			
		||||
 | 
			
		||||
    # Calculate the date of the next Sunday
 | 
			
		||||
    next_sunday = input_date + timedelta(days=days_until_sunday)
 | 
			
		||||
 | 
			
		||||
    # Calculate the date of Father's Day, which is the third Sunday of June
 | 
			
		||||
    fathers_day = date(next_sunday.year, 6, 1) + timedelta(
 | 
			
		||||
        weeks=2, days=next_sunday.weekday()
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # Check if Father's Day has already passed this year
 | 
			
		||||
    if input_date > fathers_day:
 | 
			
		||||
        # If it has passed, calculate for the next year
 | 
			
		||||
        fathers_day = date(fathers_day.year + 1, 6, 1) + timedelta(
 | 
			
		||||
            weeks=2, days=next_sunday.weekday()
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    return fathers_day
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def timezone_transition(
 | 
			
		||||
    start_dt: datetime, end_dt: datetime, key: str, tz_name: str
 | 
			
		||||
) -> list[Event]:
 | 
			
		||||
| 
						 | 
				
			
			@ -119,29 +71,6 @@ def timezone_transition(
 | 
			
		|||
    ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def get_next_bank_holiday(start_date: date, end_date: date) -> list[Event]:
 | 
			
		||||
    """Date and name of the next UK bank holiday."""
 | 
			
		||||
    url = "https://www.gov.uk/bank-holidays.json"
 | 
			
		||||
    filename = os.path.join(data_dir, "bank-holidays.json")
 | 
			
		||||
    mtime = os.path.getmtime(filename)
 | 
			
		||||
    if (unixtime() - mtime) > 60 * 60 * 6:  # six hours
 | 
			
		||||
        async with httpx.AsyncClient() as client:
 | 
			
		||||
            r = await client.get(url)
 | 
			
		||||
        open(filename, "w").write(r.text)
 | 
			
		||||
 | 
			
		||||
    events = json.load(open(filename))["england-and-wales"]["events"]
 | 
			
		||||
    hols: list[Event] = []
 | 
			
		||||
    for event in events:
 | 
			
		||||
        event_date = datetime.strptime(event["date"], "%Y-%m-%d").date()
 | 
			
		||||
        if event_date < start_date:
 | 
			
		||||
            continue
 | 
			
		||||
        if event_date > end_date:
 | 
			
		||||
            break
 | 
			
		||||
        hols.append(Event(name="bank_holiday", date=event_date, title=event["title"]))
 | 
			
		||||
 | 
			
		||||
    return hols
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def uk_financial_year_end(input_date: date) -> date:
 | 
			
		||||
    """Next date of the end of the UK financial year, April 5th."""
 | 
			
		||||
    # Determine the year of the input date
 | 
			
		||||
| 
						 | 
				
			
			@ -276,7 +205,7 @@ async def get_data(now: datetime) -> typing.Mapping[str, str | object]:
 | 
			
		|||
    ) = await asyncio.gather(
 | 
			
		||||
        fx.get_gbpusd(config),
 | 
			
		||||
        gwr.advance_ticket_date(data_dir),
 | 
			
		||||
        get_next_bank_holiday(last_year, next_year),
 | 
			
		||||
        uk_holiday.bank_holiday_list(last_year, next_year, data_dir),
 | 
			
		||||
        thespacedevs.get_launches(rocket_dir, limit=40),
 | 
			
		||||
        waste_collection_events(),
 | 
			
		||||
        bristol_waste_collection_events(today),
 | 
			
		||||
| 
						 | 
				
			
			@ -296,8 +225,8 @@ async def get_data(now: datetime) -> typing.Mapping[str, str | object]:
 | 
			
		|||
        "us_clock_change": timezone_transition(
 | 
			
		||||
            minus_365, plus_365, "us_clock_change", "America/New_York"
 | 
			
		||||
        ),
 | 
			
		||||
        "mothers_day": next_uk_mothers_day(today),
 | 
			
		||||
        "fathers_day": next_uk_fathers_day(today),
 | 
			
		||||
        "mothers_day": uk_holiday.get_mothers_day(today),
 | 
			
		||||
        "fathers_day": uk_holiday.get_fathers_day(today),
 | 
			
		||||
        "uk_financial_year_end": uk_financial_year_end(today),
 | 
			
		||||
        "xmas_last_posting_dates": xmas_last_posting_dates,
 | 
			
		||||
        "gwr_advance_tickets": gwr_advance_tickets,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										81
									
								
								agenda/uk_holiday.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								agenda/uk_holiday.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,81 @@
 | 
			
		|||
"""UK holidays."""
 | 
			
		||||
 | 
			
		||||
import json
 | 
			
		||||
import os
 | 
			
		||||
from datetime import date, datetime, timedelta
 | 
			
		||||
from time import time
 | 
			
		||||
 | 
			
		||||
import httpx
 | 
			
		||||
from dateutil.easter import easter
 | 
			
		||||
 | 
			
		||||
from .types import Event
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def bank_holiday_list(
 | 
			
		||||
    start_date: date, end_date: date, data_dir: str
 | 
			
		||||
) -> list[Event]:
 | 
			
		||||
    """Date and name of the next UK bank holiday."""
 | 
			
		||||
    url = "https://www.gov.uk/bank-holidays.json"
 | 
			
		||||
    filename = os.path.join(data_dir, "bank-holidays.json")
 | 
			
		||||
    mtime = os.path.getmtime(filename)
 | 
			
		||||
    if (time() - mtime) > 60 * 60 * 6:  # six hours
 | 
			
		||||
        async with httpx.AsyncClient() as client:
 | 
			
		||||
            r = await client.get(url)
 | 
			
		||||
        open(filename, "w").write(r.text)
 | 
			
		||||
 | 
			
		||||
    events = json.load(open(filename))["england-and-wales"]["events"]
 | 
			
		||||
    hols: list[Event] = []
 | 
			
		||||
    for event in events:
 | 
			
		||||
        event_date = datetime.strptime(event["date"], "%Y-%m-%d").date()
 | 
			
		||||
        if event_date < start_date:
 | 
			
		||||
            continue
 | 
			
		||||
        if event_date > end_date:
 | 
			
		||||
            break
 | 
			
		||||
        hols.append(Event(name="bank_holiday", date=event_date, title=event["title"]))
 | 
			
		||||
 | 
			
		||||
    return hols
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_mothers_day(input_date: date) -> date:
 | 
			
		||||
    """Calculate the date of the next UK Mother's Day from the current date."""
 | 
			
		||||
    current_year = input_date.year
 | 
			
		||||
 | 
			
		||||
    easter_date = easter(current_year)
 | 
			
		||||
 | 
			
		||||
    # Calculate the date of Mother's Day, which is the fourth Sunday of Lent
 | 
			
		||||
    mothers_day = easter_date + timedelta(weeks=3)
 | 
			
		||||
 | 
			
		||||
    # Check if Mother's Day has already passed this year
 | 
			
		||||
    if input_date > mothers_day:
 | 
			
		||||
        # If it has passed, calculate for the next year
 | 
			
		||||
        easter_date = easter(current_year + 1)
 | 
			
		||||
        mothers_day = easter_date + timedelta(weeks=3)
 | 
			
		||||
 | 
			
		||||
    return mothers_day
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_fathers_day(input_date: date) -> date:
 | 
			
		||||
    """Calculate the date of the next UK Father's Day from the current date."""
 | 
			
		||||
    # Get the current date
 | 
			
		||||
    # Calculate the day of the week for the current date (0 = Monday, 6 = Sunday)
 | 
			
		||||
    current_day_of_week = input_date.weekday()
 | 
			
		||||
 | 
			
		||||
    # Calculate the number of days until the next Sunday
 | 
			
		||||
    days_until_sunday = (6 - current_day_of_week) % 7
 | 
			
		||||
 | 
			
		||||
    # Calculate the date of the next Sunday
 | 
			
		||||
    next_sunday = input_date + timedelta(days=days_until_sunday)
 | 
			
		||||
 | 
			
		||||
    # Calculate the date of Father's Day, which is the third Sunday of June
 | 
			
		||||
    fathers_day = date(next_sunday.year, 6, 1) + timedelta(
 | 
			
		||||
        weeks=2, days=next_sunday.weekday()
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # Check if Father's Day has already passed this year
 | 
			
		||||
    if input_date > fathers_day:
 | 
			
		||||
        # If it has passed, calculate for the next year
 | 
			
		||||
        fathers_day = date(fathers_day.year + 1, 6, 1) + timedelta(
 | 
			
		||||
            weeks=2, days=next_sunday.weekday()
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    return fathers_day
 | 
			
		||||
		Loading…
	
		Reference in a new issue