equal
deleted
inserted
replaced
15 from .. import ( |
15 from .. import ( |
16 encoding, |
16 encoding, |
17 error, |
17 error, |
18 pycompat, |
18 pycompat, |
19 ) |
19 ) |
|
20 |
|
21 if pycompat.TYPE_CHECKING: |
|
22 from typing import ( |
|
23 Callable, |
|
24 Dict, |
|
25 Iterable, |
|
26 Optional, |
|
27 Tuple, |
|
28 Union, |
|
29 ) |
|
30 |
|
31 hgdate = Tuple[float, int] # (unixtime, offset) |
20 |
32 |
21 # used by parsedate |
33 # used by parsedate |
22 defaultdateformats = ( |
34 defaultdateformats = ( |
23 b'%Y-%m-%dT%H:%M:%S', # the 'real' ISO8601 |
35 b'%Y-%m-%dT%H:%M:%S', # the 'real' ISO8601 |
24 b'%Y-%m-%dT%H:%M', # without seconds |
36 b'%Y-%m-%dT%H:%M', # without seconds |
60 b"%b %Y", |
72 b"%b %Y", |
61 ) |
73 ) |
62 |
74 |
63 |
75 |
64 def makedate(timestamp=None): |
76 def makedate(timestamp=None): |
|
77 # type: (Optional[float]) -> hgdate |
65 """Return a unix timestamp (or the current time) as a (unixtime, |
78 """Return a unix timestamp (or the current time) as a (unixtime, |
66 offset) tuple based off the local timezone.""" |
79 offset) tuple based off the local timezone.""" |
67 if timestamp is None: |
80 if timestamp is None: |
68 timestamp = time.time() |
81 timestamp = time.time() |
69 if timestamp < 0: |
82 if timestamp < 0: |
77 tz = delta.days * 86400 + delta.seconds |
90 tz = delta.days * 86400 + delta.seconds |
78 return timestamp, tz |
91 return timestamp, tz |
79 |
92 |
80 |
93 |
81 def datestr(date=None, format=b'%a %b %d %H:%M:%S %Y %1%2'): |
94 def datestr(date=None, format=b'%a %b %d %H:%M:%S %Y %1%2'): |
|
95 # type: (Optional[hgdate], bytes) -> bytes |
82 """represent a (unixtime, offset) tuple as a localized time. |
96 """represent a (unixtime, offset) tuple as a localized time. |
83 unixtime is seconds since the epoch, and offset is the time zone's |
97 unixtime is seconds since the epoch, and offset is the time zone's |
84 number of seconds away from UTC. |
98 number of seconds away from UTC. |
85 |
99 |
86 >>> datestr((0, 0)) |
100 >>> datestr((0, 0)) |
114 s = encoding.strtolocal(t.strftime(encoding.strfromlocal(format))) |
128 s = encoding.strtolocal(t.strftime(encoding.strfromlocal(format))) |
115 return s |
129 return s |
116 |
130 |
117 |
131 |
118 def shortdate(date=None): |
132 def shortdate(date=None): |
|
133 # type: (Optional[hgdate]) -> bytes |
119 """turn (timestamp, tzoff) tuple into iso 8631 date.""" |
134 """turn (timestamp, tzoff) tuple into iso 8631 date.""" |
120 return datestr(date, format=b'%Y-%m-%d') |
135 return datestr(date, format=b'%Y-%m-%d') |
121 |
136 |
122 |
137 |
123 def parsetimezone(s): |
138 def parsetimezone(s): |
|
139 # type: (bytes) -> Tuple[Optional[int], bytes] |
124 """find a trailing timezone, if any, in string, and return a |
140 """find a trailing timezone, if any, in string, and return a |
125 (offset, remainder) pair""" |
141 (offset, remainder) pair""" |
126 s = pycompat.bytestr(s) |
142 s = pycompat.bytestr(s) |
127 |
143 |
128 if s.endswith(b"GMT") or s.endswith(b"UTC"): |
144 if s.endswith(b"GMT") or s.endswith(b"UTC"): |
154 |
170 |
155 return None, s |
171 return None, s |
156 |
172 |
157 |
173 |
158 def strdate(string, format, defaults=None): |
174 def strdate(string, format, defaults=None): |
|
175 # type: (bytes, bytes, Optional[Dict[bytes, Tuple[bytes, bytes]]]) -> hgdate |
159 """parse a localized time string and return a (unixtime, offset) tuple. |
176 """parse a localized time string and return a (unixtime, offset) tuple. |
160 if the string cannot be parsed, ValueError is raised.""" |
177 if the string cannot be parsed, ValueError is raised.""" |
161 if defaults is None: |
178 if defaults is None: |
162 defaults = {} |
179 defaults = {} |
163 |
180 |
196 unixtime = localunixtime + offset |
213 unixtime = localunixtime + offset |
197 return unixtime, offset |
214 return unixtime, offset |
198 |
215 |
199 |
216 |
200 def parsedate(date, formats=None, bias=None): |
217 def parsedate(date, formats=None, bias=None): |
|
218 # type: (Union[bytes, hgdate], Optional[Iterable[bytes]], Optional[Dict[bytes, bytes]]) -> hgdate |
201 """parse a localized date/time and return a (unixtime, offset) tuple. |
219 """parse a localized date/time and return a (unixtime, offset) tuple. |
202 |
220 |
203 The date may be a "unixtime offset" string or in one of the specified |
221 The date may be a "unixtime offset" string or in one of the specified |
204 formats. If the date already is a (unixtime, offset) tuple, it is returned. |
222 formats. If the date already is a (unixtime, offset) tuple, it is returned. |
205 |
223 |
221 """ |
239 """ |
222 if bias is None: |
240 if bias is None: |
223 bias = {} |
241 bias = {} |
224 if not date: |
242 if not date: |
225 return 0, 0 |
243 return 0, 0 |
226 if isinstance(date, tuple) and len(date) == 2: |
244 if isinstance(date, tuple): |
227 return date |
245 if len(date) == 2: |
|
246 return date |
|
247 else: |
|
248 raise error.ProgrammingError(b"invalid date format") |
228 if not formats: |
249 if not formats: |
229 formats = defaultdateformats |
250 formats = defaultdateformats |
230 date = date.strip() |
251 date = date.strip() |
231 |
252 |
232 if date == b'now' or date == _(b'now'): |
253 if date == b'now' or date == _(b'now'): |
282 raise error.ParseError(_(b'impossible time zone offset: %d') % offset) |
303 raise error.ParseError(_(b'impossible time zone offset: %d') % offset) |
283 return when, offset |
304 return when, offset |
284 |
305 |
285 |
306 |
286 def matchdate(date): |
307 def matchdate(date): |
|
308 # type: (bytes) -> Callable[[float], bool] |
287 """Return a function that matches a given date match specifier |
309 """Return a function that matches a given date match specifier |
288 |
310 |
289 Formats include: |
311 Formats include: |
290 |
312 |
291 '{date}' match a given date to the accuracy provided |
313 '{date}' match a given date to the accuracy provided |
311 >>> f(p5[0]) |
333 >>> f(p5[0]) |
312 False |
334 False |
313 """ |
335 """ |
314 |
336 |
315 def lower(date): |
337 def lower(date): |
|
338 # type: (bytes) -> float |
316 d = {b'mb': b"1", b'd': b"1"} |
339 d = {b'mb': b"1", b'd': b"1"} |
317 return parsedate(date, extendeddateformats, d)[0] |
340 return parsedate(date, extendeddateformats, d)[0] |
318 |
341 |
319 def upper(date): |
342 def upper(date): |
|
343 # type: (bytes) -> float |
320 d = {b'mb': b"12", b'HI': b"23", b'M': b"59", b'S': b"59"} |
344 d = {b'mb': b"12", b'HI': b"23", b'M': b"59", b'S': b"59"} |
321 for days in (b"31", b"30", b"29"): |
345 for days in (b"31", b"30", b"29"): |
322 try: |
346 try: |
323 d[b"d"] = days |
347 d[b"d"] = days |
324 return parsedate(date, extendeddateformats, d)[0] |
348 return parsedate(date, extendeddateformats, d)[0] |