Skip to content

Timezone components

These are the components that are related to TimeZone information. You generally don't use these directly but let iCal-library use it when there is a TZID parameter set for a property.

The DayLight and Standard class both extend the _TimeOffsetPeriod.

VTimeZone

Bases: Component

This class represents the VTIMEZONE component specified in RFC 5545 in '3.6.5. Time Zone Component'.

If present, the "VTIMEZONE" calendar component defines the set of Standard Time and Daylight Saving Time observances (or rules) for a particular time zone for a given interval of time. The "VTIMEZONE" calendar component cannot be nested within other calendar components. Multiple "VTIMEZONE" calendar components can exist in an iCalendar object. In this situation, each "VTIMEZONE" MUST represent a unique time zone definition. This is necessary for some classes of events, such as airline flights, that start in one time zone and end in another.

Parameters:

Name Type Description Default
parent Optional[Component]

The Component this item is encapsulated by in the iCalendar data file.

None
tzid Optional[TZID]

The TZID property. Required and must occur exactly once.

None
last_mod Optional[LastModified]

Optional LastModified property. Optional, but may occur at most once.

None
tzurl Optional[TZURL]

The TZURL property. Optional, but may occur at most once.

None
standardc Optional[List[Standard]]

Optional list of Standard components. Each component may occur multiple times. Either standardc or daylightc must contain at least one TimeOffsetPeriod.

None
daylightc Optional[List[DayLight]]

Optional list of DayLight components. Each component may occur multiple times. Either standardc or daylightc must contain at least one TimeOffsetPeriod.

