_common.py (5530B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\dateutil\tz\_common.py 2 from six import PY3 3 from datetime import datetime, timedelta, tzinfo 4 import copy 5 ZERO = timedelta(0) 6 __all__ = ['tzname_in_python2', 'enfold'] 7 8 def tzname_in_python2(namefunc): 9 10 def adjust_encoding(*args, **kwargs): 11 name = namefunc(*args, **kwargs) 12 if name is not None and not PY3: 13 name = name.encode() 14 return name 15 16 return adjust_encoding 17 18 19 if hasattr(datetime, 'fold'): 20 21 def enfold(dt, fold = 1): 22 return dt.replace(fold=fold) 23 24 25 else: 26 27 class _DatetimeWithFold(datetime): 28 __slots__ = () 29 30 @property 31 def fold(self): 32 return 1 33 34 35 def enfold(dt, fold = 1): 36 if getattr(dt, 'fold', 0) == fold: 37 return dt 38 args = dt.timetuple()[:6] 39 args += (dt.microsecond, dt.tzinfo) 40 if fold: 41 return _DatetimeWithFold(*args) 42 else: 43 return datetime(*args) 44 45 46 class _tzinfo(tzinfo): 47 48 def is_ambiguous(self, dt): 49 dt = dt.replace(tzinfo=self) 50 wall_0 = enfold(dt, fold=0) 51 wall_1 = enfold(dt, fold=1) 52 same_offset = wall_0.utcoffset() == wall_1.utcoffset() 53 same_dt = wall_0.replace(tzinfo=None) == wall_1.replace(tzinfo=None) 54 return same_dt and not same_offset 55 56 def _fold_status(self, dt_utc, dt_wall): 57 if self.is_ambiguous(dt_wall): 58 delta_wall = dt_wall - dt_utc 59 _fold = int(delta_wall == dt_utc.utcoffset() - dt_utc.dst()) 60 else: 61 _fold = 0 62 return _fold 63 64 def _fold(self, dt): 65 return getattr(dt, 'fold', 0) 66 67 def _fromutc(self, dt): 68 if not isinstance(dt, datetime): 69 raise TypeError('fromutc() requires a datetime argument') 70 if dt.tzinfo is not self: 71 raise ValueError('dt.tzinfo is not self') 72 dtoff = dt.utcoffset() 73 if dtoff is None: 74 raise ValueError('fromutc() requires a non-None utcoffset() result') 75 dtdst = dt.dst() 76 if dtdst is None: 77 raise ValueError('fromutc() requires a non-None dst() result') 78 delta = dtoff - dtdst 79 if delta: 80 dt += delta 81 dtdst = enfold(dt, fold=1).dst() 82 if dtdst is None: 83 raise ValueError('fromutc(): dt.dst gave inconsistent results; cannot convert') 84 return dt + dtdst 85 86 def fromutc(self, dt): 87 dt_wall = self._fromutc(dt) 88 _fold = self._fold_status(dt, dt_wall) 89 return enfold(dt_wall, fold=_fold) 90 91 92 class tzrangebase(_tzinfo): 93 94 def __init__(self): 95 raise NotImplementedError('tzrangebase is an abstract base class') 96 97 def utcoffset(self, dt): 98 isdst = self._isdst(dt) 99 if isdst is None: 100 return 101 elif isdst: 102 return self._dst_offset 103 else: 104 return self._std_offset 105 106 def dst(self, dt): 107 isdst = self._isdst(dt) 108 if isdst is None: 109 return 110 elif isdst: 111 return self._dst_base_offset 112 else: 113 return ZERO 114 115 @tzname_in_python2 116 def tzname(self, dt): 117 if self._isdst(dt): 118 return self._dst_abbr 119 else: 120 return self._std_abbr 121 122 def fromutc(self, dt): 123 if not isinstance(dt, datetime): 124 raise TypeError('fromutc() requires a datetime argument') 125 if dt.tzinfo is not self: 126 raise ValueError('dt.tzinfo is not self') 127 transitions = self.transitions(dt.year) 128 if transitions is None: 129 return dt + self.utcoffset(dt) 130 dston, dstoff = transitions 131 dston -= self._std_offset 132 dstoff -= self._std_offset 133 utc_transitions = (dston, dstoff) 134 dt_utc = dt.replace(tzinfo=None) 135 isdst = self._naive_isdst(dt_utc, utc_transitions) 136 if isdst: 137 dt_wall = dt + self._dst_offset 138 else: 139 dt_wall = dt + self._std_offset 140 _fold = int(not isdst and self.is_ambiguous(dt_wall)) 141 return enfold(dt_wall, fold=_fold) 142 143 def is_ambiguous(self, dt): 144 if not self.hasdst: 145 return False 146 start, end = self.transitions(dt.year) 147 dt = dt.replace(tzinfo=None) 148 return end <= dt < end + self._dst_base_offset 149 150 def _isdst(self, dt): 151 if not self.hasdst: 152 return False 153 elif dt is None: 154 return 155 transitions = self.transitions(dt.year) 156 if transitions is None: 157 return False 158 dt = dt.replace(tzinfo=None) 159 isdst = self._naive_isdst(dt, transitions) 160 if not isdst and self.is_ambiguous(dt): 161 return not self._fold(dt) 162 else: 163 return isdst 164 165 def _naive_isdst(self, dt, transitions): 166 dston, dstoff = transitions 167 dt = dt.replace(tzinfo=None) 168 if dston < dstoff: 169 isdst = dston <= dt < dstoff 170 else: 171 isdst = not dstoff <= dt < dston 172 return isdst 173 174 @property 175 def _dst_base_offset(self): 176 return self._dst_offset - self._std_offset 177 178 __hash__ = None 179 180 def __ne__(self, other): 181 return not self == other 182 183 def __repr__(self): 184 return '%s(...)' % self.__class__.__name__ 185 186 __reduce__ = object.__reduce__ 187 188 189 def _total_seconds(td): 190 return ((td.seconds + td.days * 86400) * 1000000 + td.microseconds) // 1000000 191 192 193 _total_seconds = getattr(timedelta, 'total_seconds', _total_seconds)