Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/icalendar/tools.py: 91%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Utility functions for icalendar."""
3from __future__ import annotations
5from datetime import date, datetime, tzinfo
6from typing import TYPE_CHECKING, cast
8if TYPE_CHECKING:
9 from icalendar.compatibility import TypeGuard, TypeIs
12def is_date(dt: date | datetime) -> bool:
13 """Check if a value is a date but not a datetime.
15 This function distinguishes between ``date`` and ``datetime`` objects,
16 returning ``True`` only for pure ``date`` instances.
18 Parameters:
19 dt: The date or datetime object to check.
21 Returns:
22 ``True`` if the value is a ``date`` but not a ``datetime``,
23 ``False`` otherwise.
25 Example:
26 .. code-block:: pycon
28 >>> from datetime import date, datetime
29 >>> from icalendar.tools import is_date
30 >>> is_date(date(2024, 1, 15))
31 True
32 >>> is_date(datetime(2024, 1, 15, 10, 30))
33 False
34 """
35 return isinstance(dt, date) and not isinstance(dt, datetime)
38def is_datetime(dt: date | datetime) -> TypeIs[datetime]:
39 """Check if a value is a datetime.
41 Parameters:
42 dt: The date or datetime object to check.
44 Returns:
45 ``True`` if the value is a ``datetime``, ``False`` if it is
46 only a ``date``.
48 Example:
49 .. code-block:: pycon
51 >>> from datetime import date, datetime
52 >>> from icalendar.tools import is_datetime
53 >>> is_datetime(datetime(2024, 1, 15, 10, 30))
54 True
55 >>> is_datetime(date(2024, 1, 15))
56 False
57 """
58 return isinstance(dt, datetime)
61def to_datetime(dt: date | datetime) -> datetime:
62 """Convert a date to a datetime.
64 If the input is already a ``datetime``, it is returned unchanged.
65 If the input is a ``date``, it is converted to a ``datetime`` at midnight.
67 Parameters:
68 dt: The date or datetime to convert.
70 Returns:
71 A ``datetime`` object. If the input was a ``date``, the time
72 component will be set to midnight (00:00:00).
74 Example:
75 .. code-block:: pycon
77 >>> from datetime import date, datetime
78 >>> from icalendar.tools import to_datetime
79 >>> to_datetime(date(2024, 1, 15))
80 datetime.datetime(2024, 1, 15, 0, 0)
81 >>> to_datetime(datetime(2024, 1, 15, 10, 30))
82 datetime.datetime(2024, 1, 15, 10, 30)
83 """
84 if is_date(dt):
85 return datetime(dt.year, dt.month, dt.day) # noqa: DTZ001
86 return cast("datetime", dt)
89def is_pytz(tz: tzinfo) -> bool:
90 """Check if a timezone is a pytz timezone.
92 pytz timezones require special handling with ``localize()`` and
93 ``normalize()`` methods for correct timezone calculations.
95 Parameters:
96 tz: The timezone info object to check.
98 Returns:
99 ``True`` if the timezone is a pytz timezone (has a ``localize``
100 attribute), ``False`` otherwise.
101 """
102 return hasattr(tz, "localize")
105def is_pytz_dt(dt: date | datetime) -> TypeGuard[datetime]:
106 """Check if a datetime uses a pytz timezone.
108 This function checks whether the datetime has a timezone attached
109 and whether that timezone is a pytz timezone requiring special handling.
111 Parameters:
112 dt: The date or datetime object to check.
114 Returns:
115 ``True`` if the value is a ``datetime`` with a pytz timezone,
116 ``False`` otherwise.
117 """
118 return is_datetime(dt) and (tzinfo := dt.tzinfo) is not None and is_pytz(tzinfo)
121def normalize_pytz(dt: date | datetime) -> date | datetime:
122 """Normalize a datetime after calculations when using pytz.
124 pytz requires the ``normalize()`` function to be called after arithmetic
125 operations to correctly adjust the timezone offset, especially around
126 daylight saving time transitions.
128 Parameters:
129 dt: The date or datetime to normalize.
131 Returns:
132 The normalized datetime if it uses pytz, otherwise the input unchanged.
133 """
134 if is_pytz_dt(dt):
135 return dt.tzinfo.normalize(dt) # type: ignore[attr-defined]
136 return dt
139__all__ = [
140 "is_date",
141 "is_datetime",
142 "is_pytz",
143 "is_pytz_dt",
144 "normalize_pytz",
145 "to_datetime",
146]