None
Source code in ical_library/ical_components/v_timezone.py
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
class VTimeZone(Component):
    """
    This class represents the VTIMEZONE component specified in RFC 5545 in '3.6.5. Time Zone Component'.

    If present, the "VTIMEZONE" calendar component defines the set of Standard Time and Daylight Saving Time
    observances (or rules) for a particular time zone for a given interval of time. The "VTIMEZONE" calendar component
    cannot be nested within other calendar components. Multiple "VTIMEZONE" calendar components can exist in an
    iCalendar object. In this situation, each "VTIMEZONE" MUST represent a unique time zone definition. This is
    necessary for some classes of events, such as airline flights, that start in one time zone and end in another.

    :param parent: The Component this item is encapsulated by in the iCalendar data file.
    :param tzid: The TZID property. Required and must occur exactly once.
    :param last_mod: Optional LastModified property. Optional, but may occur at most once.
    :param tzurl: The TZURL property. Optional, but may occur at most once.
    :param standardc: Optional list of Standard components. Each component may occur multiple times. Either standardc
    or daylightc must contain at least one TimeOffsetPeriod.
    :param daylightc: Optional list of DayLight components. Each component may occur multiple times. Either standardc
    or daylightc must contain at least one TimeOffsetPeriod.
    """

    def __init__(
        self,
        tzid: Optional[TZID] = None,
        last_mod: Optional[LastModified] = None,
        tzurl: Optional[TZURL] = None,
        standardc: Optional[List[Standard]] = None,
        daylightc: Optional[List[DayLight]] = None,
        parent: Optional[Component] = None,
    ):
        super().__init__("VTIMEZONE", parent=parent)

        # Required properties, must occur one.
        self._tzid: Optional[TZID] = self.as_parent(tzid)
        # Optional properties, may only occur once.
        self.last_mod: Optional[LastModified] = self.as_parent(last_mod)
        self.tzurl: Optional[TZURL] = self.as_parent(tzurl)
        # Either one of these components must have at least one record. May occur multiple times.
        self.standardc: List[Standard] = standardc or []
        self.daylightc: List[DayLight] = daylightc or []

        self.__storage_of_results: Dict[DateTime, List[Tuple[DateTime, _TimeOffsetPeriod]]] = {}

    def __repr__(self) -> str:
        """Overwrite the repr to create a better representation for the item."""
        return f"VTimeZone({self.tzid.value})"

    @property
    def tzid(self) -> TZID:
        """A getter to ensure the required property is set."""
        if self._tzid is None:
            raise MissingRequiredProperty(self, "tzid")
        return self._tzid

    @tzid.setter
    def tzid(self, value: TZID):
        """A setter to set the required property."""
        self._tzid = value

    def get_ordered_timezone_overview(self, max_datetime: DateTime) -> List[Tuple[DateTime, _TimeOffsetPeriod]]:
        """
        Expand all TimeOffsetPeriod configuration and return them in an ordered by time fashion.
        :param max_datetime: The maximum datetime value we wish to expand to.
        :return: A sorted list on datetime containing tuples of datetime and offset period where the datetime is
        lower than *max_datetime*.
        """
        if max_datetime in self.__storage_of_results.keys():
            return self.__storage_of_results[max_datetime]
        all_timezones: List[Tuple[Union[DateTime, Date], _TimeOffsetPeriod]] = []
        for a_standard in self.standardc:
            all_timezones.extend(a_standard.get_time_sequence(max_datetime=max_datetime))
        for a_daylight in self.daylightc:
            all_timezones.extend(a_daylight.get_time_sequence(max_datetime=max_datetime))
        sorted_list = sorted(all_timezones, key=lambda tup: tup[0])
        self.__storage_of_results[max_datetime] = sorted_list
        return sorted_list

    def convert_naive_datetime_to_aware(self, dt: DateTime) -> DateTime:
        """
        Convert a naive datetime to an aware datetime using the configuration of this TimeZone object.
        :param dt: The (possibly naive) datetime to convert to this timezone configuration.
        :return: The timezone aware datetime.
        """
        if dt.tzinfo is not None:
            return dt
        return dt.in_timezone(self.get_as_timezone_object())

    def get_ordered_timezone_overview_as_transition(self, max_datetime: DateTime) -> List[Transition]:
        """
        Get timezone components as a list of pendulum Transitions.
        :param max_datetime: The maximum datetime for which we include transitions. Any transitions after are excluded.
        :return: Return the list of pendulum Transitions for this VTimezone.
        """
        timezones: List[Tuple[DateTime, _TimeOffsetPeriod]] = self.get_ordered_timezone_overview(max_datetime)
        transitions: List[Transition] = []
        previous_transition: Optional[Transition] = None
        for time, offset_period in timezones:
            new_transition_type = TransitionType(
                offset=offset_period.tzoffsetto.parse_value_as_seconds(),
                is_dst=offset_period.is_dst,
                abbr=offset_period.tzname[0].value if offset_period.tzname else "unknown",
            )
            at = int(time.in_tz("UTC").timestamp())
            new_transition = Transition(at=at, ttype=new_transition_type, previous=previous_transition)
            previous_transition = new_transition
            transitions.append(new_transition)
        return transitions

    @instance_lru_cache()
    def get_as_timezone_object(self, max_datetime: DateTime = DateTime(2100, 1, 1)) -> Timezone:
        """
        For a given maximum datetime, compute a pendulum Timezone object that contains all transition till max_datetime.
        :param max_datetime: The maximum datetime for which we include transitions. Any transitions after are excluded.
        :return: Returns a pendulum Timezone object that you can use for DateTimes.
        """
        return CustomTimezone(
            name=self.tzid.value, transitions=self.get_ordered_timezone_overview_as_transition(max_datetime)
        )

tzid: TZID property writable

A getter to ensure the required property is set.

convert_naive_datetime_to_aware(dt)

Convert a naive datetime to an aware datetime using the configuration of this TimeZone object.

Parameters:

Name Type Description Default
dt DateTime

The (possibly naive) datetime to convert to this timezone configuration.

required

Returns:

Type Description
DateTime

The timezone aware datetime.

Source code in ical_library/ical_components/v_timezone.py
189
190
191
192
193
194
195
196
197
def convert_naive_datetime_to_aware(self, dt: DateTime) -> DateTime:
    """
    Convert a naive datetime to an aware datetime using the configuration of this TimeZone object.
    :param dt: The (possibly naive) datetime to convert to this timezone configuration.
    :return: The timezone aware datetime.
    """
    if dt.tzinfo is not None:
        return dt
    return dt.in_timezone(self.get_as_timezone_object())

