|
16 | 16 | from re import compile as re_compile |
17 | 17 | from re import IGNORECASE, ASCII |
18 | 18 | from re import escape as re_escape |
19 | | -from datetime import date as datetime_date |
| 19 | +from datetime import (date as datetime_date, |
| 20 | + datetime as datetime_datetime, |
| 21 | + timedelta as datetime_timedelta, |
| 22 | + timezone as datetime_timezone) |
20 | 23 | try: |
21 | 24 | from _thread import allocate_lock as _thread_allocate_lock |
22 | 25 | except: |
@@ -204,6 +207,7 @@ def __init__(self, locale_time=None): |
204 | 207 | #XXX: Does 'Y' need to worry about having less or more than |
205 | 208 | # 4 digits? |
206 | 209 | 'Y': r"(?P<Y>\d\d\d\d)", |
| 210 | + 'z': r"(?P<z>[+-]\d\d[0-5]\d)", |
207 | 211 | 'A': self.__seqToRE(self.locale_time.f_weekday, 'A'), |
208 | 212 | 'a': self.__seqToRE(self.locale_time.a_weekday, 'a'), |
209 | 213 | 'B': self.__seqToRE(self.locale_time.f_month[1:], 'B'), |
@@ -293,7 +297,9 @@ def _calc_julian_from_U_or_W(year, week_of_year, day_of_week, week_starts_Mon): |
293 | 297 |
|
294 | 298 |
|
295 | 299 | def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"): |
296 | | - """Return a time struct based on the input string and the format string.""" |
| 300 | + """Return a 2-tuple consisting of a time struct and an int containg |
| 301 | + the number of microseconds based on the input string and the |
| 302 | + format string.""" |
297 | 303 |
|
298 | 304 | for index, arg in enumerate([data_string, format]): |
299 | 305 | if not isinstance(arg, str): |
@@ -333,10 +339,12 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"): |
333 | 339 | if len(data_string) != found.end(): |
334 | 340 | raise ValueError("unconverted data remains: %s" % |
335 | 341 | data_string[found.end():]) |
| 342 | + |
336 | 343 | year = 1900 |
337 | 344 | month = day = 1 |
338 | 345 | hour = minute = second = fraction = 0 |
339 | 346 | tz = -1 |
| 347 | + tzoffset = None |
340 | 348 | # Default to -1 to signify that values not known; not critical to have, |
341 | 349 | # though |
342 | 350 | week_of_year = -1 |
@@ -417,6 +425,11 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"): |
417 | 425 | else: |
418 | 426 | # W starts week on Monday. |
419 | 427 | week_of_year_start = 0 |
| 428 | + elif group_key == 'z': |
| 429 | + z = found_dict['z'] |
| 430 | + tzoffset = int(z[1:3]) * 60 + int(z[3:5]) |
| 431 | + if z.startswith("-"): |
| 432 | + tzoffset = -tzoffset |
420 | 433 | elif group_key == 'Z': |
421 | 434 | # Since -1 is default value only need to worry about setting tz if |
422 | 435 | # it can be something other than -1. |
@@ -453,9 +466,35 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"): |
453 | 466 | day = datetime_result.day |
454 | 467 | if weekday == -1: |
455 | 468 | weekday = datetime_date(year, month, day).weekday() |
456 | | - return (time.struct_time((year, month, day, |
457 | | - hour, minute, second, |
458 | | - weekday, julian, tz)), fraction) |
| 469 | + # Add timezone info |
| 470 | + tzname = found_dict.get("Z") |
| 471 | + if tzoffset is not None: |
| 472 | + gmtoff = tzoffset * 60 |
| 473 | + else: |
| 474 | + gmtoff = None |
| 475 | + |
| 476 | + return (year, month, day, |
| 477 | + hour, minute, second, |
| 478 | + weekday, julian, tz, gmtoff, tzname), fraction |
459 | 479 |
|
460 | 480 | def _strptime_time(data_string, format="%a %b %d %H:%M:%S %Y"): |
461 | | - return _strptime(data_string, format)[0] |
| 481 | + """Return a time struct based on the input string and the |
| 482 | + format string.""" |
| 483 | + tt = _strptime(data_string, format)[0] |
| 484 | + return time.struct_time(tt[:9]) |
| 485 | + |
| 486 | +def _strptime_datetime(data_string, format="%a %b %d %H:%M:%S %Y"): |
| 487 | + """Return a datetime instace based on the input string and the |
| 488 | + format string.""" |
| 489 | + tt, fraction = _strptime(data_string, format) |
| 490 | + gmtoff, tzname = tt[-2:] |
| 491 | + args = tt[:6] + (fraction,) |
| 492 | + if gmtoff is not None: |
| 493 | + tzdelta = datetime_timedelta(seconds=gmtoff) |
| 494 | + if tzname: |
| 495 | + tz = datetime_timezone(tzdelta, tzname) |
| 496 | + else: |
| 497 | + tz = datetime_timezone(tzdelta) |
| 498 | + args += (tz,) |
| 499 | + |
| 500 | + return datetime_datetime(*args) |
0 commit comments