Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/utils/timezone.py: 45%
119 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1"""
2Timezone-related classes and functions.
3"""
5import functools
6import sys
7import warnings
9try:
10 import zoneinfo
11except ImportError:
12 from backports import zoneinfo
14from contextlib import ContextDecorator
15from datetime import datetime, timedelta, timezone, tzinfo
17from asgiref.local import Local
19from django.conf import settings
20from django.utils.deprecation import RemovedInDjango50Warning
22__all__ = [
23 "utc",
24 "get_fixed_timezone",
25 "get_default_timezone",
26 "get_default_timezone_name",
27 "get_current_timezone",
28 "get_current_timezone_name",
29 "activate",
30 "deactivate",
31 "override",
32 "localtime",
33 "now",
34 "is_aware",
35 "is_naive",
36 "make_aware",
37 "make_naive",
38]
40# RemovedInDjango50Warning: sentinel for deprecation of is_dst parameters.
41NOT_PASSED = object()
44utc = timezone.utc
47def get_fixed_timezone(offset):
48 """Return a tzinfo instance with a fixed offset from UTC."""
49 if isinstance(offset, timedelta):
50 offset = offset.total_seconds() // 60
51 sign = "-" if offset < 0 else "+"
52 hhmm = "%02d%02d" % divmod(abs(offset), 60)
53 name = sign + hhmm
54 return timezone(timedelta(minutes=offset), name)
57# In order to avoid accessing settings at compile time,
58# wrap the logic in a function and cache the result.
59@functools.lru_cache()
60def get_default_timezone():
61 """
62 Return the default time zone as a tzinfo instance.
64 This is the time zone defined by settings.TIME_ZONE.
65 """
66 if settings.USE_DEPRECATED_PYTZ: 66 ↛ 67line 66 didn't jump to line 67, because the condition on line 66 was never true
67 import pytz
69 return pytz.timezone(settings.TIME_ZONE)
70 return zoneinfo.ZoneInfo(settings.TIME_ZONE)
73# This function exists for consistency with get_current_timezone_name
74def get_default_timezone_name():
75 """Return the name of the default time zone."""
76 return _get_timezone_name(get_default_timezone())
79_active = Local()
82def get_current_timezone():
83 """Return the currently active time zone as a tzinfo instance."""
84 return getattr(_active, "value", get_default_timezone())
87def get_current_timezone_name():
88 """Return the name of the currently active time zone."""
89 return _get_timezone_name(get_current_timezone())
92def _get_timezone_name(timezone):
93 """
94 Return the offset for fixed offset timezones, or the name of timezone if
95 not set.
96 """
97 return timezone.tzname(None) or str(timezone)
100# Timezone selection functions.
102# These functions don't change os.environ['TZ'] and call time.tzset()
103# because it isn't thread safe.
106def activate(timezone):
107 """
108 Set the time zone for the current thread.
110 The ``timezone`` argument must be an instance of a tzinfo subclass or a
111 time zone name.
112 """
113 if isinstance(timezone, tzinfo):
114 _active.value = timezone
115 elif isinstance(timezone, str):
116 if settings.USE_DEPRECATED_PYTZ:
117 import pytz
119 _active.value = pytz.timezone(timezone)
120 else:
121 _active.value = zoneinfo.ZoneInfo(timezone)
122 else:
123 raise ValueError("Invalid timezone: %r" % timezone)
126def deactivate():
127 """
128 Unset the time zone for the current thread.
130 Django will then use the time zone defined by settings.TIME_ZONE.
131 """
132 if hasattr(_active, "value"):
133 del _active.value
136class override(ContextDecorator):
137 """
138 Temporarily set the time zone for the current thread.
140 This is a context manager that uses django.utils.timezone.activate()
141 to set the timezone on entry and restores the previously active timezone
142 on exit.
144 The ``timezone`` argument must be an instance of a ``tzinfo`` subclass, a
145 time zone name, or ``None``. If it is ``None``, Django enables the default
146 time zone.
147 """
149 def __init__(self, timezone):
150 self.timezone = timezone
152 def __enter__(self):
153 self.old_timezone = getattr(_active, "value", None)
154 if self.timezone is None:
155 deactivate()
156 else:
157 activate(self.timezone)
159 def __exit__(self, exc_type, exc_value, traceback):
160 if self.old_timezone is None:
161 deactivate()
162 else:
163 _active.value = self.old_timezone
166# Templates
169def template_localtime(value, use_tz=None):
170 """
171 Check if value is a datetime and converts it to local time if necessary.
173 If use_tz is provided and is not None, that will force the value to
174 be converted (or not), overriding the value of settings.USE_TZ.
176 This function is designed for use by the template engine.
177 """
178 should_convert = (
179 isinstance(value, datetime)
180 and (settings.USE_TZ if use_tz is None else use_tz)
181 and not is_naive(value)
182 and getattr(value, "convert_to_local_time", True)
183 )
184 return localtime(value) if should_convert else value
187# Utilities
190def localtime(value=None, timezone=None):
191 """
192 Convert an aware datetime.datetime to local time.
194 Only aware datetimes are allowed. When value is omitted, it defaults to
195 now().
197 Local time is defined by the current time zone, unless another time zone
198 is specified.
199 """
200 if value is None:
201 value = now()
202 if timezone is None:
203 timezone = get_current_timezone()
204 # Emulate the behavior of astimezone() on Python < 3.6.
205 if is_naive(value):
206 raise ValueError("localtime() cannot be applied to a naive datetime")
207 return value.astimezone(timezone)
210def localdate(value=None, timezone=None):
211 """
212 Convert an aware datetime to local time and return the value's date.
214 Only aware datetimes are allowed. When value is omitted, it defaults to
215 now().
217 Local time is defined by the current time zone, unless another time zone is
218 specified.
219 """
220 return localtime(value, timezone).date()
223def now():
224 """
225 Return an aware or naive datetime.datetime, depending on settings.USE_TZ.
226 """
227 return datetime.now(tz=utc if settings.USE_TZ else None)
230# By design, these four functions don't perform any checks on their arguments.
231# The caller should ensure that they don't receive an invalid value like None.
234def is_aware(value):
235 """
236 Determine if a given datetime.datetime is aware.
238 The concept is defined in Python's docs:
239 https://docs.python.org/library/datetime.html#datetime.tzinfo
241 Assuming value.tzinfo is either None or a proper datetime.tzinfo,
242 value.utcoffset() implements the appropriate logic.
243 """
244 return value.utcoffset() is not None
247def is_naive(value):
248 """
249 Determine if a given datetime.datetime is naive.
251 The concept is defined in Python's docs:
252 https://docs.python.org/library/datetime.html#datetime.tzinfo
254 Assuming value.tzinfo is either None or a proper datetime.tzinfo,
255 value.utcoffset() implements the appropriate logic.
256 """
257 return value.utcoffset() is None
260def make_aware(value, timezone=None, is_dst=NOT_PASSED):
261 """Make a naive datetime.datetime in a given time zone aware."""
262 if is_dst is NOT_PASSED: 262 ↛ 265line 262 didn't jump to line 265, because the condition on line 262 was never false
263 is_dst = None
264 else:
265 warnings.warn(
266 "The is_dst argument to make_aware(), used by the Trunc() "
267 "database functions and QuerySet.datetimes(), is deprecated as it "
268 "has no effect with zoneinfo time zones.",
269 RemovedInDjango50Warning,
270 )
271 if timezone is None: 271 ↛ 272line 271 didn't jump to line 272, because the condition on line 271 was never true
272 timezone = get_current_timezone()
273 if _is_pytz_zone(timezone): 273 ↛ 275line 273 didn't jump to line 275, because the condition on line 273 was never true
274 # This method is available for pytz time zones.
275 return timezone.localize(value, is_dst=is_dst)
276 else:
277 # Check that we won't overwrite the timezone of an aware datetime.
278 if is_aware(value): 278 ↛ 279line 278 didn't jump to line 279, because the condition on line 278 was never true
279 raise ValueError("make_aware expects a naive datetime, got %s" % value)
280 # This may be wrong around DST changes!
281 return value.replace(tzinfo=timezone)
284def make_naive(value, timezone=None):
285 """Make an aware datetime.datetime naive in a given time zone."""
286 if timezone is None:
287 timezone = get_current_timezone()
288 # Emulate the behavior of astimezone() on Python < 3.6.
289 if is_naive(value):
290 raise ValueError("make_naive() cannot be applied to a naive datetime")
291 return value.astimezone(timezone).replace(tzinfo=None)
294_PYTZ_IMPORTED = False
297def _pytz_imported():
298 """
299 Detects whether or not pytz has been imported without importing pytz.
301 Copied from pytz_deprecation_shim with thanks to Paul Ganssle.
302 """
303 global _PYTZ_IMPORTED
305 if not _PYTZ_IMPORTED and "pytz" in sys.modules:
306 _PYTZ_IMPORTED = True
308 return _PYTZ_IMPORTED
311def _is_pytz_zone(tz):
312 """Checks if a zone is a pytz zone."""
313 # See if pytz was already imported rather than checking
314 # settings.USE_DEPRECATED_PYTZ to *allow* manually passing a pytz timezone,
315 # which some of the test cases (at least) rely on.
316 if not _pytz_imported(): 316 ↛ 317line 316 didn't jump to line 317, because the condition on line 316 was never true
317 return False
319 # If tz could be pytz, then pytz is needed here.
320 import pytz
322 _PYTZ_BASE_CLASSES = (pytz.tzinfo.BaseTzInfo, pytz._FixedOffset)
323 # In releases prior to 2018.4, pytz.UTC was not a subclass of BaseTzInfo
324 if not isinstance(pytz.UTC, pytz._FixedOffset): 324 ↛ 327line 324 didn't jump to line 327, because the condition on line 324 was never false
325 _PYTZ_BASE_CLASSES = _PYTZ_BASE_CLASSES + (type(pytz.UTC),)
327 return isinstance(tz, _PYTZ_BASE_CLASSES)
330def _datetime_ambiguous_or_imaginary(dt, tz):
331 if _is_pytz_zone(tz):
332 import pytz
334 try:
335 tz.utcoffset(dt)
336 except (pytz.AmbiguousTimeError, pytz.NonExistentTimeError):
337 return True
338 else:
339 return False
341 return tz.utcoffset(dt.replace(fold=not dt.fold)) != tz.utcoffset(dt)