get_as_timezone_object(max_datetime=DateTime(2100, 1, 1))

For a given maximum datetime, compute a pendulum Timezone object that contains all transition till max_datetime.

Parameters:

Name Type Description Default
max_datetime DateTime

The maximum datetime for which we include transitions. Any transitions after are excluded.

DateTime(2100, 1, 1)

Returns:

Type Description
Timezone

Returns a pendulum Timezone object that you can use for DateTimes.

Source code in ical_library/ical_components/v_timezone.py
220
221
222
223
224
225
226
227
228
229
@instance_lru_cache()
def get_as_timezone_object(self, max_datetime: DateTime = DateTime(2100, 1, 1)) -> Timezone:
    """
    For a given maximum datetime, compute a pendulum Timezone object that contains all transition till max_datetime.
    :param max_datetime: The maximum datetime for which we include transitions. Any transitions after are excluded.
    :return: Returns a pendulum Timezone object that you can use for DateTimes.
    """
    return CustomTimezone(
        name=self.tzid.value, transitions=self.get_ordered_timezone_overview_as_transition(max_datetime)
    )

get_ordered_timezone_overview(max_datetime)

Expand all TimeOffsetPeriod configuration and return them in an ordered by time fashion.

Parameters:

Name Type Description Default
max_datetime DateTime

The maximum datetime value we wish to expand to.

required

Returns:

Type Description
List[Tuple[DateTime, _TimeOffsetPeriod]]

A sorted list on datetime containing tuples of datetime and offset period where the datetime is lower than max_datetime.

Source code in ical_library/ical_components/v_timezone.py
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
def get_ordered_timezone_overview(self, max_datetime: DateTime) -> List[Tuple[DateTime, _TimeOffsetPeriod]]:
    """
    Expand all TimeOffsetPeriod configuration and return them in an ordered by time fashion.
    :param max_datetime: The maximum datetime value we wish to expand to.
    :return: A sorted list on datetime containing tuples of datetime and offset period where the datetime is
    lower than *max_datetime*.
    """
    if max_datetime in self.__storage_of_results.keys():
        return self.__storage_of_results[max_datetime]
    all_timezones: List[Tuple[Union[DateTime, Date], _TimeOffsetPeriod]] = []
    for a_standard in self.standardc:
        all_timezones.extend(a_standard.get_time_sequence(max_datetime=max_datetime))
    for a_daylight in self.daylightc:
        all_timezones.extend(a_daylight.get_time_sequence(max_datetime=max_datetime))
    sorted_list = sorted(all_timezones, key=lambda tup: tup[0])
    self.__storage_of_results[max_datetime] = sorted_list
    return sorted_list

get_ordered_timezone_overview_as_transition(max_datetime)

Get timezone components as a list of pendulum Transitions.

Parameters:

Name Type Description Default
max_datetime DateTime

The maximum datetime for which we include transitions. Any transitions after are excluded.

required

Returns:

Type Description
List[Transition]

Return the list of pendulum Transitions for this VTimezone.

Source code in ical_library/ical_components/v_timezone.py
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
def get_ordered_timezone_overview_as_transition(self, max_datetime: DateTime) -> List[Transition]:
    """
    Get timezone components as a list of pendulum Transitions.
    :param max_datetime: The maximum datetime for which we include transitions. Any transitions after are excluded.
    :return: Return the list of pendulum Transitions for this VTimezone.
    """
    timezones: List[Tuple[DateTime, _TimeOffsetPeriod]] = self.get_ordered_timezone_overview(max_datetime)
    transitions: List[Transition] = []
    previous_transition: Optional[Transition] = None
    for time, offset_period in timezones:
        new_transition_type = TransitionType(
            offset=offset_period.tzoffsetto.parse_value_as_seconds(),
            is_dst=offset_period.is_dst,
            abbr=offset_period.tzname[0].value if offset_period.tzname else "unknown",
        )
        at = int(time.in_tz("UTC").timestamp())
        new_transition = Transition(at=at, ttype=new_transition_type, previous=previous_transition)
        previous_transition = new_transition
        transitions.append(new_transition)
    return transitions

