Git Product home page Git Product logo

bdew-datetimes's Introduction

bdew_datetimes

GitHub Workflow StatusPyPI - Python VersionPyPI - LicensePyPI

A collection of utils to work with datetimes and holidays in the German energy market and is based on the python-holiday package.

The implementation considers the publications of the BDEW (Bundesverband der Energie- und Wasserwirtschaft e. V.) and EDI@Energy, which provide boundaries and guidance for the data exchange on the german energy market.

Current highlights:

  • BDEW-holiday calendar
    • allows dict like evaluation of dates and datetimes and contains all holidays considered by the BDEW
  • Statutory Periods ("Gesetzliche Fristen")
    • calculate dates of the kind "x Werktage ab Stichtag"
    • calculate dates of the kind "nter Werktag des Fristen- bzw. Liefermonats"
  • Gas-Day / Market Day evaluation

Future Scope:

  • providing subdivision holiday calendars to allow granular load profiles

Quick Start and Examples

Install the package from pypi:

pip install bdew-datetimes

Check if a date is a specific BDEW Holidays

The HolidaySum returned by create_bdew_calendar contains the BDEW specific holidays. This means it contains those holidays which are defined by BDEW which includes Heiligabend and Silvester as well as special days without Marktkommunikation but not the local or nationwide holidays in Germany and its states.

from datetime import date
from bdew_datetimes import create_bdew_calendar

bdew_holidays = create_bdew_calendar()  # this behaves like a dict

assert date(2022, 12, 31) in bdew_holidays # Silvester is a BDEW holiday
assert date(2022, 8, 8) in bdew_holidays is False # Augsburger Friedensfest is _not_ a BDEW holiday (but a holiday in Augsburg only)
assert date(2022, 12, 2) in bdew_holidays is False # The 12th of February is not a BDEW holiday

print(bdew_holidays.get('2022-01-01'))  # prints "Neujahr"

The union (type HolidaySum) of both nation and state wide holidays and the BDEW holidays (only the latter is returned by create_bdew_calendar) is the relevant calendar for German utilities.

Check if a given Date is a BDEW Working Day

BDEW working days are those days taken into account for the "Fristenberechnung". The function is_bdew_working_day considers both national and state wide holidays as well as BDEW holidays:

from datetime import date

from bdew_datetimes.periods import is_bdew_working_day

assert is_bdew_working_day(date(2023, 1, 1)) is False  # Neujahr (national holiday)
assert is_bdew_working_day(date(2023, 1, 2)) is True  # regular weekday
assert is_bdew_working_day(date(2023, 1, 6)) is False  # Heilige Drei Könige (local holiday in parts of Germany)
assert is_bdew_working_day(date(2023, 4, 7)) is False  # Karfreitag (national holiday, but based on an astronomical calendar)
assert is_bdew_working_day(date(2023, 12, 24)) is False  # Heiligabend (BDEW holiday)

You can also get the next or previous working day for any date:

from datetime import date

from bdew_datetimes.periods import get_next_working_day, get_previous_working_day

assert get_next_working_day(date(2023, 1, 1)) == date(2023, 1, 2)  # the next working day after Neujahr
assert get_previous_working_day(date(2023, 1, 1)) == date(2022, 12, 30)  # the last working day of 2022
assert get_next_working_day(date(2023, 1, 20)) == date(2023, 1, 23)  # the next working day after a friday is the next monday

Calculate Statutory Periods

Statutory periods define the maximum time between e.g. the EDIFACT message for the "Anmeldung" and the actual start of supply ("Lieferbeginn").

from datetime import date

from bdew_datetimes.periods import DayType, EndDateType, Period, add_frist

