1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
"""ESIOS API handler for HomeAssistant. PVPC tariff periods."""
from __future__ import annotations
from datetime import date, datetime, timedelta
_HOURS_P2 = (8, 9, 14, 15, 16, 17, 22, 23)
_HOURS_P2_CYM = (8, 9, 10, 15, 16, 17, 18, 23)
# TODO review 'festivos nacionales no sustituibles de fecha fija', + 6/1
# obtained from `holidays` library,
# - with weekend days disabled (already full P3)
# - no 'translated' holidays
# - no 'Jueves Santo' as special day
_NATIONAL_EXTRA_HOLIDAYS_FOR_P3_PERIOD = {
2021: {
date(2021, 1, 1): "(viernes), Año nuevo",
date(2021, 1, 6): "(miércoles), Epifanía del Señor",
# date(2021, 4, 1): "(jueves), Jueves Santo",
date(2021, 4, 2): "(viernes), Viernes Santo",
# date(2021, 5, 1): "(sábado), Día del Trabajador",
# date(2021, 8, 15): "(domingo), Asunción de la Virgen",
date(2021, 10, 12): "(martes), Día de la Hispanidad",
date(2021, 11, 1): "(lunes), Todos los Santos",
date(2021, 12, 6): "(lunes), Día de la Constitución Española",
date(2021, 12, 8): "(miércoles), La Inmaculada Concepción",
# date(2021, 12, 25): "(sábado), Navidad",
},
2022: {
# date(2022, 1, 1): "(sábado), Año nuevo",
date(2022, 1, 6): "(jueves), Epifanía del Señor",
date(2022, 4, 15): "(viernes), Viernes Santo",
date(2022, 8, 15): "(lunes), Asunción de la Virgen",
date(2022, 10, 12): "(miércoles), Día de la Hispanidad",
date(2022, 11, 1): "(martes), Todos los Santos",
date(2022, 12, 6): "(martes), Día de la Constitución Española",
date(2022, 12, 8): "(jueves), La Inmaculada Concepción",
# date(2022, 12, 26): "(lunes), Navidad (Trasladado)",
},
2023: {
# date(2023, 1, 1): "(domingo), Año nuevo",
date(2023, 1, 6): "(viernes), Epifanía del Señor",
# date(2023, 4, 6): "(jueves), Jueves Santo",
date(2023, 4, 7): "(viernes), Viernes Santo",
date(2023, 5, 1): "(lunes), Día del Trabajador",
date(2023, 8, 15): "(martes), Asunción de la Virgen",
date(2023, 10, 12): "(jueves), Día de la Hispanidad",
date(2023, 11, 1): "(miércoles), Todos los Santos",
date(2023, 12, 6): "(miércoles), Día de la Constitución Española",
date(2023, 12, 8): "(viernes), La Inmaculada Concepción",
date(2023, 12, 25): "(lunes), Navidad",
},
2024: {
date(2024, 1, 1): "(lunes), Año nuevo",
# date(2024, 1, 6): "(sábado), Epifanía del Señor",
# date(2024, 3, 28): "(jueves), Jueves Santo",
date(2024, 3, 29): "(viernes), Viernes Santo",
date(2024, 5, 1): "(miércoles), Día del Trabajador",
date(2024, 8, 15): "(jueves), Asunción de la Virgen",
# date(2024, 10, 12): "(sábado), Día de la Hispanidad",
date(2024, 11, 1): "(viernes), Todos los Santos",
date(2024, 12, 6): "(viernes), Día de la Constitución Española",
# date(2024, 12, 8): "(domingo), La Inmaculada Concepción",
date(2024, 12, 25): "(miércoles), Navidad",
},
2025: {
date(2025, 1, 1): "(miércoles), Año nuevo",
date(2025, 1, 6): "(lunes), Epifanía del Señor",
# date(2025, 4, 17): "(jueves), Jueves Santo",
date(2025, 4, 18): "(viernes), Viernes Santo",
date(2025, 5, 1): "(jueves), Día del Trabajador",
date(2025, 8, 15): "(viernes), Asunción de la Virgen",
# date(2025, 10, 12): "(domingo), Día de la Hispanidad",
# date(2025, 11, 1): "(sábado), Todos los Santos",
# date(2025, 12, 6): "(sábado), Día de la Constitución Española",
date(2025, 12, 8): "(lunes), La Inmaculada Concepción",
date(2025, 12, 25): "(jueves), Navidad",
},
}
def _tariff_period_key(local_ts: datetime, zone_ceuta_melilla: bool) -> str:
"""Return period key (P1/P2/P3) for current hour."""
day = local_ts.date()
national_holiday = day in _NATIONAL_EXTRA_HOLIDAYS_FOR_P3_PERIOD[day.year]
if national_holiday or day.isoweekday() >= 6 or local_ts.hour < 8:
return "P3"
if zone_ceuta_melilla and local_ts.hour in _HOURS_P2_CYM:
return "P2"
if not zone_ceuta_melilla and local_ts.hour in _HOURS_P2:
return "P2"
return "P1"
def get_current_and_next_tariff_periods(
local_ts: datetime, zone_ceuta_melilla: bool
) -> tuple[str, str, timedelta]:
"""Get tariff periods for PVPC 2.0TD."""
current_period = _tariff_period_key(local_ts, zone_ceuta_melilla)
delta = timedelta(hours=1)
while (
next_period := _tariff_period_key(local_ts + delta, zone_ceuta_melilla)
) == current_period:
delta += timedelta(hours=1)
return current_period, next_period, delta
|