_TimeOffsetPeriod

Bases: Component

A _TimeOffsetPeriod representing either a Standard configuration or a Winter configuration.

Parameters:

Name Type Description Default
name str

The actual name of this component instance. E.g. VEVENT, RRULE, VCUSTOMCOMPONENT.

required
dtstart Optional[DTStart]

The DTStart property. Required and must occur exactly once.

None
tzoffsetto Optional[TZOffsetTo]

The TZOffsetTo property. Required and must occur exactly once.

None
tzoffsetfrom Optional[TZOffsetFrom]

The TZOffsetFrom property. Required and must occur exactly once.

None
rrule Optional[RRule]

The RRule property. Optional, but may occur at most once.

None
comment Optional[List[Comment]]

The Comment property. Optional, but may occur multiple times.

None
rdate Optional[List[RDate]]

The RDate property. Optional, but may occur multiple times.

None
tzname Optional[List[TZName]]

The TZName property. Optional, but may occur multiple times.

None
parent Optional[Component]

The Component this item is encapsulated by in the iCalendar data file.

None
Source code in ical_library/ical_components/v_timezone.py
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
class _TimeOffsetPeriod(Component):
    """
    A _TimeOffsetPeriod representing either a Standard configuration or a Winter configuration.

    :param name: The actual name of this component instance. E.g. VEVENT, RRULE, VCUSTOMCOMPONENT.
    :param dtstart: The DTStart property. Required and must occur exactly once.
    :param tzoffsetto: The TZOffsetTo property. Required and must occur exactly once.
    :param tzoffsetfrom: The TZOffsetFrom property. Required and must occur exactly once.
    :param rrule: The RRule property. Optional, but may occur at most once.
    :param comment: The Comment property. Optional, but may occur multiple times.
    :param rdate: The RDate property. Optional, but may occur multiple times.
    :param tzname: The TZName property. Optional, but may occur multiple times.
    :param parent: The Component this item is encapsulated by in the iCalendar data file.
    """

    def __init__(
        self,
        name: str,
        dtstart: Optional[DTStart] = None,
        tzoffsetto: Optional[TZOffsetTo] = None,
        tzoffsetfrom: Optional[TZOffsetFrom] = None,
        rrule: Optional[RRule] = None,
        comment: Optional[List[Comment]] = None,
        rdate: Optional[List[RDate]] = None,
        tzname: Optional[List[TZName]] = None,
        parent: Optional[Component] = None,
        is_dst: bool = False,
    ):
        super().__init__(name, parent=parent)
        # Required, must occur only once.
        self.dtstart: Optional[DTStart] = self.as_parent(dtstart)
        self.tzoffsetto: Optional[TZOffsetTo] = self.as_parent(tzoffsetto)
        self.tzoffsetfrom: Optional[TZOffsetFrom] = self.as_parent(tzoffsetfrom)
        # Optional, may only occur once.
        self.rrule: Optional[RRule] = self.as_parent(rrule)
        # Optional, may occur more than once.
        self.comment: Optional[List[Comment]] = self.as_parent(comment)
        self.rdate: Optional[List[RDate]] = self.as_parent(rdate)
        self.tzname: Optional[List[TZName]] = self.as_parent(tzname)
        self.is_dst = is_dst

    def __repr__(self) -> str:
        """Overwrite the repr to create a better representation for the item."""
        return f"{self.__class__.__name__}({self.dtstart.value}: {self.tzoffsetto.value})"

    def timezone_aware_start(self) -> DateTime:
        """Return a timezone aware start."""
        dt: DateTime = dt_utils.convert_time_object_to_datetime(self.dtstart.datetime_or_date_value)
        return dt.in_timezone(tz=self.tzoffsetfrom.as_timezone_object())

    def get_time_sequence(
        self, max_datetime: Optional[DateTime] = None
    ) -> Iterator[Tuple[DateTime, "_TimeOffsetPeriod"]]:
        """
        Expand the TimeZone start date according to its recurring *RDate* and *RRule* properties.
        :param max_datetime: The maximum datetime value we wish to expand to.
        :return: Yield all the datetime values according to the recurring properties that are lower than *max_datetime*.
        """
        for rtime in property_utils.expand_event_in_range_only_return_first(
            rdate_list=self.rdate or [],
            rrule=self.rrule,
            first_event_start=self.timezone_aware_start(),
            return_range=Timespan(self.timezone_aware_start() - timedelta(days=1), max_datetime),
            make_tz_aware=self.tzoffsetfrom.as_timezone_object(),
        ):
            if not isinstance(rtime, DateTime):
                raise TypeError(f"{rtime} was expected to be a DateTime object.")
            yield rtime, self