# Eingang der Anmeldung des LFN erfolgt am 04.07.2016. Der Mindestzeitraum von zehn WT
# beginnt am 05.07.2016 und endet am 18.07.2016. Frühestes zulässiges Anmeldedatum
# ist damit der 19.07.2016, sodass die Marktlokation dem LFN frühestens zum Beginn
# des vorgenannten Tages zugeordnet wird.
eingang_der_anmeldung = date(2016, 7, 4)
gesetzliche_frist = Period(
    10,
    DayType.WORKING_DAY,
    end_date_type=EndDateType.EXCLUSIVE
    # lieferbeginn is the exclusive end of the previous supply contract
)
fruehest_moeglicher_lieferbeginn = add_frist(eingang_der_anmeldung, gesetzliche_frist)
assert fruehest_moeglicher_lieferbeginn == date(2016, 7, 19)

Calculate "Liefer- and Fristenmonate"

Liefer- and Fristenmonat are concepts used in MaBiS and GPKE:

from datetime import date

from bdew_datetimes.periods import get_nth_working_day_of_month, MonthType

# returns the 18th working day of the current month in Germany
get_nth_working_day_of_month(18)

# the 18th working day of November 2023
assert get_nth_working_day_of_month(18, start=date(2023, 11, 1)) == date(2023, 11, 28)

# the 42th working day of Fristenmonat July 2023
assert get_nth_working_day_of_month(42, month_type=MonthType.FRISTENMONAT, start=date(2023, 7, 1)) == date(2023, 9, 29)

Notes

The BDEW considers all days as holidays, which are nationwide holidays and days, which are a holiday in at least one state. Furthermore, the 24. and the 31. December are holidays as well. Therefore, this package utilizes the composition of all available german holiday calendars and adds the two additional days.

Shifting holidays to the next weekday if they fall on a weekend is currently not considered.

License

This library is licensed under the MIT license, see the LICENSE file.

Users

This library is used by the following projects:

bdew-datetimes's People

Contributors

mj0nez avatar hf-kklein avatar dependabot[bot] avatar

Stargazers

Florian Kubis avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

hf-kklein

bdew-datetimes's Issues

Is this package published on PyPi already?

Hi @mj0nez,
we'd love to use this library but it seems like it is not available on PyPi?
https://pypi.org/search/?q=+energy-datetime-utils&o=

Do you plan to publish it there? I see two options:

  1. we could either fork it and publish it from our (@Hochfrequenz / unlimitedfox) account
  2. or we could help you setup the deployment pipeline. It's pretty straightforward, once you've done it a few times. Shouldn't take more than 10mins.

Just drop a line what you'd prefer and we're happy to help :)

BTW: If you're publishing it on your own PyPi account I'd suggest to not call it "energy-datetime-utils" but instead be very specific with e.g. "bdewholidays" or something similar. That'd make it obvious to anyone whom it may concern what exactly the thing does while "energy" is quite vague.

Setup.cfg refers to wrong dependency (typo)

python-dateutils

When trying to install this package (v0.3.2) pip dies with the following error message:

ERROR: Could not find a version that satisfies the requirement python-dateutils (from bdew-datetimes) (from versions: none)

The problem is, that the setup.cfg refers to python-dateutils (note the s at the end), but actually it should be python-dateutil as in requirements.in:

python-dateutil

tox: dev env

@hf-kklein, could you help me understand the benefits of this testenv?
I really liked the simplicity of invoking tests, linting, typing and so forth. Therefore, I’ve added the format env to orchestrate isort and black, too. But it seems that with ‘dev’ we just replicate the pip upgrade and installation of all dependencies in another tox-environment.

the dev tox.ini

[testenv:dev]
# the dev environment contains everything you need to start developing on your local machine.
deps =
    {[testenv:tests]deps}
    {[testenv:linting]deps}
    {[testenv:format]deps}
    pip-tools
commands =
    python -m pip install --upgrade pip

packing fails because of metadata change and outdated pkginfo version

A failed CI run:

Run tox -e test_packaging
  tox -e test_packaging
  shell: /usr/bin/bash -e {0}
  env:
    pythonLocation: /opt/hostedtoolcache/Python/3.11.9/x64
    PKG_CONFIG_PATH: /opt/hostedtoolcache/Python/3.11.9/x64/lib/pkgconfig
    Python_ROOT_DIR: /opt/hostedtoolcache/Python/3.11.9/x64
    Python2_ROOT_DIR: /opt/hostedtoolcache/Python/3.11.9/x64
    Python3_ROOT_DIR: /opt/hostedtoolcache/Python/3.11.9/x64
    LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.11.9/x64/lib
