| 2032 | |
| 2033 | @dataclasses.dataclass(frozen=True) |
| 2034 | class ZoneTransition: |
| 2035 | transition: datetime |
| 2036 | offset_before: ZoneOffset |
| 2037 | offset_after: ZoneOffset |
| 2038 | |
| 2039 | @property |
| 2040 | def transition_utc(self): |
| 2041 | return (self.transition - self.offset_before.utcoffset).replace( |
| 2042 | tzinfo=timezone.utc |
| 2043 | ) |
| 2044 | |
| 2045 | @property |
| 2046 | def fold(self): |
| 2047 | """Whether this introduces a fold""" |
| 2048 | return self.offset_before.utcoffset > self.offset_after.utcoffset |
| 2049 | |
| 2050 | @property |
| 2051 | def gap(self): |
| 2052 | """Whether this introduces a gap""" |
| 2053 | return self.offset_before.utcoffset < self.offset_after.utcoffset |
| 2054 | |
| 2055 | @property |
| 2056 | def delta(self): |
| 2057 | return self.offset_after.utcoffset - self.offset_before.utcoffset |
| 2058 | |
| 2059 | @property |
| 2060 | def anomaly_start(self): |
| 2061 | if self.fold: |
| 2062 | return self.transition + self.delta |
| 2063 | else: |
| 2064 | return self.transition |
| 2065 | |
| 2066 | @property |
| 2067 | def anomaly_end(self): |
| 2068 | if not self.fold: |
| 2069 | return self.transition + self.delta |
| 2070 | else: |
| 2071 | return self.transition |
| 2072 | |
| 2073 | |
| 2074 | class ZoneInfoData: |
no outgoing calls