get_time_sequence(max_datetime=None)

Expand the TimeZone start date according to its recurring RDate and RRule properties.

Parameters:

Name Type Description Default
max_datetime Optional[DateTime]

The maximum datetime value we wish to expand to.

None

Returns:

Type Description
Iterator[Tuple[DateTime, _TimeOffsetPeriod]]

Yield all the datetime values according to the recurring properties that are lower than max_datetime.

Source code in ical_library/ical_components/v_timezone.py
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
def get_time_sequence(
    self, max_datetime: Optional[DateTime] = None
) -> Iterator[Tuple[DateTime, "_TimeOffsetPeriod"]]:
    """
    Expand the TimeZone start date according to its recurring *RDate* and *RRule* properties.
    :param max_datetime: The maximum datetime value we wish to expand to.
    :return: Yield all the datetime values according to the recurring properties that are lower than *max_datetime*.
    """
    for rtime in property_utils.expand_event_in_range_only_return_first(
        rdate_list=self.rdate or [],
        rrule=self.rrule,
        first_event_start=self.timezone_aware_start(),
        return_range=Timespan(self.timezone_aware_start() - timedelta(days=1), max_datetime),
        make_tz_aware=self.tzoffsetfrom.as_timezone_object(),
    ):
        if not isinstance(rtime, DateTime):
            raise TypeError(f"{rtime} was expected to be a DateTime object.")
        yield rtime, self

timezone_aware_start()

Return a timezone aware start.

Source code in ical_library/ical_components/v_timezone.py
66
67
68
69
def timezone_aware_start(self) -> DateTime:
    """Return a timezone aware start."""
    dt: DateTime = dt_utils.convert_time_object_to_datetime(self.dtstart.datetime_or_date_value)
    return dt.in_timezone(tz=self.tzoffsetfrom.as_timezone_object())

DayLight

Bases: _TimeOffsetPeriod

A TimeOffsetPeriod representing a DayLight(a.k.a. Advanced Time, Summer Time or Legal Time) configuration.

Source code in ical_library/ical_components/v_timezone.py
91
92
93
94
95
96
97
98
99
class DayLight(_TimeOffsetPeriod):
    """A TimeOffsetPeriod representing a DayLight(a.k.a. Advanced Time, Summer Time or Legal Time) configuration."""

    def __init__(self, parent: Optional[Component] = None, **kwargs):
        super().__init__("DAYLIGHT", parent=parent, is_dst=True, **kwargs)

    @classmethod
    def _get_init_method_for_var_mapping(cls) -> Callable:
        return _TimeOffsetPeriod.__init__

Standard

Bases: _TimeOffsetPeriod

A TimeOffsetPeriod representing a Standard(a.k.a. Winter Time) configuration.

Source code in ical_library/ical_components/v_timezone.py
102
103
104
105
106
107
108
109
110
class Standard(_TimeOffsetPeriod):
    """A TimeOffsetPeriod representing a Standard(a.k.a. Winter Time) configuration."""

    def __init__(self, parent: Optional[Component] = None, **kwargs):
        super().__init__("STANDARD", parent=parent, is_dst=False, **kwargs)

    @classmethod
    def _get_init_method_for_var_mapping(cls) -> Callable:
        return _TimeOffsetPeriod.__init__