python-dateutil 4.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
dateutil/__init__.py ADDED
@@ -0,0 +1,25 @@
1
+ import sys
2
+
3
+ try:
4
+ from ._version import version as __version__
5
+ except ImportError:
6
+ __version__ = 'unknown'
7
+
8
+ __all__ = ["easter", "parser", "relativedelta", "rrule", "tz", "utils"]
9
+
10
+
11
+ def __getattr__(name):
12
+ import importlib
13
+
14
+ if name in __all__ or name == "zoneinfo":
15
+ return importlib.import_module("." + name, __name__)
16
+ raise AttributeError(
17
+ "module {!r} has no attribute {!r}".format(__name__, name)
18
+ )
19
+
20
+
21
+ def __dir__():
22
+ # __dir__ should include all the lazy-importable modules as well.
23
+ return (
24
+ [x for x in globals() if x not in sys.modules] + __all__ + ["zoneinfo"]
25
+ )
dateutil/_common.py ADDED
@@ -0,0 +1,40 @@
1
+ """
2
+ Common code used in multiple modules.
3
+ """
4
+
5
+
6
+ class weekday:
7
+ __slots__ = ["weekday", "n"]
8
+
9
+ def __init__(self, weekday, n=None):
10
+ self.weekday = weekday
11
+ self.n = n
12
+
13
+ def __call__(self, n):
14
+ if n == self.n:
15
+ return self
16
+ else:
17
+ return self.__class__(self.weekday, n)
18
+
19
+ def __eq__(self, other):
20
+ try:
21
+ if self.weekday != other.weekday or self.n != other.n:
22
+ return False
23
+ except AttributeError:
24
+ return False
25
+ return True
26
+
27
+ def __hash__(self):
28
+ return hash((
29
+ self.weekday,
30
+ self.n,
31
+ ))
32
+
33
+ def __repr__(self):
34
+ s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday]
35
+ if not self.n:
36
+ return s
37
+ else:
38
+ return "%s(%+d)" % (s, self.n)
39
+
40
+ # vim:ts=4:sw=4:et
@@ -0,0 +1,75 @@
1
+ """This is an implementation of functions that interact with the tzdata module.
2
+
3
+ It will only live as long as :mod:`dateutil.zoneinfo` lives; when the
4
+ ``dateutil.zoneinfo`` module is removed, this can all move under :mod:`tz`.
5
+ """
6
+
7
+ import importlib.resources
8
+ from typing import BinaryIO, TextIO
9
+
10
+ _TZDATA_LOAD_EXCEPTIONS = (
11
+ ImportError,
12
+ FileNotFoundError,
13
+ UnicodeEncodeError,
14
+ IsADirectoryError,
15
+ ValueError,
16
+ )
17
+
18
+
19
+ def _open_text(package: str, resource: str) -> TextIO:
20
+ return (
21
+ importlib.resources.files(package)
22
+ .joinpath(resource)
23
+ .open("r", encoding="utf-8")
24
+ )
25
+
26
+
27
+ def _open_binary(package: str, resource: str) -> BinaryIO:
28
+ return importlib.resources.files(package).joinpath(resource).open("rb")
29
+
30
+
31
+ def _is_package_directory(package: str, resource: str) -> bool:
32
+ """Checks for directories before opening resources on Windows."""
33
+ try:
34
+ return importlib.resources.files(package).joinpath(resource).is_dir()
35
+ except ImportError:
36
+ return False
37
+
38
+
39
+ def _load_tzdata(key):
40
+ components = key.split("/")
41
+ package_name = ".".join(["tzdata.zoneinfo"] + components[:-1])
42
+ resource_name = components[-1]
43
+
44
+ # Empty or relative path components cannot name a zone, and they produce
45
+ # module names that the import machinery handles inconsistently across
46
+ # versions, so treat them as not found up front. A key naming a directory
47
+ # (a subpackage) is not a zone either, and opening it raises a
48
+ # platform-dependent error, see CPython gh-85702.
49
+ if any(c in ("", ".", "..") for c in components) or _is_package_directory(
50
+ package_name, resource_name
51
+ ):
52
+ raise TZFileNotFound("Time zone not found: %s", zone_key=key)
53
+
54
+ try:
55
+ return _open_binary(package_name, resource_name)
56
+ except _TZDATA_LOAD_EXCEPTIONS:
57
+ # ImportError: package does not exist (or tzdata is not installed)
58
+ # FileNotFoundError: the key is not a file in the package
59
+ # UnicodeEncodeError: the key is not encodable as a filename
60
+ # IsADirectoryError: the key names a package rather than a resource
61
+ # ValueError: the key is not a valid path (e.g. contains a NUL byte)
62
+ raise TZFileNotFound("Time zone not found: %s", zone_key=key) from None
63
+
64
+
65
+ def _load_tzdata_keys():
66
+ with _open_text("tzdata", "zones") as f:
67
+ return list(filter(None, (l.strip() for l in f)))
68
+
69
+
70
+ class TZFileNotFound(ValueError):
71
+ """Indicates that a time zone file isn't present in tzdata."""
72
+
73
+ def __init__(self, msg: str, *args: object, zone_key: str) -> None:
74
+ super().__init__(msg % zone_key, *args)
75
+ self.zone_key = zone_key
dateutil/_version.py ADDED
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '4.0.0'
22
+ __version_tuple__ = version_tuple = (4, 0, 0)
23
+
24
+ __commit_id__ = commit_id = None
dateutil/easter.py ADDED
@@ -0,0 +1,88 @@
1
+ """
2
+ This module offers a generic Easter computing method for any given year, using
3
+ Western, Orthodox or Julian algorithms.
4
+ """
5
+
6
+ import datetime
7
+
8
+ __all__ = ["easter", "EASTER_JULIAN", "EASTER_ORTHODOX", "EASTER_WESTERN"]
9
+
10
+ EASTER_JULIAN = 1
11
+ EASTER_ORTHODOX = 2
12
+ EASTER_WESTERN = 3
13
+
14
+
15
+ def easter(year, method=EASTER_WESTERN):
16
+ """
17
+ This method was ported from the work done by GM Arts,
18
+ on top of the algorithm by Claus Tondering, which was
19
+ based in part on the algorithm of Ouding (1940), as
20
+ quoted in "Explanatory Supplement to the Astronomical
21
+ Almanac", P. Kenneth Seidelmann, editor.
22
+
23
+ This algorithm implements three different Easter
24
+ calculation methods:
25
+
26
+ 1. Original calculation in Julian calendar, valid in
27
+ dates after 326 AD
28
+ 2. Original method, with date converted to Gregorian
29
+ calendar, valid in years 1583 to 4099
30
+ 3. Revised method, in Gregorian calendar, valid in
31
+ years 1583 to 4099 as well
32
+
33
+ These methods are represented by the constants:
34
+
35
+ * ``EASTER_JULIAN = 1``
36
+ * ``EASTER_ORTHODOX = 2``
37
+ * ``EASTER_WESTERN = 3``
38
+
39
+ The default method is method 3.
40
+
41
+ More about the algorithm may be found at:
42
+
43
+ `GM Arts: Easter Algorithms <http://www.gmarts.org/index.php?go=415>`_
44
+
45
+ and
46
+
47
+ `The Calendar FAQ: Easter <https://www.tondering.dk/claus/cal/easter.php>`_
48
+
49
+ """
50
+
51
+ if not (1 <= method <= 3):
52
+ raise ValueError("invalid method")
53
+
54
+ # g - Golden year - 1
55
+ # c - Century
56
+ # h - (23 - Epact) mod 30
57
+ # i - Number of days from March 21 to Paschal Full Moon
58
+ # j - Weekday for PFM (0=Sunday, etc)
59
+ # p - Number of days from March 21 to Sunday on or before PFM
60
+ # (-6 to 28 methods 1 & 3, to 56 for method 2)
61
+ # e - Extra days to add for method 2 (converting Julian
62
+ # date to Gregorian date)
63
+
64
+ y = year
65
+ g = y % 19
66
+ e = 0
67
+ if method < 3:
68
+ # Old method
69
+ i = (19*g + 15) % 30
70
+ j = (y + y//4 + i) % 7
71
+ if method == 2:
72
+ # Extra dates to convert Julian to Gregorian date
73
+ e = 10
74
+ if y > 1600:
75
+ e = e + y//100 - 16 - (y//100 - 16)//4
76
+ else:
77
+ # New method
78
+ c = y//100
79
+ h = (c - c//4 - (8*c + 13)//25 + 19*g + 15) % 30
80
+ i = h - (h//28)*(1 - (h//28)*(29//(h + 1))*((21 - g)//11))
81
+ j = (y + y//4 + i + 2 - c + c//4) % 7
82
+
83
+ # p can be from -6 to 56 corresponding to dates 22 March to 23 May
84
+ # (later dates apply to method 2, although 23 May never actually occurs)
85
+ p = i - j + e
86
+ d = 1 + (p + 27 + (p + 6)//40) % 31
87
+ m = 3 + (p + 26)//30
88
+ return datetime.date(int(y), int(m), int(d))
@@ -0,0 +1,63 @@
1
+ from ._parser import (
2
+ DEFAULTPARSER,
3
+ DEFAULTTZPARSER,
4
+ ParserError,
5
+ UnknownTimezoneWarning,
6
+ __doc__,
7
+ parse,
8
+ parser,
9
+ parserinfo,
10
+ )
11
+ from .isoparser import isoparse, isoparser
12
+
13
+ __all__ = ['parse', 'parser', 'parserinfo',
14
+ 'isoparse', 'isoparser',
15
+ 'ParserError',
16
+ 'UnknownTimezoneWarning']
17
+
18
+
19
+ ###
20
+ # Deprecate portions of the private interface so that downstream code that
21
+ # is improperly relying on it is given *some* notice.
22
+
23
+
24
+ def __deprecated_private_func(f):
25
+ import warnings
26
+ from functools import wraps
27
+
28
+ msg = ('{name} is a private function and may break without warning, '
29
+ 'it will be moved and or renamed in future versions.')
30
+ msg = msg.format(name=f.__name__)
31
+
32
+ @wraps(f)
33
+ def deprecated_func(*args, **kwargs):
34
+ warnings.warn(msg, DeprecationWarning)
35
+ return f(*args, **kwargs)
36
+
37
+ return deprecated_func
38
+
39
+ def __deprecate_private_class(c):
40
+ import warnings
41
+
42
+ msg = ('{name} is a private class and may break without warning, '
43
+ 'it will be moved and or renamed in future versions.')
44
+ msg = msg.format(name=c.__name__)
45
+
46
+ class private_class(c):
47
+ __doc__ = c.__doc__
48
+
49
+ def __init__(self, *args, **kwargs):
50
+ warnings.warn(msg, DeprecationWarning)
51
+ super().__init__(*args, **kwargs)
52
+
53
+ private_class.__name__ = c.__name__
54
+
55
+ return private_class
56
+
57
+
58
+ from ._parser import _parsetz, _resultbase, _timelex, _tzparser
59
+
60
+ _timelex = __deprecate_private_class(_timelex)
61
+ _tzparser = __deprecate_private_class(_tzparser)
62
+ _resultbase = __deprecate_private_class(_resultbase)
63
+ _parsetz = __deprecated_private_func(_parsetz)