diff --git a/src/bo4e/__init__.py b/src/bo4e/__init__.py index 255977773..c45aebf00 100644 --- a/src/bo4e/__init__.py +++ b/src/bo4e/__init__.py @@ -101,7 +101,6 @@ "Zaehlzeitregister", "Zeitraum", "Zeitreihenwert", - "Zeitspanne", "Zustaendigkeit", "AbgabeArt", "Angebotsstatus", @@ -295,7 +294,6 @@ from .com.zaehlzeitregister import Zaehlzeitregister from .com.zeitraum import Zeitraum from .com.zeitreihenwert import Zeitreihenwert -from .com.zeitspanne import Zeitspanne from .com.zustaendigkeit import Zustaendigkeit # Import Enums diff --git a/src/bo4e/bo/lokationszuordnung.py b/src/bo4e/bo/lokationszuordnung.py index 4e2c08065..7ee433b57 100644 --- a/src/bo4e/bo/lokationszuordnung.py +++ b/src/bo4e/bo/lokationszuordnung.py @@ -16,7 +16,7 @@ from ..bo.netzlokation import Netzlokation from ..bo.steuerbareressource import SteuerbareRessource from ..bo.technischeressource import TechnischeRessource - from ..com.zeitspanne import Zeitspanne + from ..com.zeitraum import Zeitraum @postprocess_docstring @@ -45,8 +45,8 @@ class Lokationszuordnung(Geschaeftsobjekt): """Liste mit referenzierten technischen Ressourcen""" steuerbare_ressourcen: Optional[list["SteuerbareRessource"]] = None """Liste mit referenzierten steuerbaren Ressourcen""" - gueltigkeit: Optional["Zeitspanne"] = None - """Zeitspanne der Gültigkeit""" + gueltigkeit: Optional["Zeitraum"] = None + """Zeitraum der Gültigkeit""" zuordnungstyp: Optional[str] = None """Verknüpfungsrichtung z.B. Malo-Melo [TODO: Eventuell anderer Datentyp]""" lokationsbuendelcode: Optional[str] = None diff --git a/src/bo4e/bo/person.py b/src/bo4e/bo/person.py index 5b69754d6..7bb077a97 100644 --- a/src/bo4e/bo/person.py +++ b/src/bo4e/bo/person.py @@ -3,9 +3,9 @@ and corresponding marshmallow schema for de-/serialization """ +from datetime import date from typing import TYPE_CHECKING, Annotated, Literal, Optional -import pydantic from pydantic import Field from ..enum.typ import Typ @@ -53,7 +53,7 @@ class Person(Geschaeftsobjekt): """Nachname (Familienname) der Person""" kontaktwege: Optional[list["Kontaktweg"]] = None """Kontaktwege der Person""" - geburtsdatum: Optional[pydantic.AwareDatetime] = None + geburtsdatum: Optional[date] = None """Geburtsdatum der Person""" kommentar: Optional[str] = None """Weitere Informationen zur Person""" diff --git a/src/bo4e/com/zeitraum.py b/src/bo4e/com/zeitraum.py index 90325ab44..3495c5157 100644 --- a/src/bo4e/com/zeitraum.py +++ b/src/bo4e/com/zeitraum.py @@ -3,11 +3,9 @@ and corresponding marshmallow schema for de-/serialization """ -from decimal import Decimal +from datetime import date, time from typing import TYPE_CHECKING, Optional -import pydantic - from ..utils import postprocess_docstring from .com import COM @@ -16,8 +14,6 @@ # pylint: disable=too-few-public-methods - - @postprocess_docstring class Zeitraum(COM): """ @@ -36,9 +32,13 @@ class Zeitraum(COM): """ - einheit: Optional["Mengeneinheit"] = None - dauer: Optional[Decimal] = None - startdatum: Optional[pydantic.AwareDatetime] = None - enddatum: Optional[pydantic.AwareDatetime] = None - startzeitpunkt: Optional[pydantic.AwareDatetime] = None - endzeitpunkt: Optional[pydantic.AwareDatetime] = None + startdatum: Optional[date] = None + """Startdatum, inklusiv""" + enddatum: Optional[date] = None + """Enddatum, inklusiv""" + startuhrzeit: Optional[time] = None + """Startuhrzeit, inklusiv mit Zeitzone""" + enduhrzeit: Optional[time] = None + """Enduhrzeit, exklusiv mit Zeitzone""" + dauer: Optional[str] = None + """Dauer in ISO 8601 , example: 'P1DT30H4S', siehe https://datatracker.ietf.org/doc/html/rfc3339 """ diff --git a/src/bo4e/com/zeitreihenwert.py b/src/bo4e/com/zeitreihenwert.py index a4f6f9e91..989ecb86e 100644 --- a/src/bo4e/com/zeitreihenwert.py +++ b/src/bo4e/com/zeitreihenwert.py @@ -10,14 +10,12 @@ from .com import COM if TYPE_CHECKING: - from ..com.zeitspanne import Zeitspanne + from ..com.zeitraum import Zeitraum from ..enum.messwertstatus import Messwertstatus from ..enum.messwertstatuszusatz import Messwertstatuszusatz # pylint: disable=too-few-public-methods - - @postprocess_docstring class Zeitreihenwert(COM): """ @@ -32,12 +30,11 @@ class Zeitreihenwert(COM): """ - zeitspanne: Optional["Zeitspanne"] = None - """Zeitespanne für das Messintervall""" + zeitraum: Optional["Zeitraum"] = None + """Zeitraum für das Messintervall""" wert: Optional[Decimal] = None - """Der in der Zeitspanne gültige Wert.""" + """Der in dem Zeitraum gültige Wert.""" status: Optional["Messwertstatus"] = None """Der Status gibt an, wie der Wert zu interpretieren ist, z.B. in Berechnungen.""" - statuszusatz: Optional["Messwertstatuszusatz"] = None """Eine Zusatzinformation zum Status, beispielsweise ein Grund für einen fehlenden Wert.""" diff --git a/src/bo4e/com/zeitspanne.py b/src/bo4e/com/zeitspanne.py deleted file mode 100644 index 73fc7b047..000000000 --- a/src/bo4e/com/zeitspanne.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -contains the COM Zeitspanne -""" - -from typing import Optional - -import pydantic - -from bo4e.com.com import COM - -from ..utils import postprocess_docstring - - -@postprocess_docstring -class Zeitspanne(COM): - """ - Eine Zeitspanne ist definiert aus Start und/oder Ende. - Der Unterschied zur Menge (die auch zur Abbildung von Zeitmengen genutzt wird) ist, dass konkrete Start- und Endzeitpunkte angegeben werden. - Die Zeitspanne ist aus dem COM Zeitraum hervorgegangen, das in Zeitspanne und Menge aufgeteilt wurde. - - .. raw:: html - - - - .. HINT:: - `Zeitspanne JSON Schema `_ - - """ - - start: Optional[pydantic.AwareDatetime] = None - """inklusiver Beginn""" - ende: Optional[pydantic.AwareDatetime] = None - """exklusives Ende""" diff --git a/tests/test_lokationszuordnung.py b/tests/test_lokationszuordnung.py index f16a7aad7..02a9c18fa 100644 --- a/tests/test_lokationszuordnung.py +++ b/tests/test_lokationszuordnung.py @@ -1,5 +1,4 @@ import pytest -from pydantic import AwareDatetime from bo4e import ( Lokationszuordnung, @@ -8,7 +7,7 @@ Netzlokation, SteuerbareRessource, TechnischeRessource, - Zeitspanne, + Zeitraum, ) from tests.serialization_helper import assert_serialization_roundtrip @@ -24,7 +23,7 @@ class TestLokationszuordnung: netzlokationen=[Netzlokation()], technische_ressourcen=[TechnischeRessource()], steuerbare_ressourcen=[SteuerbareRessource()], - gueltigkeit=Zeitspanne(), + gueltigkeit=Zeitraum(), zuordnungstyp="Zuordnungstyp", lokationsbuendelcode="9992 00000 125 6", ), diff --git a/tests/test_rechnung.py b/tests/test_rechnung.py index 9ad9cd9e9..fc9b0564e 100644 --- a/tests/test_rechnung.py +++ b/tests/test_rechnung.py @@ -40,7 +40,7 @@ class TestRechnung: faelligkeitsdatum=datetime.today().replace(tzinfo=timezone.utc), rechnungstyp=Rechnungstyp.ENDKUNDENRECHNUNG, original_rechnungsnummer="RE-2022-01-21_1701", - rechnungsperiode=Zeitraum(einheit=Mengeneinheit.TAG, dauer=Decimal(21)), + rechnungsperiode=Zeitraum(dauer="P21D"), rechnungsersteller=Geschaeftspartner(), rechnungsempfaenger=Geschaeftspartner(), gesamtnetto=Betrag(wert=Decimal(12.5), waehrung=Waehrungscode.EUR), @@ -91,7 +91,7 @@ class TestRechnung: faelligkeitsdatum=datetime.today().replace(tzinfo=timezone.utc), rechnungstyp=Rechnungstyp.ENDKUNDENRECHNUNG, original_rechnungsnummer="RE-2022-01-21_1701", - rechnungsperiode=Zeitraum(einheit=Mengeneinheit.TAG, dauer=Decimal(21)), + rechnungsperiode=Zeitraum(dauer="P21D"), rechnungsersteller=Geschaeftspartner(), rechnungsempfaenger=Geschaeftspartner(), gesamtnetto=Betrag(wert=Decimal(12.5), waehrung=Waehrungscode.EUR), diff --git a/tests/test_regionalepreisgarantie.py b/tests/test_regionalepreisgarantie.py index 6ac127c54..2344d2ec9 100644 --- a/tests/test_regionalepreisgarantie.py +++ b/tests/test_regionalepreisgarantie.py @@ -1,4 +1,4 @@ -from datetime import datetime, timezone +from datetime import datetime, time import pytest @@ -22,8 +22,10 @@ class TestRegionalePreisgarantie: RegionalePreisgarantie( preisgarantietyp=Preisgarantietyp.NUR_ENERGIEPREIS, zeitliche_gueltigkeit=Zeitraum( - startzeitpunkt=datetime(2011, 2, 5, 16, 43, tzinfo=timezone.utc), - endzeitpunkt=datetime(2021, 7, 30, tzinfo=timezone.utc), + startdatum=datetime(2011, 2, 5), + startuhrzeit=time(16, 43), + enddatum=datetime(2021, 7, 30), + enduhrzeit=time(16, 43), ), regionale_gueltigkeit=RegionaleGueltigkeit( gueltigkeitstyp=Gueltigkeitstyp.NUR_IN, diff --git a/tests/test_vertragskonditionen.py b/tests/test_vertragskonditionen.py index f21f391cc..c3904a5ff 100644 --- a/tests/test_vertragskonditionen.py +++ b/tests/test_vertragskonditionen.py @@ -19,9 +19,9 @@ class TestVertragskonditionen: startdatum=datetime(2012, 9, 21, tzinfo=timezone.utc), enddatum=datetime(2013, 10, 11, tzinfo=timezone.utc), ), - kuendigungsfrist=Zeitraum(einheit=Mengeneinheit.WOCHE, dauer=Decimal(3)), - vertragsverlaengerung=Zeitraum(einheit=Mengeneinheit.TAG, dauer=Decimal(14)), - abschlagszyklus=Zeitraum(einheit=Mengeneinheit.TAG, dauer=Decimal(5)), + kuendigungsfrist=Zeitraum(dauer="P3W"), + vertragsverlaengerung=Zeitraum(dauer="P14D"), + abschlagszyklus=Zeitraum(dauer="P5D"), ), ), pytest.param( diff --git a/tests/test_zeitraum.py b/tests/test_zeitraum.py index 88f9c817e..7b6645231 100644 --- a/tests/test_zeitraum.py +++ b/tests/test_zeitraum.py @@ -1,8 +1,8 @@ -from decimal import Decimal +from datetime import date, time, timedelta, timezone import pytest -from bo4e import Mengeneinheit, Zeitraum +from bo4e import Zeitraum from tests.serialization_helper import assert_serialization_roundtrip @@ -12,9 +12,37 @@ class TestZeitraum: [ pytest.param( Zeitraum( - einheit=Mengeneinheit.TAG, - dauer=Decimal(21), + dauer="P1DT30H4S", ), + id="period-P1DT30H4S", + ), + pytest.param( + Zeitraum( + startdatum=date(2025, 1, 1), + enddatum=date(2025, 1, 31), + ), + id="startdatum-enddatum", + ), + pytest.param( + Zeitraum( + startuhrzeit=time(10, 0, 0), + enduhrzeit=time(11, 0, 0), + ), + id="startuhrzeit-enduhrzeit", + ), + pytest.param( + Zeitraum( + startuhrzeit=time(10, 0, 0, tzinfo=timezone.utc), + enduhrzeit=time(11, 0, 0, tzinfo=timezone.utc), + ), + id="startuhrzeit-enduhrzeit-utc-timezone", + ), + pytest.param( + Zeitraum( + startuhrzeit=time(18, 0, 0, tzinfo=timezone(timedelta(hours=1), "Europe/Berlin")), + enduhrzeit=time(19, 0, 0, tzinfo=timezone(timedelta(hours=1), "Europe/Berlin")), + ), + id="startuhrzeit-enduhrzeit-berlin-timezone", ), ], ) diff --git a/tests/test_zeitreihenwert.py b/tests/test_zeitreihenwert.py index 924844181..80f27530f 100644 --- a/tests/test_zeitreihenwert.py +++ b/tests/test_zeitreihenwert.py @@ -1,9 +1,9 @@ -from datetime import datetime, timezone +from datetime import datetime from decimal import Decimal import pytest -from bo4e import Messwertstatus, Messwertstatuszusatz, Zeitreihenwert, Zeitspanne +from bo4e import Messwertstatus, Messwertstatuszusatz, Zeitraum, Zeitreihenwert from tests.serialization_helper import assert_serialization_roundtrip @@ -13,9 +13,7 @@ class TestZeitreihenwert: [ pytest.param( Zeitreihenwert( - zeitspanne=Zeitspanne( - start=datetime(2013, 5, 1, tzinfo=timezone.utc), ende=datetime(2022, 1, 28, tzinfo=timezone.utc) - ), + zeitraum=Zeitraum(startdatum=datetime(2013, 5, 1), enddatum=datetime(2022, 1, 28)), wert=Decimal(2.5), status=Messwertstatus.ABGELESEN, statuszusatz=Messwertstatuszusatz.Z78_GERAETEWECHSEL, diff --git a/tests/test_zeitspanne.py b/tests/test_zeitspanne.py deleted file mode 100644 index 51f9c9744..000000000 --- a/tests/test_zeitspanne.py +++ /dev/null @@ -1,21 +0,0 @@ -from datetime import datetime, timezone - -from bo4e.com.zeitspanne import Zeitspanne - - -class TestZeitspanne: - def test_zeitspanne(self) -> None: - """ - Test de-/serialisation of Zeitspanne - """ - zeitspanne = Zeitspanne( - start=datetime(2013, 5, 1, tzinfo=timezone.utc), ende=datetime(2022, 1, 28, tzinfo=timezone.utc) - ) - - json_string = zeitspanne.model_dump_json(by_alias=True) - - assert "2013-05-01T00:00:00Z" in json_string - assert "2022-01-28T00:00:00Z" in json_string - - zeitspanne_deserialized = Zeitspanne.model_validate_json(json_string) - assert zeitspanne_deserialized == zeitspanne