Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(8)

Side by Side Diff: Lib/datetime.py

Issue 15873: "datetime" cannot parse ISO 8601 dates and times
Patch Set: Created 3 years, 8 months ago
 Left: Base Patch Set 1: None Patch Set 2: None Patch Set 3: None Patch Set 4: None Patch Set 5: None Patch Set 6: None Patch Set 7: None Patch Set 8: None Patch Set 9: None Patch Set 10: None Patch Set 11: None Patch Set 12: None Right: Patch Set 1: None Patch Set 2: None Patch Set 3: None Patch Set 4: None Patch Set 5: None Patch Set 6: None Patch Set 7: None Patch Set 8: None Patch Set 9: None Patch Set 10: None Patch Set 11: None Patch Set 12: None
« no previous file with comments | « no previous file | Lib/test/datetimetester.py » ('j') | no next file with comments »
OLDNEW
1 """Concrete date/time and related types. 1 """Concrete date/time and related types.
2 2
4 time zone and DST data sources. 4 time zone and DST data sources.
5 """ 5 """
6 6
7 import time as _time 7 import time as _time
8 import math as _math 8 import math as _math
9 import re
9 10
10 def _cmp(x, y): 11 def _cmp(x, y):
11 return 0 if x == y else 1 if x > y else -1 12 return 0 if x == y else 1 if x > y else -1
12 13
13 MINYEAR = 1 14 MINYEAR = 1
14 MAXYEAR = 9999 15 MAXYEAR = 9999
15 _MAXORDINAL = 3652059 # date.max.toordinal() 16 _MAXORDINAL = 3652059 # date.max.toordinal()
16 17
17 # Utility functions, adapted from Python's Demo/classes/Dates.py, which 18 # Utility functions, adapted from Python's Demo/classes/Dates.py, which
18 # also assumes the current Gregorian calendar indefinitely extended in 19 # also assumes the current Gregorian calendar indefinitely extended in
(...skipping 303 matching lines...)
322 q, r = divmod(a, b) 323 q, r = divmod(a, b)
323 # round up if either r / b > 0.5, or r / b == 0.5 and q is odd. 324 # round up if either r / b > 0.5, or r / b == 0.5 and q is odd.
324 # The expression r / b > 0.5 is equivalent to 2 * r > b if b is 325 # The expression r / b > 0.5 is equivalent to 2 * r > b if b is
325 # positive, 2 * r < b if b negative. 326 # positive, 2 * r < b if b negative.
326 r *= 2 327 r *= 2
327 greater_than_half = r > b if b > 0 else r < b 328 greater_than_half = r > b if b > 0 else r < b
328 if greater_than_half or r == b and q % 2 == 1: 329 if greater_than_half or r == b and q % 2 == 1:
329 q += 1 330 q += 1
330 331
331 return q 332 return q
333
334
335 def _parse_isotime(cls, isostring):
336 match = cls._isore.match(isostring)
337 if not match:
338 raise ValueError("invalid RFC 3339 %s string: %r"
339 % (cls.__name__, isostring))
340 kw = match.groupdict()
341 tzinfo = kw.pop('tzinfo', None)
342 if tzinfo == 'Z' or tzinfo == 'z':
343 tzinfo = timezone.utc
344 elif tzinfo is not None:
345 offset_hours, _, offset_mins = tzinfo[1:].partition(':')
346 offset = timedelta(hours=int(offset_hours), minutes=int(offset_mins))
347 if tzinfo[0] == '-':
348 offset = -offset
349 tzinfo = timezone(offset)
350 us = kw.pop('microsecond', None)
351 kw = {k: int(v) for k, v in kw.items()}
352 if us:
353 us = round(float(us), 6)
354 kw['microsecond'] = int(us * 1e6)
355 if tzinfo:
356 kw['tzinfo'] = tzinfo
357 return cls(**kw)
332 358
333 359
334 class timedelta: 360 class timedelta:
335 """Represent the difference between two datetime objects. 361 """Represent the difference between two datetime objects.
336 362
337 Supported operators: 363 Supported operators:
338 364
340 - unary plus, minus, abs 366 - unary plus, minus, abs
341 - compare to timedelta 367 - compare to timedelta
(...skipping 333 matching lines...)
675 toordinal() 701 toordinal()
676 weekday() 702 weekday()
677 isoweekday(), isocalendar(), isoformat() 703 isoweekday(), isocalendar(), isoformat()
678 ctime() 704 ctime()
679 strftime() 705 strftime()
680 706
682 year, month, day 708 year, month, day
683 """ 709 """
684 __slots__ = '_year', '_month', '_day', '_hashcode' 710 __slots__ = '_year', '_month', '_day', '_hashcode'
711
712 _isore = re.compile(r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})\$', re. ASCII)
685 713
686 def __new__(cls, year, month=None, day=None): 714 def __new__(cls, year, month=None, day=None):
687 """Constructor. 715 """Constructor.
688 716
689 Arguments: 717 Arguments:
690 718
691 year, month, day (required, base 1) 719 year, month, day (required, base 1)
692 """ 720 """
693 if month is None and isinstance(year, bytes) and len(year) == 4 and \ 721 if month is None and isinstance(year, bytes) and len(year) == 4 and \
694 1 <= year[2] <= 12: 722 1 <= year[2] <= 12:
(...skipping 26 matching lines...) Expand all
721 749
722 @classmethod 750 @classmethod
723 def fromordinal(cls, n): 751 def fromordinal(cls, n):
724 """Construct a date from a proleptic Gregorian ordinal. 752 """Construct a date from a proleptic Gregorian ordinal.
725 753
726 January 1 of year 1 is day 1. Only the year, month and day are 754 January 1 of year 1 is day 1. Only the year, month and day are
727 non-zero in the result. 755 non-zero in the result.
728 """ 756 """
729 y, m, d = _ord2ymd(n) 757 y, m, d = _ord2ymd(n)
730 return cls(y, m, d) 758 return cls(y, m, d)
759
760 @classmethod
761 def fromisoformat(cls, date_string):
762 """Constructs a date from an RFC 3339 string, a strict subset of ISO 860 1
763
764 Raises ValueError in case of ill-formatted or invalid string.
765 """
766 return _parse_isotime(cls, date_string)
731 767
732 # Conversions to string 768 # Conversions to string
733 769
734 def __repr__(self): 770 def __repr__(self):
735 """Convert to formal string, for repr(). 771 """Convert to formal string, for repr().
736 772
737 >>> dt = datetime(2010, 1, 1) 773 >>> dt = datetime(2010, 1, 1)
738 >>> repr(dt) 774 >>> repr(dt)
739 'datetime.datetime(2010, 1, 1, 0, 0)' 775 'datetime.datetime(2010, 1, 1, 0, 0)'
740 776
(...skipping 269 matching lines...)
1010 if getstate: 1046 if getstate:
1011 state = getstate() 1047 state = getstate()
1012 else: 1048 else:
1013 state = getattr(self, "__dict__", None) or None 1049 state = getattr(self, "__dict__", None) or None
1014 if state is None: 1050 if state is None:
1015 return (self.__class__, args) 1051 return (self.__class__, args)
1016 else: 1052 else:
1017 return (self.__class__, args, state) 1053 return (self.__class__, args, state)
1018 1054
1019 _tzinfo_class = tzinfo 1055 _tzinfo_class = tzinfo
1056
1020 1057
1021 class time: 1058 class time:
1022 """Time with time zone. 1059 """Time with time zone.
1023 1060
1024 Constructors: 1061 Constructors:
1025 1062
1026 __new__() 1063 __new__()
1027 1064
1028 Operators: 1065 Operators:
1029 1066
1030 __repr__, __str__ 1067 __repr__, __str__
1031 __eq__, __le__, __lt__, __ge__, __gt__, __hash__ 1068 __eq__, __le__, __lt__, __ge__, __gt__, __hash__
1032 1069
1033 Methods: 1070 Methods:
1034 1071
1035 strftime() 1072 strftime()
1036 isoformat() 1073 isoformat()
1037 utcoffset() 1074 utcoffset()
1038 tzname() 1075 tzname()
1039 dst() 1076 dst()
1040 1077
1042 hour, minute, second, microsecond, tzinfo, fold 1079 hour, minute, second, microsecond, tzinfo, fold
1043 """ 1080 """
1044 __slots__ = '_hour', '_minute', '_second', '_microsecond', '_tzinfo', '_hash code', '_fold' 1081 __slots__ = '_hour', '_minute', '_second', '_microsecond', '_tzinfo', '_hash code', '_fold'
1082
1083 _isore = re.compile(r'(?P<hour>\d{2}):(?P<minute>\d{2}):(?P<second>\d{2})'
1084 r'(?P<microsecond>\.\d+)?(?P<tzinfo>Z|[+-]\d{2}:\d{2})?\$ ',
1085 re.ASCII|re.IGNORECASE)
1086
1045 1087
1046 def __new__(cls, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0): 1088 def __new__(cls, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0):
1047 """Constructor. 1089 """Constructor.
1048 1090
1049 Arguments: 1091 Arguments:
1050 1092
1051 hour, minute (required) 1093 hour, minute (required)
1052 second, microsecond (default to zero) 1094 second, microsecond (default to zero)
1053 tzinfo (default to None) 1095 tzinfo (default to None)
1054 fold (keyword only, default to True) 1096 fold (keyword only, default to True)
1055 """ 1097 """
1056 if isinstance(hour, bytes) and len(hour) == 6 and hour[0]&0x7F < 24: 1098 if isinstance(hour, bytes) and len(hour) == 6 and hour[0]&0x7F < 24:
1057 # Pickle support 1099 # Pickle support
1058 self = object.__new__(cls) 1100 self = object.__new__(cls)
1059 self.__setstate(hour, minute or None) 1101 self.__setstate(hour, minute or None)
1060 self._hashcode = -1 1102 self._hashcode = -1
1061 return self 1103 return self
1062 hour, minute, second, microsecond = _check_time_fields( 1104 hour, minute, second, microsecond = _check_time_fields(
1063 hour, minute, second, microsecond) 1105 hour, minute, second, microsecond)
1064 _check_tzinfo_arg(tzinfo) 1106 _check_tzinfo_arg(tzinfo)
1065 self = object.__new__(cls) 1107 self = object.__new__(cls)
1066 self._hour = hour 1108 self._hour = hour
1067 self._minute = minute 1109 self._minute = minute
1068 self._second = second 1110 self._second = second
1069 self._microsecond = microsecond 1111 self._microsecond = microsecond
1070 self._tzinfo = tzinfo 1112 self._tzinfo = tzinfo
1071 self._hashcode = -1 1113 self._hashcode = -1
1072 self._fold = fold 1114 self._fold = fold
1073 return self 1115 return self
1116
1117 @classmethod
1118 def fromisoformat(cls, time_string):
1119 """Constructs a time from an RFC 3339 string, a strict subset of ISO 860 1
1120
1121 Microseconds are rounded to 6 digits.
1122 Raises ValueError in case of ill-formatted or invalid string.
1123 """
1124 return _parse_isotime(cls, time_string)
1074 1125
1076 @property 1127 @property
1077 def hour(self): 1128 def hour(self):
1078 """hour (0-23)""" 1129 """hour (0-23)"""
1079 return self._hour 1130 return self._hour
1080 1131
1081 @property 1132 @property
1082 def minute(self): 1133 def minute(self):
1083 """minute (0-59)""" 1134 """minute (0-59)"""
(...skipping 268 matching lines...)
1352 time.max = time(23, 59, 59, 999999) 1403 time.max = time(23, 59, 59, 999999)
1353 time.resolution = timedelta(microseconds=1) 1404 time.resolution = timedelta(microseconds=1)
1354 1405
1355 class datetime(date): 1406 class datetime(date):
1356 """datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo] ]]]]) 1407 """datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo] ]]]])
1357 1408
1358 The year, month and day arguments are required. tzinfo may be None, or an 1409 The year, month and day arguments are required. tzinfo may be None, or an
1359 instance of a tzinfo subclass. The remaining arguments may be ints. 1410 instance of a tzinfo subclass. The remaining arguments may be ints.
1360 """ 1411 """
1361 __slots__ = date.__slots__ + time.__slots__ 1412 __slots__ = date.__slots__ + time.__slots__
1413
1414 _isore = re.compile(date._isore.pattern[:-1] + r'[T ]' +
1415 time._isore.pattern, re.ASCII|re.IGNORECASE)
1362 1416
1363 def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0, 1417 def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0,
1364 microsecond=0, tzinfo=None, *, fold=0): 1418 microsecond=0, tzinfo=None, *, fold=0):
1365 if isinstance(year, bytes) and len(year) == 10 and 1 <= year[2]&0x7F <= 12: 1419 if isinstance(year, bytes) and len(year) == 10 and 1 <= year[2]&0x7F <= 12:
1366 # Pickle support 1420 # Pickle support
1367 self = object.__new__(cls) 1421 self = object.__new__(cls)
1368 self.__setstate(year, month) 1422 self.__setstate(year, month)
1369 self._hashcode = -1 1423 self._hashcode = -1
1370 return self 1424 return self
1371 year, month, day = _check_date_fields(year, month, day) 1425 year, month, day = _check_date_fields(year, month, day)
(...skipping 873 matching lines...)
2245 # 2299 #
2246 # In any case, it's clear that the default fromutc() is strong enough to handle 2300 # In any case, it's clear that the default fromutc() is strong enough to handle
2247 # "almost all" time zones: so long as the standard offset is invariant, it 2301 # "almost all" time zones: so long as the standard offset is invariant, it
2248 # doesn't matter if daylight time transition points change from year to year, or 2302 # doesn't matter if daylight time transition points change from year to year, or
2249 # if daylight time is skipped in some years; it doesn't matter how large or 2303 # if daylight time is skipped in some years; it doesn't matter how large or
2250 # small dst() may get within its bounds; and it doesn't even matter if some 2304 # small dst() may get within its bounds; and it doesn't even matter if some
2251 # perverse time zone returns a negative dst()). So a breaking case must be 2305 # perverse time zone returns a negative dst()). So a breaking case must be
2252 # pretty bizarre, and a tzinfo subclass can override fromutc() if it is. 2306 # pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
2253 2307
2254 try: 2308 try:
2309 raise ImportError
2255 from _datetime import * 2310 from _datetime import *
2256 except ImportError: 2311 except ImportError:
2257 pass 2312 pass
2258 else: 2313 else:
2259 # Clean up unused names 2314 # Clean up unused names
2260 del (_DAYNAMES, _DAYS_BEFORE_MONTH, _DAYS_IN_MONTH, _DI100Y, _DI400Y, 2315 del (_DAYNAMES, _DAYS_BEFORE_MONTH, _DAYS_IN_MONTH, _DI100Y, _DI400Y,
2261 _DI4Y, _EPOCH, _MAXORDINAL, _MONTHNAMES, _build_struct_time, 2316 _DI4Y, _EPOCH, _MAXORDINAL, _MONTHNAMES, _build_struct_time,
2262 _check_date_fields, _check_int_field, _check_time_fields, 2317 _check_date_fields, _check_int_field, _check_time_fields,
2263 _check_tzinfo_arg, _check_tzname, _check_utc_offset, _cmp, _cmperror, 2318 _check_tzinfo_arg, _check_tzname, _check_utc_offset, _cmp, _cmperror,
2264 _date_class, _days_before_month, _days_before_year, _days_in_month, 2319 _date_class, _days_before_month, _days_before_year, _days_in_month,
2265 _format_time, _is_leap, _isoweek1monday, _math, _ord2ymd, 2320 _format_time, _is_leap, _isoweek1monday, _math, _ord2ymd,
2266 _time, _time_class, _tzinfo_class, _wrap_strftime, _ymd2ord) 2321 _time, _time_class, _tzinfo_class, _wrap_strftime, _ymd2ord)
2267 # XXX Since import * above excludes names that start with _, 2322 # XXX Since import * above excludes names that start with _,
2268 # docstring does not get overwritten. In the future, it may be 2323 # docstring does not get overwritten. In the future, it may be
2269 # appropriate to maintain a single module level docstring and 2324 # appropriate to maintain a single module level docstring and
2270 # remove the following line. 2325 # remove the following line.
2271 from _datetime import __doc__ 2326 from _datetime import __doc__
OLDNEW
« no previous file with comments | « no previous file | Lib/test/datetimetester.py » ('j') | no next file with comments »

This is Rietveld 894c83f36cb7+