Mercurial > repos > rliterman > csp2
comparison CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/site-packages/pytz/tzfile.py @ 69:33d812a61356
planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author | jpayne |
---|---|
date | Tue, 18 Mar 2025 17:55:14 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
67:0e9998148a16 | 69:33d812a61356 |
---|---|
1 ''' | |
2 $Id: tzfile.py,v 1.8 2004/06/03 00:15:24 zenzen Exp $ | |
3 ''' | |
4 | |
5 from datetime import datetime | |
6 from struct import unpack, calcsize | |
7 | |
8 from pytz.tzinfo import StaticTzInfo, DstTzInfo, memorized_ttinfo | |
9 from pytz.tzinfo import memorized_datetime, memorized_timedelta | |
10 | |
11 | |
12 def _byte_string(s): | |
13 """Cast a string or byte string to an ASCII byte string.""" | |
14 return s.encode('ASCII') | |
15 | |
16 _NULL = _byte_string('\0') | |
17 | |
18 | |
19 def _std_string(s): | |
20 """Cast a string or byte string to an ASCII string.""" | |
21 return str(s.decode('ASCII')) | |
22 | |
23 | |
24 def build_tzinfo(zone, fp): | |
25 head_fmt = '>4s c 15x 6l' | |
26 head_size = calcsize(head_fmt) | |
27 (magic, format, ttisgmtcnt, ttisstdcnt, leapcnt, timecnt, | |
28 typecnt, charcnt) = unpack(head_fmt, fp.read(head_size)) | |
29 | |
30 # Make sure it is a tzfile(5) file | |
31 assert magic == _byte_string('TZif'), 'Got magic %s' % repr(magic) | |
32 | |
33 # Read out the transition times, localtime indices and ttinfo structures. | |
34 data_fmt = '>%(timecnt)dl %(timecnt)dB %(ttinfo)s %(charcnt)ds' % dict( | |
35 timecnt=timecnt, ttinfo='lBB' * typecnt, charcnt=charcnt) | |
36 data_size = calcsize(data_fmt) | |
37 data = unpack(data_fmt, fp.read(data_size)) | |
38 | |
39 # make sure we unpacked the right number of values | |
40 assert len(data) == 2 * timecnt + 3 * typecnt + 1 | |
41 transitions = [memorized_datetime(trans) | |
42 for trans in data[:timecnt]] | |
43 lindexes = list(data[timecnt:2 * timecnt]) | |
44 ttinfo_raw = data[2 * timecnt:-1] | |
45 tznames_raw = data[-1] | |
46 del data | |
47 | |
48 # Process ttinfo into separate structs | |
49 ttinfo = [] | |
50 tznames = {} | |
51 i = 0 | |
52 while i < len(ttinfo_raw): | |
53 # have we looked up this timezone name yet? | |
54 tzname_offset = ttinfo_raw[i + 2] | |
55 if tzname_offset not in tznames: | |
56 nul = tznames_raw.find(_NULL, tzname_offset) | |
57 if nul < 0: | |
58 nul = len(tznames_raw) | |
59 tznames[tzname_offset] = _std_string( | |
60 tznames_raw[tzname_offset:nul]) | |
61 ttinfo.append((ttinfo_raw[i], | |
62 bool(ttinfo_raw[i + 1]), | |
63 tznames[tzname_offset])) | |
64 i += 3 | |
65 | |
66 # Now build the timezone object | |
67 if len(ttinfo) == 1 or len(transitions) == 0: | |
68 ttinfo[0][0], ttinfo[0][2] | |
69 cls = type(zone, (StaticTzInfo,), dict( | |
70 zone=zone, | |
71 _utcoffset=memorized_timedelta(ttinfo[0][0]), | |
72 _tzname=ttinfo[0][2])) | |
73 else: | |
74 # Early dates use the first standard time ttinfo | |
75 i = 0 | |
76 while ttinfo[i][1]: | |
77 i += 1 | |
78 if ttinfo[i] == ttinfo[lindexes[0]]: | |
79 transitions[0] = datetime.min | |
80 else: | |
81 transitions.insert(0, datetime.min) | |
82 lindexes.insert(0, i) | |
83 | |
84 # calculate transition info | |
85 transition_info = [] | |
86 for i in range(len(transitions)): | |
87 inf = ttinfo[lindexes[i]] | |
88 utcoffset = inf[0] | |
89 if not inf[1]: | |
90 dst = 0 | |
91 else: | |
92 for j in range(i - 1, -1, -1): | |
93 prev_inf = ttinfo[lindexes[j]] | |
94 if not prev_inf[1]: | |
95 break | |
96 dst = inf[0] - prev_inf[0] # dst offset | |
97 | |
98 # Bad dst? Look further. DST > 24 hours happens when | |
99 # a timzone has moved across the international dateline. | |
100 if dst <= 0 or dst > 3600 * 3: | |
101 for j in range(i + 1, len(transitions)): | |
102 stdinf = ttinfo[lindexes[j]] | |
103 if not stdinf[1]: | |
104 dst = inf[0] - stdinf[0] | |
105 if dst > 0: | |
106 break # Found a useful std time. | |
107 | |
108 tzname = inf[2] | |
109 | |
110 # Round utcoffset and dst to the nearest minute or the | |
111 # datetime library will complain. Conversions to these timezones | |
112 # might be up to plus or minus 30 seconds out, but it is | |
113 # the best we can do. | |
114 utcoffset = int((utcoffset + 30) // 60) * 60 | |
115 dst = int((dst + 30) // 60) * 60 | |
116 transition_info.append(memorized_ttinfo(utcoffset, dst, tzname)) | |
117 | |
118 cls = type(zone, (DstTzInfo,), dict( | |
119 zone=zone, | |
120 _utc_transition_times=transitions, | |
121 _transition_info=transition_info)) | |
122 | |
123 return cls() | |
124 | |
125 if __name__ == '__main__': | |
126 import os.path | |
127 from pprint import pprint | |
128 base = os.path.join(os.path.dirname(__file__), 'zoneinfo') | |
129 tz = build_tzinfo('Australia/Melbourne', | |
130 open(os.path.join(base, 'Australia', 'Melbourne'), 'rb')) | |
131 tz = build_tzinfo('US/Eastern', | |
132 open(os.path.join(base, 'US', 'Eastern'), 'rb')) | |
133 pprint(tz._utc_transition_times) |