test_packaging: install_deps> python -I -m pip install -r dev_requirements/requirements-packaging.txt
test_packaging: freeze> python -m pip freeze --all
test_packaging: bleach==6.0.0,build==1.2.1,certifi==2023.7.22,cffi==1.15.1,charset-normalizer==3.1.0,cryptography==41.0.6,docutils==0.20.1,idna==3.4,importlib-metadata==6.7.0,jaraco.classes==3.2.3,jeepney==0.8.0,keyring==23.13.1,markdown-it-py==3.0.0,mdurl==0.1.2,more-itertools==9.1.0,packaging==23.1,pip==24.0,pkginfo==1.9.6,pycparser==2.21,Pygments==2.15.1,pyproject_hooks==1.0.0,readme-renderer==37.3,requests==2.31.0,requests-toolbelt==1.0.0,rfc3986==2.0.0,rich==13.4.2,SecretStorage==3.3.3,setuptools==69.5.1,six==1.16.0,twine==5.1.0,urllib3==2.0.7,webencodings==0.5.1,wheel==0.43.0,zipp==3.15.0
test_packaging: commands[0]> python -m build
* Creating isolated environment: venv+pip...
* Installing packages in isolated environment:
  - hatch-fancy-pypi-readme
  - hatch-vcs
  - hatchling>=1.8.0
* Getting build dependencies for sdist...
* Building sdist...
/tmp/build-env-d_2jz3yr/lib/python3.11/site-packages/setuptools_scm/git.py:167: UserWarning: "/home/runner/work/bdew-datetimes/bdew-datetimes" is shallow and may cause errors
  warnings.warn(f'"{wd.path}" is shallow and may cause errors')
* Building wheel from sdist
* Creating isolated environment: venv+pip...
* Installing packages in isolated environment:
  - hatch-fancy-pypi-readme
  - hatch-vcs
  - hatchling>=1.8.0
* Getting build dependencies for wheel...
* Building wheel...
Successfully built bdew_datetimes-0.1.dev1+g08179a6.tar.gz and bdew_datetimes-0.1.dev1+g08179a6-py3-none-any.whl
test_packaging: commands[1]> twine check 'dist/*'
Checking dist/bdew_datetimes-0.1.dev1+g08179a6-py3-none-any.whl: ERROR    InvalidDistribution: Metadata is missing required fields: Name,        
         Version.                                                               
         Make sure the distribution includes the files where those fields are   
         specified, and is using a supported Metadata-Version: 1.0, 1.1, 1.2,   
         2.0, 2.1, 2.2.                                                         
test_packaging: exit 1 (0.42 seconds) /home/runner/work/bdew-datetimes/bdew-datetimes> twine check 'dist/*' pid=1837
  test_packaging: FAIL code 1 (11.32=setup[6.78]+cmd[4.12,0.42] seconds)
  evaluation failed :( (11.47 seconds)
Error: Process completed with exit code 1.

Some other issue describing the bug: pypa/twine#1059

CI has redundant triggers

Currently, the workflows get triggered by any activity on a PR or any push. This results in duplicate workflows see:

image

The any-push trigger should be sufficient.

Fix: Release Worklfow - using old build backend

sr/bin/bash -e /home/runner/work/_temp/ddd9e5c2-dd09-46f9-b437-bc069c914f81.sh
python: can't open file '/home/runner/work/bdew-datetimes/bdew-datetimes/setup.py': [Errno 2] No such file or directory
Error: Process completed with exit code 2.
##[debug]Finishing: Build a binary wheel and a source tarball

Action

`py.typed` missing in built package

I have a project where I use bdew-datetimes.

When running mypy on the code base I get an error:

error: Skipping analyzing "bdew_datetimes.periods": module is installed, but missing library stubs or py.typed marker [import]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.