Python 3.10 is the minimum supported version. Code cleanup.
This commit is contained in:
parent
c31d676a4f
commit
344a7cbae4
8 changed files with 123 additions and 137 deletions
|
@ -7,7 +7,7 @@ readme = "README.md"
|
||||||
packages = [{include = "dnidatetime", from = "src"}]
|
packages = [{include = "dnidatetime", from = "src"}]
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.11"
|
python = ">=3.10"
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
pylint = "^3.1.0"
|
pylint = "^3.1.0"
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from typing import Tuple, TypedDict
|
from typing import TypedDict
|
||||||
|
|
||||||
|
|
||||||
#: Type alias for a seven-integer tuple used in a datetime timestamp.
|
#: Type alias for a seven-integer tuple used in a datetime timestamp.
|
||||||
DniDateTimeTuple = Tuple[int, int, int, int, int, int, int]
|
DniDateTimeTuple = tuple[int, int, int, int, int, int, int]
|
||||||
|
|
||||||
|
|
||||||
class DniUnitType(TypedDict):
|
class DniUnitType(TypedDict):
|
||||||
|
@ -64,34 +63,34 @@ DNI_EPOCH_HAHR = 9647
|
||||||
#: delta_ms_1900_to_1970 = -2208988800000
|
#: delta_ms_1900_to_1970 = -2208988800000
|
||||||
#: leap_ms = leap_sec_from_ietf * 1000 + delta_ms_1900_to_1970
|
#: leap_ms = leap_sec_from_ietf * 1000 + delta_ms_1900_to_1970
|
||||||
LEAP_MS_FROM_EPOCH = [
|
LEAP_MS_FROM_EPOCH = [
|
||||||
63072000000, # 1 Jan 1972
|
63072000000, # 1 Jan 1972
|
||||||
78796800000, # 1 Jul 1972
|
78796800000, # 1 Jul 1972
|
||||||
94694400000, # 1 Jan 1973
|
94694400000, # 1 Jan 1973
|
||||||
126230400000, # 1 Jan 1974
|
126230400000, # 1 Jan 1974
|
||||||
157766400000, # 1 Jan 1975
|
157766400000, # 1 Jan 1975
|
||||||
189302400000, # 1 Jan 1976
|
189302400000, # 1 Jan 1976
|
||||||
220924800000, # 1 Jan 1977
|
220924800000, # 1 Jan 1977
|
||||||
252460800000, # 1 Jan 1978
|
252460800000, # 1 Jan 1978
|
||||||
283996800000, # 1 Jan 1979
|
283996800000, # 1 Jan 1979
|
||||||
315532800000, # 1 Jan 1980
|
315532800000, # 1 Jan 1980
|
||||||
362793600000, # 1 Jul 1981
|
362793600000, # 1 Jul 1981
|
||||||
394329600000, # 1 Jul 1982
|
394329600000, # 1 Jul 1982
|
||||||
425865600000, # 1 Jul 1983
|
425865600000, # 1 Jul 1983
|
||||||
489024000000, # 1 Jul 1985
|
489024000000, # 1 Jul 1985
|
||||||
567993600000, # 1 Jan 1988
|
567993600000, # 1 Jan 1988
|
||||||
631152000000, # 1 Jan 1990
|
631152000000, # 1 Jan 1990
|
||||||
662688000000, # 1 Jan 1991
|
662688000000, # 1 Jan 1991
|
||||||
709948800000, # 1 Jul 1992
|
709948800000, # 1 Jul 1992
|
||||||
741484800000, # 1 Jul 1993
|
741484800000, # 1 Jul 1993
|
||||||
773020800000, # 1 Jul 1994
|
773020800000, # 1 Jul 1994
|
||||||
820454400000, # 1 Jan 1996
|
820454400000, # 1 Jan 1996
|
||||||
867715200000, # 1 Jul 1997
|
867715200000, # 1 Jul 1997
|
||||||
915148800000, # 1 Jan 1999
|
915148800000, # 1 Jan 1999
|
||||||
1136073600000, # 1 Jan 2006
|
1136073600000, # 1 Jan 2006
|
||||||
1230768000000, # 1 Jan 2009
|
1230768000000, # 1 Jan 2009
|
||||||
1341100800000, # 1 Jul 2012
|
1341100800000, # 1 Jul 2012
|
||||||
1435708800000, # 1 Jul 2015
|
1435708800000, # 1 Jul 2015
|
||||||
1483228800000, # 1 Jan 2017
|
1483228800000, # 1 Jan 2017
|
||||||
]
|
]
|
||||||
|
|
||||||
#: A carry-over from the Python datetime module for timedelta objects. Might
|
#: A carry-over from the Python datetime module for timedelta objects. Might
|
||||||
|
|
|
@ -2,10 +2,8 @@
|
||||||
|
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from math import floor
|
from math import floor
|
||||||
from typing import Dict, Optional, Tuple
|
|
||||||
|
|
||||||
from .constants import (
|
from .constants import (
|
||||||
DniDateTimeTuple,
|
|
||||||
DNI_EPOCH_EDT,
|
DNI_EPOCH_EDT,
|
||||||
DNI_EPOCH_HAHR,
|
DNI_EPOCH_HAHR,
|
||||||
DNI_UNITS,
|
DNI_UNITS,
|
||||||
|
@ -13,17 +11,16 @@ from .constants import (
|
||||||
MIN_DNI_ORDINAL,
|
MIN_DNI_ORDINAL,
|
||||||
MS_PER_HAHR,
|
MS_PER_HAHR,
|
||||||
MS_PER_PRORAHN,
|
MS_PER_PRORAHN,
|
||||||
YAHRTEE_BEFORE_VAILEE
|
YAHRTEE_BEFORE_VAILEE,
|
||||||
|
DniDateTimeTuple,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .utils import (
|
from .utils import (
|
||||||
check_dni_date_fields,
|
check_dni_date_fields,
|
||||||
get_adj_ms_from_epoch,
|
get_adj_ms_from_epoch,
|
||||||
get_ms_from_epoch,
|
get_ms_from_epoch,
|
||||||
is_timezone_aware
|
is_timezone_aware,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Number of yahrtee (days) in a hahr (year) == 290.
|
# Number of yahrtee (days) in a hahr (year) == 290.
|
||||||
_YAHR_IN_HAHR = DNI_UNITS["yahr"]["max"] * DNI_UNITS["vailee"]["max"]
|
_YAHR_IN_HAHR = DNI_UNITS["yahr"]["max"] * DNI_UNITS["vailee"]["max"]
|
||||||
|
|
||||||
|
@ -35,7 +32,7 @@ def hvy2ord(hahr: int, vailee: int, yahr: int) -> int:
|
||||||
return yahr_before_hahr + YAHRTEE_BEFORE_VAILEE[ok_vailee] + ok_yahr
|
return yahr_before_hahr + YAHRTEE_BEFORE_VAILEE[ok_vailee] + ok_yahr
|
||||||
|
|
||||||
|
|
||||||
def ord2hvy(ordinal: int) -> Tuple[int, int, int]:
|
def ord2hvy(ordinal: int) -> tuple[int, int, int]:
|
||||||
"""Find the exact hahr, vailee, and yahr from an ordinal value of
|
"""Find the exact hahr, vailee, and yahr from an ordinal value of
|
||||||
yahrtee.
|
yahrtee.
|
||||||
"""
|
"""
|
||||||
|
@ -53,19 +50,14 @@ def ord2hvy(ordinal: int) -> Tuple[int, int, int]:
|
||||||
vailee = DNI_UNITS["vailee"]["max"]
|
vailee = DNI_UNITS["vailee"]["max"]
|
||||||
yahr = DNI_UNITS["yahr"]["max"]
|
yahr = DNI_UNITS["yahr"]["max"]
|
||||||
else:
|
else:
|
||||||
vailee, yahr = divmod(
|
vailee, yahr = divmod(rem + DNI_UNITS["yahr"]["max"], DNI_UNITS["yahr"]["max"])
|
||||||
rem + DNI_UNITS["yahr"]["max"],
|
|
||||||
DNI_UNITS["yahr"]["max"]
|
|
||||||
)
|
|
||||||
if yahr == 0:
|
if yahr == 0:
|
||||||
vailee -= 1
|
vailee -= 1
|
||||||
yahr = DNI_UNITS["yahr"]["max"]
|
yahr = DNI_UNITS["yahr"]["max"]
|
||||||
return hahr, vailee, yahr
|
return hahr, vailee, yahr
|
||||||
|
|
||||||
|
|
||||||
def earth_to_dni(
|
def earth_to_dni(date_time: datetime | None = None) -> DniDateTimeTuple:
|
||||||
date_time: Optional[datetime] = None
|
|
||||||
) -> DniDateTimeTuple:
|
|
||||||
"""Converts an Earth gregorian datetime to a D'Ni datetime."""
|
"""Converts an Earth gregorian datetime to a D'Ni datetime."""
|
||||||
if date_time is None:
|
if date_time is None:
|
||||||
moment = datetime.now(timezone.utc)
|
moment = datetime.now(timezone.utc)
|
||||||
|
@ -75,7 +67,7 @@ def earth_to_dni(
|
||||||
else:
|
else:
|
||||||
raise ValueError("Supplied datetime must be timezone aware.")
|
raise ValueError("Supplied datetime must be timezone aware.")
|
||||||
|
|
||||||
dni_dt: Dict[str, int] = {}
|
dni_dt: dict[str, int] = {}
|
||||||
|
|
||||||
stamp = get_adj_ms_from_epoch(moment)
|
stamp = get_adj_ms_from_epoch(moment)
|
||||||
dni_epoch = get_adj_ms_from_epoch(DNI_EPOCH_EDT)
|
dni_epoch = get_adj_ms_from_epoch(DNI_EPOCH_EDT)
|
||||||
|
@ -125,13 +117,13 @@ def dni_to_earth(dni_date_time: DniDateTimeTuple) -> datetime:
|
||||||
"D'Ni datetime must be in the form of a timetuple. "
|
"D'Ni datetime must be in the form of a timetuple. "
|
||||||
"See DniDateTime.timetuple()."
|
"See DniDateTime.timetuple()."
|
||||||
),
|
),
|
||||||
dni_date_time
|
dni_date_time,
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(dni_date_time) != 7:
|
if len(dni_date_time) != 7:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"The D'Ni timetuple is malformed. See DniDateTime.timetuple().",
|
"The D'Ni timetuple is malformed. See DniDateTime.timetuple().",
|
||||||
dni_date_time
|
dni_date_time,
|
||||||
)
|
)
|
||||||
|
|
||||||
temp_units = list(dni_date_time)
|
temp_units = list(dni_date_time)
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
"""The DniDate class."""
|
"""The DniDate class."""
|
||||||
|
|
||||||
from typing import Any, Optional, TYPE_CHECKING, Union
|
from __future__ import annotations
|
||||||
|
|
||||||
from .constants import DniDateTimeTuple, DNI_UNITS, MAX_DNI_ORDINAL
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
|
from .constants import DNI_UNITS, MAX_DNI_ORDINAL, DniDateTimeTuple
|
||||||
from .conversions import hvy2ord, ord2hvy
|
from .conversions import hvy2ord, ord2hvy
|
||||||
from .dnitimedelta import DniTimedelta
|
from .dnitimedelta import DniTimedelta
|
||||||
from .utils import check_dni_date_fields, cmp
|
from .utils import check_dni_date_fields, cmp
|
||||||
|
@ -19,8 +21,8 @@ class DniDate:
|
||||||
_yahr: int
|
_yahr: int
|
||||||
|
|
||||||
# Class properties
|
# Class properties
|
||||||
min: "DniDate"
|
min: DniDate
|
||||||
max: "DniDate"
|
max: DniDate
|
||||||
resolution: DniTimedelta
|
resolution: DniTimedelta
|
||||||
|
|
||||||
def __new__(
|
def __new__(
|
||||||
|
@ -28,7 +30,7 @@ class DniDate:
|
||||||
hahr: int = DNI_UNITS["hahr"]["min"],
|
hahr: int = DNI_UNITS["hahr"]["min"],
|
||||||
vailee: int = DNI_UNITS["vailee"]["min"],
|
vailee: int = DNI_UNITS["vailee"]["min"],
|
||||||
yahr: int = DNI_UNITS["yahr"]["min"],
|
yahr: int = DNI_UNITS["yahr"]["min"],
|
||||||
) -> "DniDate":
|
) -> DniDate:
|
||||||
if isinstance(hahr, int):
|
if isinstance(hahr, int):
|
||||||
hahr, vailee, yahr = check_dni_date_fields(hahr, vailee, yahr)
|
hahr, vailee, yahr = check_dni_date_fields(hahr, vailee, yahr)
|
||||||
self = object.__new__(cls)
|
self = object.__new__(cls)
|
||||||
|
@ -39,7 +41,7 @@ class DniDate:
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dnitimestamp(cls, prorahntee: int) -> "DniDate":
|
def from_dnitimestamp(cls, prorahntee: int) -> DniDate:
|
||||||
"""Construct a D'Ni date from a D'Ni timestamp."""
|
"""Construct a D'Ni date from a D'Ni timestamp."""
|
||||||
yahrtee = prorahntee // DNI_UNITS["yahr"]["total_pro"]
|
yahrtee = prorahntee // DNI_UNITS["yahr"]["total_pro"]
|
||||||
return cls.from_ordinal(yahrtee)
|
return cls.from_ordinal(yahrtee)
|
||||||
|
@ -50,7 +52,7 @@ class DniDate:
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_isoformat(cls, date_str: str) -> "DniDate":
|
def from_isoformat(cls, date_str: str) -> DniDate:
|
||||||
if not isinstance(date_str, str):
|
if not isinstance(date_str, str):
|
||||||
raise TypeError("from_isoformat: argument must be str.")
|
raise TypeError("from_isoformat: argument must be str.")
|
||||||
|
|
||||||
|
@ -64,7 +66,7 @@ class DniDate:
|
||||||
raise ValueError(f"Invalid isoformat string: {date_str!r}") from exc
|
raise ValueError(f"Invalid isoformat string: {date_str!r}") from exc
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_ordinal(cls, yahrtee: int) -> "DniDate":
|
def from_ordinal(cls, yahrtee: int) -> DniDate:
|
||||||
"""Construct a D'ni date from a D'ni ordinal."""
|
"""Construct a D'ni date from a D'ni ordinal."""
|
||||||
hahr, vailee, yahr = ord2hvy(yahrtee)
|
hahr, vailee, yahr = ord2hvy(yahrtee)
|
||||||
return cls(hahr, vailee, yahr)
|
return cls(hahr, vailee, yahr)
|
||||||
|
@ -105,10 +107,10 @@ class DniDate:
|
||||||
|
|
||||||
def replace(
|
def replace(
|
||||||
self,
|
self,
|
||||||
hahr: Optional[int] = None,
|
hahr: int | None = None,
|
||||||
vailee: Optional[int] = None,
|
vailee: int | None = None,
|
||||||
yahr: Optional[int] = None,
|
yahr: int | None = None,
|
||||||
) -> "DniDate":
|
) -> DniDate:
|
||||||
"""Return a new D'ni date with new values for the specified fields."""
|
"""Return a new D'ni date with new values for the specified fields."""
|
||||||
if hahr is None:
|
if hahr is None:
|
||||||
hahr = self._hahr
|
hahr = self._hahr
|
||||||
|
@ -119,7 +121,7 @@ class DniDate:
|
||||||
return type(self)(hahr, vailee, yahr)
|
return type(self)(hahr, vailee, yahr)
|
||||||
|
|
||||||
# Arithmetic
|
# Arithmetic
|
||||||
def __add__(self, other: Any) -> "DniDate":
|
def __add__(self, other: Any) -> DniDate:
|
||||||
if isinstance(other, DniTimedelta):
|
if isinstance(other, DniTimedelta):
|
||||||
ordinal = self.to_ordinal() + other._yahrtee
|
ordinal = self.to_ordinal() + other._yahrtee
|
||||||
if 0 < ordinal <= MAX_DNI_ORDINAL:
|
if 0 < ordinal <= MAX_DNI_ORDINAL:
|
||||||
|
@ -129,7 +131,7 @@ class DniDate:
|
||||||
|
|
||||||
__radd__ = __add__
|
__radd__ = __add__
|
||||||
|
|
||||||
def __sub__(self, other: Any) -> Union["DniDate", DniTimedelta]:
|
def __sub__(self, other: Any) -> DniDate | DniTimedelta:
|
||||||
if isinstance(other, DniTimedelta):
|
if isinstance(other, DniTimedelta):
|
||||||
return self + DniTimedelta(-other._yahrtee)
|
return self + DniTimedelta(-other._yahrtee)
|
||||||
if isinstance(other, DniDate):
|
if isinstance(other, DniDate):
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
"""The DniDatetime class."""
|
"""The DniDatetime class."""
|
||||||
|
|
||||||
from datetime import datetime, timedelta, timezone
|
from __future__ import annotations
|
||||||
from typing import Any, Optional, TYPE_CHECKING, Union
|
|
||||||
|
|
||||||
from .constants import (
|
from datetime import datetime, timedelta, timezone
|
||||||
DniDateTimeTuple,
|
from typing import TYPE_CHECKING, Any
|
||||||
DNI_EPOCH_HAHR,
|
|
||||||
DNI_UNITS,
|
from .constants import DNI_EPOCH_HAHR, DNI_UNITS, MAX_DNI_ORDINAL, DniDateTimeTuple
|
||||||
MAX_DNI_ORDINAL
|
|
||||||
)
|
|
||||||
from .conversions import dni_to_earth, earth_to_dni, hvy2ord
|
from .conversions import dni_to_earth, earth_to_dni, hvy2ord
|
||||||
from .dnidate import DniDate
|
from .dnidate import DniDate
|
||||||
from .dnitime import DniTime
|
from .dnitime import DniTime
|
||||||
|
@ -31,8 +28,8 @@ class DniDatetime:
|
||||||
_prorahn: int
|
_prorahn: int
|
||||||
|
|
||||||
# Class properties
|
# Class properties
|
||||||
min: "DniDatetime"
|
min: DniDatetime
|
||||||
max: "DniDatetime"
|
max: DniDatetime
|
||||||
resolution: DniTimedelta
|
resolution: DniTimedelta
|
||||||
|
|
||||||
def __new__(
|
def __new__(
|
||||||
|
@ -44,7 +41,7 @@ class DniDatetime:
|
||||||
tahvo: int = DNI_UNITS["tahvo"]["min"],
|
tahvo: int = DNI_UNITS["tahvo"]["min"],
|
||||||
gorahn: int = DNI_UNITS["gorahn"]["min"],
|
gorahn: int = DNI_UNITS["gorahn"]["min"],
|
||||||
prorahn: int = DNI_UNITS["prorahn"]["min"],
|
prorahn: int = DNI_UNITS["prorahn"]["min"],
|
||||||
) -> "DniDatetime":
|
) -> DniDatetime:
|
||||||
if isinstance(hahr, int):
|
if isinstance(hahr, int):
|
||||||
hahr, vailee, yahr = check_dni_date_fields(hahr, vailee, yahr)
|
hahr, vailee, yahr = check_dni_date_fields(hahr, vailee, yahr)
|
||||||
gahrtahvo, tahvo, gorahn, prorahn = check_dni_time_fields(
|
gahrtahvo, tahvo, gorahn, prorahn = check_dni_time_fields(
|
||||||
|
@ -121,13 +118,13 @@ class DniDatetime:
|
||||||
|
|
||||||
def replace(
|
def replace(
|
||||||
self,
|
self,
|
||||||
hahr: Optional[int] = None,
|
hahr: int | None = None,
|
||||||
vailee: Optional[int] = None,
|
vailee: int | None = None,
|
||||||
yahr: Optional[int] = None,
|
yahr: int | None = None,
|
||||||
gahrtahvo: Optional[int] = None,
|
gahrtahvo: int | None = None,
|
||||||
tahvo: Optional[int] = None,
|
tahvo: int | None = None,
|
||||||
gorahn: Optional[int] = None,
|
gorahn: int | None = None,
|
||||||
prorahn: Optional[int] = None,
|
prorahn: int | None = None,
|
||||||
) -> "DniDatetime":
|
) -> "DniDatetime":
|
||||||
"""Return a new D'ni datetime with new values for the specified fields."""
|
"""Return a new D'ni datetime with new values for the specified fields."""
|
||||||
if hahr is None:
|
if hahr is None:
|
||||||
|
@ -147,7 +144,7 @@ class DniDatetime:
|
||||||
return type(self)(hahr, vailee, yahr, gahrtahvo, tahvo, gorahn, prorahn)
|
return type(self)(hahr, vailee, yahr, gahrtahvo, tahvo, gorahn, prorahn)
|
||||||
|
|
||||||
# Arithmetic
|
# Arithmetic
|
||||||
def __add__(self, other: Any) -> "DniDatetime":
|
def __add__(self, other: Any) -> DniDatetime:
|
||||||
if not isinstance(other, (timedelta, DniTimedelta)):
|
if not isinstance(other, (timedelta, DniTimedelta)):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
if isinstance(other, timedelta):
|
if isinstance(other, timedelta):
|
||||||
|
@ -173,7 +170,7 @@ class DniDatetime:
|
||||||
|
|
||||||
__radd__ = __add__
|
__radd__ = __add__
|
||||||
|
|
||||||
def __sub__(self, other: Any) -> Union["DniDatetime", DniTimedelta]:
|
def __sub__(self, other: Any) -> DniDatetime | DniTimedelta:
|
||||||
if not isinstance(other, DniDatetime):
|
if not isinstance(other, DniDatetime):
|
||||||
if isinstance(other, timedelta):
|
if isinstance(other, timedelta):
|
||||||
return self + -other
|
return self + -other
|
||||||
|
@ -266,7 +263,7 @@ class DniDatetime:
|
||||||
|
|
||||||
def timestamp(self) -> int:
|
def timestamp(self) -> int:
|
||||||
"""Return total number of prorahntee since the D'ni epoch."""
|
"""Return total number of prorahntee since the D'ni epoch."""
|
||||||
return (self - DNI_EPOCH_DDT).total_prorahntee() #type: ignore
|
return (self - DNI_EPOCH_DDT).total_prorahntee() # type: ignore
|
||||||
|
|
||||||
def timetuple(self) -> DniDateTimeTuple:
|
def timetuple(self) -> DniDateTimeTuple:
|
||||||
"""Return the DniDateTime in the form of a timetuple."""
|
"""Return the DniDateTime in the form of a timetuple."""
|
||||||
|
@ -277,7 +274,7 @@ class DniDatetime:
|
||||||
self._gahrtahvo,
|
self._gahrtahvo,
|
||||||
self._tahvo,
|
self._tahvo,
|
||||||
self._gorahn,
|
self._gorahn,
|
||||||
self._prorahn
|
self._prorahn,
|
||||||
)
|
)
|
||||||
|
|
||||||
def to_ordinal(self) -> int:
|
def to_ordinal(self) -> int:
|
||||||
|
@ -285,7 +282,7 @@ class DniDatetime:
|
||||||
return hvy2ord(self._hahr, self._vailee, self._yahr)
|
return hvy2ord(self._hahr, self._vailee, self._yahr)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def combine(cls, date_obj: DniDate, time_obj: DniTime) -> "DniDatetime":
|
def combine(cls, date_obj: DniDate, time_obj: DniTime) -> DniDatetime:
|
||||||
"""Construct a D'ni datetime from a given DniDate and DniTime."""
|
"""Construct a D'ni datetime from a given DniDate and DniTime."""
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
if not isinstance(date_obj, DniDate):
|
if not isinstance(date_obj, DniDate):
|
||||||
|
@ -302,12 +299,12 @@ class DniDatetime:
|
||||||
time_obj._prorahn,
|
time_obj._prorahn,
|
||||||
)
|
)
|
||||||
|
|
||||||
def to_earth(self, tz: Optional[timezone] = timezone.utc) -> datetime:
|
def to_earth(self, tz: timezone | None = timezone.utc) -> datetime:
|
||||||
"""Create an earth datetime from a DniDatetime."""
|
"""Create an earth datetime from a DniDatetime."""
|
||||||
return dni_to_earth(self.timetuple()).astimezone(tz)
|
return dni_to_earth(self.timetuple()).astimezone(tz)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_earth(cls, date_time: datetime) -> "DniDatetime":
|
def from_earth(cls, date_time: datetime) -> DniDatetime:
|
||||||
"""Create a DniDatetime from an earth datetime."""
|
"""Create a DniDatetime from an earth datetime."""
|
||||||
ddt = earth_to_dni(date_time)
|
ddt = earth_to_dni(date_time)
|
||||||
return cls(*ddt)
|
return cls(*ddt)
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
"""The DniTime class."""
|
"""The DniTime class."""
|
||||||
|
|
||||||
from typing import Any, Optional, TYPE_CHECKING
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
from .constants import DNI_UNITS
|
from .constants import DNI_UNITS
|
||||||
from .dnitimedelta import DniTimedelta
|
from .dnitimedelta import DniTimedelta
|
||||||
|
@ -19,8 +21,8 @@ class DniTime:
|
||||||
_prorahn: int
|
_prorahn: int
|
||||||
|
|
||||||
# Class properties
|
# Class properties
|
||||||
min: "DniTime"
|
min: DniTime
|
||||||
max: "DniTime"
|
max: DniTime
|
||||||
resolution: DniTimedelta
|
resolution: DniTimedelta
|
||||||
|
|
||||||
def __new__(
|
def __new__(
|
||||||
|
@ -29,7 +31,7 @@ class DniTime:
|
||||||
tahvo: int = DNI_UNITS["tahvo"]["min"],
|
tahvo: int = DNI_UNITS["tahvo"]["min"],
|
||||||
gorahn: int = DNI_UNITS["gorahn"]["min"],
|
gorahn: int = DNI_UNITS["gorahn"]["min"],
|
||||||
prorahn: int = DNI_UNITS["prorahn"]["min"],
|
prorahn: int = DNI_UNITS["prorahn"]["min"],
|
||||||
) -> "DniTime":
|
) -> DniTime:
|
||||||
gahrtahvo, tahvo, gorahn, prorahn = check_dni_time_fields(
|
gahrtahvo, tahvo, gorahn, prorahn = check_dni_time_fields(
|
||||||
gahrtahvo, tahvo, gorahn, prorahn
|
gahrtahvo, tahvo, gorahn, prorahn
|
||||||
)
|
)
|
||||||
|
@ -41,7 +43,7 @@ class DniTime:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_isoformat(cls, time_str: str) -> "DniTime":
|
def from_isoformat(cls, time_str: str) -> DniTime:
|
||||||
if not isinstance(time_str, str):
|
if not isinstance(time_str, str):
|
||||||
raise TypeError("from_isoformat: argument must be str.")
|
raise TypeError("from_isoformat: argument must be str.")
|
||||||
|
|
||||||
|
@ -95,11 +97,11 @@ class DniTime:
|
||||||
|
|
||||||
def replace(
|
def replace(
|
||||||
self,
|
self,
|
||||||
gahrtahvo: Optional[int] = None,
|
gahrtahvo: int | None = None,
|
||||||
tahvo: Optional[int] = None,
|
tahvo: int | None = None,
|
||||||
gorahn: Optional[int] = None,
|
gorahn: int | None = None,
|
||||||
prorahn: Optional[int] = None,
|
prorahn: int | None = None,
|
||||||
) -> "DniTime":
|
) -> DniTime:
|
||||||
"""Return a new D'ni time with new values for the specified fields."""
|
"""Return a new D'ni time with new values for the specified fields."""
|
||||||
if gahrtahvo is None:
|
if gahrtahvo is None:
|
||||||
gahrtahvo = self._gahrtahvo
|
gahrtahvo = self._gahrtahvo
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
"""The DniTimedelta class."""
|
"""The DniTimedelta class."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from math import modf
|
from math import modf
|
||||||
from typing import Any, Tuple, TYPE_CHECKING, Union
|
from typing import TYPE_CHECKING, Any, Self
|
||||||
|
|
||||||
from .constants import DNI_UNITS, MAX_DNI_DELTA_YAHRTEE, MS_PER_PRORAHN
|
from .constants import DNI_UNITS, MAX_DNI_DELTA_YAHRTEE, MS_PER_PRORAHN
|
||||||
from .utils import cmp, divide_and_round
|
from .utils import cmp, divide_and_round
|
||||||
|
@ -19,19 +21,19 @@ class DniTimedelta:
|
||||||
_prorahntee: int
|
_prorahntee: int
|
||||||
|
|
||||||
# Class properties
|
# Class properties
|
||||||
min: "DniTimedelta"
|
min: DniTimedelta
|
||||||
max: "DniTimedelta"
|
max: DniTimedelta
|
||||||
resolution: "DniTimedelta"
|
resolution: DniTimedelta
|
||||||
|
|
||||||
def __new__(
|
def __new__(
|
||||||
cls,
|
cls,
|
||||||
yahrtee: Union[float, int] = 0,
|
yahrtee: float | int = 0,
|
||||||
pahrtahvotee: Union[float, int] = 0,
|
pahrtahvotee: float | int = 0,
|
||||||
prorahntee: Union[float, int] = 0,
|
prorahntee: float | int = 0,
|
||||||
gorahntee: Union[float, int] = 0,
|
gorahntee: float | int = 0,
|
||||||
tahvotee: Union[float, int] = 0,
|
tahvotee: float | int = 0,
|
||||||
gahrtahvotee: Union[float, int] = 0,
|
gahrtahvotee: float | int = 0,
|
||||||
vaileetee: Union[float, int] = 0,
|
vaileetee: float | int = 0,
|
||||||
) -> "DniTimedelta":
|
) -> "DniTimedelta":
|
||||||
# Final values are integer.
|
# Final values are integer.
|
||||||
yahr: int = 0
|
yahr: int = 0
|
||||||
|
@ -165,7 +167,7 @@ class DniTimedelta:
|
||||||
return self._prorahntee
|
return self._prorahntee
|
||||||
|
|
||||||
# Arithmetic functions
|
# Arithmetic functions
|
||||||
def __add__(self, other: Any) -> "DniTimedelta":
|
def __add__(self, other: Any) -> DniTimedelta:
|
||||||
if isinstance(other, (timedelta, DniTimedelta)):
|
if isinstance(other, (timedelta, DniTimedelta)):
|
||||||
if isinstance(other, timedelta):
|
if isinstance(other, timedelta):
|
||||||
other = self.from_timedelta(other)
|
other = self.from_timedelta(other)
|
||||||
|
@ -178,7 +180,7 @@ class DniTimedelta:
|
||||||
|
|
||||||
__radd__ = __add__
|
__radd__ = __add__
|
||||||
|
|
||||||
def __sub__(self, other: Any) -> "DniTimedelta":
|
def __sub__(self, other: Any) -> DniTimedelta:
|
||||||
if isinstance(other, (timedelta, DniTimedelta)):
|
if isinstance(other, (timedelta, DniTimedelta)):
|
||||||
if isinstance(other, timedelta):
|
if isinstance(other, timedelta):
|
||||||
other = self.from_timedelta(other)
|
other = self.from_timedelta(other)
|
||||||
|
@ -189,25 +191,25 @@ class DniTimedelta:
|
||||||
)
|
)
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
def __rsub__(self, other: Any) -> "DniTimedelta":
|
def __rsub__(self, other: Any) -> DniTimedelta:
|
||||||
if isinstance(other, (timedelta, DniTimedelta)):
|
if isinstance(other, (timedelta, DniTimedelta)):
|
||||||
if isinstance(other, timedelta):
|
if isinstance(other, timedelta):
|
||||||
other = self.from_timedelta(other)
|
other = self.from_timedelta(other)
|
||||||
return -self + other
|
return -self + other
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
def __neg__(self) -> "DniTimedelta":
|
def __neg__(self) -> DniTimedelta:
|
||||||
return DniTimedelta(-self._yahrtee, -self._pahrtahvotee, -self._prorahntee)
|
return DniTimedelta(-self._yahrtee, -self._pahrtahvotee, -self._prorahntee)
|
||||||
|
|
||||||
def __pos__(self) -> "DniTimedelta":
|
def __pos__(self) -> DniTimedelta:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __abs__(self) -> "DniTimedelta":
|
def __abs__(self) -> DniTimedelta:
|
||||||
if self._yahrtee < 0:
|
if self._yahrtee < 0:
|
||||||
return -self
|
return -self
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __mul__(self, other: Any) -> "DniTimedelta":
|
def __mul__(self, other: Any) -> DniTimedelta:
|
||||||
if isinstance(other, int):
|
if isinstance(other, int):
|
||||||
return DniTimedelta(
|
return DniTimedelta(
|
||||||
self._yahrtee * other,
|
self._yahrtee * other,
|
||||||
|
@ -222,7 +224,7 @@ class DniTimedelta:
|
||||||
|
|
||||||
__rmul__ = __mul__
|
__rmul__ = __mul__
|
||||||
|
|
||||||
def __floordiv__(self, other: Any) -> Union["DniTimedelta", int]:
|
def __floordiv__(self, other: Any) -> DniTimedelta | int:
|
||||||
if not isinstance(other, (int, DniTimedelta)):
|
if not isinstance(other, (int, DniTimedelta)):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
pro = self.total_prorahntee()
|
pro = self.total_prorahntee()
|
||||||
|
@ -231,7 +233,7 @@ class DniTimedelta:
|
||||||
if isinstance(other, int):
|
if isinstance(other, int):
|
||||||
return DniTimedelta(0, 0, pro // other)
|
return DniTimedelta(0, 0, pro // other)
|
||||||
|
|
||||||
def __truediv__(self, other: Any) -> Union["DniTimedelta", float]:
|
def __truediv__(self, other: Any) -> DniTimedelta | float:
|
||||||
if not isinstance(other, (float, int, DniTimedelta)):
|
if not isinstance(other, (float, int, DniTimedelta)):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
pro = self.total_prorahntee()
|
pro = self.total_prorahntee()
|
||||||
|
@ -243,13 +245,13 @@ class DniTimedelta:
|
||||||
if isinstance(other, int):
|
if isinstance(other, int):
|
||||||
return DniTimedelta(0, 0, divide_and_round(pro, other))
|
return DniTimedelta(0, 0, divide_and_round(pro, other))
|
||||||
|
|
||||||
def __mod__(self, other: Any) -> "DniTimedelta":
|
def __mod__(self, other: Any) -> DniTimedelta:
|
||||||
if isinstance(other, DniTimedelta):
|
if isinstance(other, DniTimedelta):
|
||||||
rem = self.total_prorahntee() % other.total_prorahntee()
|
rem = self.total_prorahntee() % other.total_prorahntee()
|
||||||
return DniTimedelta(0, 0, rem)
|
return DniTimedelta(0, 0, rem)
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
def __divmod__(self, other: Any) -> Tuple[int, "DniTimedelta"]:
|
def __divmod__(self, other: Any) -> tuple[int, DniTimedelta]:
|
||||||
if isinstance(other, DniTimedelta):
|
if isinstance(other, DniTimedelta):
|
||||||
quot, rem = divmod(self.total_prorahntee(), other.total_prorahntee())
|
quot, rem = divmod(self.total_prorahntee(), other.total_prorahntee())
|
||||||
return quot, DniTimedelta(0, 0, rem)
|
return quot, DniTimedelta(0, 0, rem)
|
||||||
|
@ -290,7 +292,7 @@ class DniTimedelta:
|
||||||
return self._yahrtee != 0 or self._pahrtahvotee != 0 or self._prorahntee != 0
|
return self._yahrtee != 0 or self._pahrtahvotee != 0 or self._prorahntee != 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_timedelta(cls, delta: timedelta) -> "DniTimedelta":
|
def from_timedelta(cls, delta: timedelta) -> DniTimedelta:
|
||||||
"""Converts a normal timedelta to a D'Ni timedelta."""
|
"""Converts a normal timedelta to a D'Ni timedelta."""
|
||||||
prorahntee = delta.total_seconds() * 1000 / MS_PER_PRORAHN
|
prorahntee = delta.total_seconds() * 1000 / MS_PER_PRORAHN
|
||||||
return cls(prorahntee=prorahntee)
|
return cls(prorahntee=prorahntee)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# pylint: disable=line-too-long
|
# pylint: disable=line-too-long
|
||||||
|
|
||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
from typing import Any, Optional, Tuple, Union
|
from typing import Any
|
||||||
|
|
||||||
from .constants import DNI_UNITS, EARTH_EPOCH, LEAP_MS_FROM_EPOCH
|
from .constants import DNI_UNITS, EARTH_EPOCH, LEAP_MS_FROM_EPOCH
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ def cmp(x: Any, y: Any) -> int:
|
||||||
return 0 if x == y else 1 if x > y else -1
|
return 0 if x == y else 1 if x > y else -1
|
||||||
|
|
||||||
|
|
||||||
def divide_and_round(a: Union[float, int], b: Union[float, int]) -> int:
|
def divide_and_round(a: float | int, b: float | int) -> int:
|
||||||
"""Divide a by b and round result to the nearest integer. When the ratio
|
"""Divide a by b and round result to the nearest integer. When the ratio
|
||||||
is exactly half-way between two integers, the even integer is returned.
|
is exactly half-way between two integers, the even integer is returned.
|
||||||
"""
|
"""
|
||||||
|
@ -35,7 +35,7 @@ def check_dni_date_fields(
|
||||||
hahr: int = DNI_UNITS["hahr"]["min"],
|
hahr: int = DNI_UNITS["hahr"]["min"],
|
||||||
vailee: int = DNI_UNITS["vailee"]["min"],
|
vailee: int = DNI_UNITS["vailee"]["min"],
|
||||||
yahr: int = DNI_UNITS["yahr"]["min"],
|
yahr: int = DNI_UNITS["yahr"]["min"],
|
||||||
) -> Tuple[int, int, int]:
|
) -> tuple[int, int, int]:
|
||||||
"""Verifies the D'Ni date fields are within proper boundaries."""
|
"""Verifies the D'Ni date fields are within proper boundaries."""
|
||||||
if not DNI_UNITS["hahr"]["min"] <= hahr <= DNI_UNITS["hahr"]["max"]:
|
if not DNI_UNITS["hahr"]["min"] <= hahr <= DNI_UNITS["hahr"]["max"]:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
@ -60,7 +60,7 @@ def check_dni_time_fields(
|
||||||
tahvo: int = DNI_UNITS["tahvo"]["min"],
|
tahvo: int = DNI_UNITS["tahvo"]["min"],
|
||||||
gorahn: int = DNI_UNITS["gorahn"]["min"],
|
gorahn: int = DNI_UNITS["gorahn"]["min"],
|
||||||
prorahn: int = DNI_UNITS["prorahn"]["min"],
|
prorahn: int = DNI_UNITS["prorahn"]["min"],
|
||||||
) -> Tuple[int, int, int, int]:
|
) -> tuple[int, int, int, int]:
|
||||||
"""Verifies the D'Ni time fields are within proper boundaries."""
|
"""Verifies the D'Ni time fields are within proper boundaries."""
|
||||||
if (
|
if (
|
||||||
not DNI_UNITS["gahrtahvo"]["min"]
|
not DNI_UNITS["gahrtahvo"]["min"]
|
||||||
|
@ -76,20 +76,12 @@ def check_dni_time_fields(
|
||||||
f"Tahvo must be in {DNI_UNITS['tahvo']['min']}..{DNI_UNITS['tahvo']['max'] - 1}",
|
f"Tahvo must be in {DNI_UNITS['tahvo']['min']}..{DNI_UNITS['tahvo']['max'] - 1}",
|
||||||
tahvo,
|
tahvo,
|
||||||
)
|
)
|
||||||
if (
|
if not DNI_UNITS["gorahn"]["min"] <= gorahn <= DNI_UNITS["gorahn"]["max"] - 1:
|
||||||
not DNI_UNITS["gorahn"]["min"]
|
|
||||||
<= gorahn
|
|
||||||
<= DNI_UNITS["gorahn"]["max"] - 1
|
|
||||||
):
|
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Gorahn must be in {DNI_UNITS['gorahn']['min']}..{DNI_UNITS['gorahn']['max'] - 1}",
|
f"Gorahn must be in {DNI_UNITS['gorahn']['min']}..{DNI_UNITS['gorahn']['max'] - 1}",
|
||||||
gorahn,
|
gorahn,
|
||||||
)
|
)
|
||||||
if (
|
if not DNI_UNITS["prorahn"]["min"] <= prorahn <= DNI_UNITS["prorahn"]["max"] - 1:
|
||||||
not DNI_UNITS["prorahn"]["min"]
|
|
||||||
<= prorahn
|
|
||||||
<= DNI_UNITS["prorahn"]["max"] - 1
|
|
||||||
):
|
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Prorahn must be in {DNI_UNITS['prorahn']['min']}..{DNI_UNITS['prorahn']['max'] - 1}",
|
f"Prorahn must be in {DNI_UNITS['prorahn']['min']}..{DNI_UNITS['prorahn']['max'] - 1}",
|
||||||
prorahn,
|
prorahn,
|
||||||
|
@ -111,7 +103,7 @@ def add_leap_seconds(timestamp: int) -> int:
|
||||||
return timestamp + (leap_seconds * 1000)
|
return timestamp + (leap_seconds * 1000)
|
||||||
|
|
||||||
|
|
||||||
def get_ms_from_epoch(date_time: Optional[datetime] = None) -> int:
|
def get_ms_from_epoch(date_time: datetime | None = None) -> int:
|
||||||
"""
|
"""
|
||||||
Returns the amount of milliseconds since the UNIX epoch (1-1-1970).
|
Returns the amount of milliseconds since the UNIX epoch (1-1-1970).
|
||||||
"""
|
"""
|
||||||
|
@ -124,7 +116,7 @@ def get_ms_from_epoch(date_time: Optional[datetime] = None) -> int:
|
||||||
return ((date - EARTH_EPOCH) // timedelta(microseconds=1)) // 1000
|
return ((date - EARTH_EPOCH) // timedelta(microseconds=1)) // 1000
|
||||||
|
|
||||||
|
|
||||||
def get_adj_ms_from_epoch(date_time: Optional[datetime] = None) -> int:
|
def get_adj_ms_from_epoch(date_time: datetime | None = None) -> int:
|
||||||
"""
|
"""
|
||||||
Returns the amount of milliseconds since the UNIX epoch (1-1-1970),
|
Returns the amount of milliseconds since the UNIX epoch (1-1-1970),
|
||||||
but also accounting for leap seconds.
|
but also accounting for leap seconds.
|
||||||
|
|
Loading…
Reference in a new issue