Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pendulum/helpers.py: 39%
122 statements
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
1from __future__ import absolute_import
3import os
4import struct
6from contextlib import contextmanager
7from datetime import date
8from datetime import datetime
9from datetime import timedelta
10from math import copysign
11from typing import TYPE_CHECKING
12from typing import Iterator
13from typing import Optional
14from typing import TypeVar
15from typing import overload
17import pendulum
19from .constants import DAYS_PER_MONTHS
20from .formatting.difference_formatter import DifferenceFormatter
21from .locales.locale import Locale
24if TYPE_CHECKING:
25 # Prevent import cycles
26 from .period import Period
28with_extensions = os.getenv("PENDULUM_EXTENSIONS", "1") == "1"
30_DT = TypeVar("_DT", bound=datetime)
31_D = TypeVar("_D", bound=date)
33try:
34 if not with_extensions or struct.calcsize("P") == 4:
35 raise ImportError()
37 from ._extensions._helpers import local_time
38 from ._extensions._helpers import precise_diff
39 from ._extensions._helpers import is_leap
40 from ._extensions._helpers import is_long_year
41 from ._extensions._helpers import week_day
42 from ._extensions._helpers import days_in_year
43 from ._extensions._helpers import timestamp
44except ImportError:
45 from ._extensions.helpers import local_time # noqa
46 from ._extensions.helpers import precise_diff # noqa
47 from ._extensions.helpers import is_leap # noqa
48 from ._extensions.helpers import is_long_year # noqa
49 from ._extensions.helpers import week_day # noqa
50 from ._extensions.helpers import days_in_year # noqa
51 from ._extensions.helpers import timestamp # noqa
54difference_formatter = DifferenceFormatter()
57@overload
58def add_duration(
59 dt, # type: _DT
60 years=0, # type: int
61 months=0, # type: int
62 weeks=0, # type: int
63 days=0, # type: int
64 hours=0, # type: int
65 minutes=0, # type: int
66 seconds=0, # type: int
67 microseconds=0, # type: int
68): # type: (...) -> _DT
69 pass
72@overload
73def add_duration(
74 dt, # type: _D
75 years=0, # type: int
76 months=0, # type: int
77 weeks=0, # type: int
78 days=0, # type: int
79): # type: (...) -> _D
80 pass
83def add_duration(
84 dt,
85 years=0,
86 months=0,
87 weeks=0,
88 days=0,
89 hours=0,
90 minutes=0,
91 seconds=0,
92 microseconds=0,
93):
94 """
95 Adds a duration to a date/datetime instance.
96 """
97 days += weeks * 7
99 if (
100 isinstance(dt, date)
101 and not isinstance(dt, datetime)
102 and any([hours, minutes, seconds, microseconds])
103 ):
104 raise RuntimeError("Time elements cannot be added to a date instance.")
106 # Normalizing
107 if abs(microseconds) > 999999:
108 s = _sign(microseconds)
109 div, mod = divmod(microseconds * s, 1000000)
110 microseconds = mod * s
111 seconds += div * s
113 if abs(seconds) > 59:
114 s = _sign(seconds)
115 div, mod = divmod(seconds * s, 60)
116 seconds = mod * s
117 minutes += div * s
119 if abs(minutes) > 59:
120 s = _sign(minutes)
121 div, mod = divmod(minutes * s, 60)
122 minutes = mod * s
123 hours += div * s
125 if abs(hours) > 23:
126 s = _sign(hours)
127 div, mod = divmod(hours * s, 24)
128 hours = mod * s
129 days += div * s
131 if abs(months) > 11:
132 s = _sign(months)
133 div, mod = divmod(months * s, 12)
134 months = mod * s
135 years += div * s
137 year = dt.year + years
138 month = dt.month
140 if months:
141 month += months
142 if month > 12:
143 year += 1
144 month -= 12
145 elif month < 1:
146 year -= 1
147 month += 12
149 day = min(DAYS_PER_MONTHS[int(is_leap(year))][month], dt.day)
151 dt = dt.replace(year=year, month=month, day=day)
153 return dt + timedelta(
154 days=days,
155 hours=hours,
156 minutes=minutes,
157 seconds=seconds,
158 microseconds=microseconds,
159 )
162def format_diff(
163 diff, is_now=True, absolute=False, locale=None
164): # type: (Period, bool, bool, Optional[str]) -> str
165 if locale is None:
166 locale = get_locale()
168 return difference_formatter.format(diff, is_now, absolute, locale)
171def _sign(x):
172 return int(copysign(1, x))
175# Global helpers
178@contextmanager
179def test(mock): # type: (pendulum.DateTime) -> Iterator[None]
180 set_test_now(mock)
181 try:
182 yield
183 finally:
184 set_test_now()
187def set_test_now(test_now=None): # type: (Optional[pendulum.DateTime]) -> None
188 pendulum._TEST_NOW = test_now
191def get_test_now(): # type: () -> Optional[pendulum.DateTime]
192 return pendulum._TEST_NOW
195def has_test_now(): # type: () -> bool
196 return pendulum._TEST_NOW is not None
199def locale(name): # type: (str) -> Locale
200 return Locale.load(name)
203def set_locale(name): # type: (str) -> None
204 locale(name)
206 pendulum._LOCALE = name
209def get_locale(): # type: () -> str
210 return pendulum._LOCALE
213def week_starts_at(wday): # type: (int) -> None
214 if wday < pendulum.SUNDAY or wday > pendulum.SATURDAY:
215 raise ValueError("Invalid week day as start of week.")
217 pendulum._WEEK_STARTS_AT = wday
220def week_ends_at(wday): # type: (int) -> None
221 if wday < pendulum.SUNDAY or wday > pendulum.SATURDAY:
222 raise ValueError("Invalid week day as start of week.")
224 pendulum._WEEK_ENDS_AT = wday