mirror of
https://github.com/python/cpython.git
synced 2025-12-04 16:43:27 +00:00
Closes issue #12006: Add ISO 8601 year, week, and day directives to strptime.
This commit adds %G, %V, and %u directives to strptime. Thanks Ashley Anderson for the implementation.
This commit is contained in:
parent
fc632e3912
commit
68713e41a5
5 changed files with 159 additions and 27 deletions
|
|
@ -1909,6 +1909,34 @@ format codes.
|
||||||
| ``%%`` | A literal ``'%'`` character. | % | |
|
| ``%%`` | A literal ``'%'`` character. | % | |
|
||||||
+-----------+--------------------------------+------------------------+-------+
|
+-----------+--------------------------------+------------------------+-------+
|
||||||
|
|
||||||
|
Several additional directives not required by the C89 standard are included for
|
||||||
|
convenience. These parameters all correspond to ISO 8601 date values. These
|
||||||
|
may not be available on all platforms when used with the :meth:`strftime`
|
||||||
|
method. The ISO 8601 year and ISO 8601 week directives are not interchangeable
|
||||||
|
with the year and week number directives above. Calling :meth:`strptime` with
|
||||||
|
incomplete or ambiguous ISO 8601 directives will raise a :exc:`ValueError`.
|
||||||
|
|
||||||
|
+-----------+--------------------------------+------------------------+-------+
|
||||||
|
| Directive | Meaning | Example | Notes |
|
||||||
|
+===========+================================+========================+=======+
|
||||||
|
| ``%G`` | ISO 8601 year with century | 0001, 0002, ..., 2013, | \(8) |
|
||||||
|
| | representing the year that | 2014, ..., 9998, 9999 | |
|
||||||
|
| | contains the greater part of | | |
|
||||||
|
| | the ISO week (``%V``). | | |
|
||||||
|
+-----------+--------------------------------+------------------------+-------+
|
||||||
|
| ``%u`` | ISO 8601 weekday as a decimal | 1, 2, ..., 7 | |
|
||||||
|
| | number where 1 is Monday. | | |
|
||||||
|
+-----------+--------------------------------+------------------------+-------+
|
||||||
|
| ``%V`` | ISO 8601 week as a decimal | 01, 02, ..., 53 | \(8) |
|
||||||
|
| | number with Monday as | | |
|
||||||
|
| | the first day of the week. | | |
|
||||||
|
| | Week 01 is the week containing | | |
|
||||||
|
| | Jan 4. | | |
|
||||||
|
+-----------+--------------------------------+------------------------+-------+
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
|
``%G``, ``%u`` and ``%V`` were added.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
(1)
|
(1)
|
||||||
|
|
@ -1973,7 +2001,14 @@ Notes:
|
||||||
|
|
||||||
(7)
|
(7)
|
||||||
When used with the :meth:`strptime` method, ``%U`` and ``%W`` are only used
|
When used with the :meth:`strptime` method, ``%U`` and ``%W`` are only used
|
||||||
in calculations when the day of the week and the year are specified.
|
in calculations when the day of the week and the calendar year (``%Y``)
|
||||||
|
are specified.
|
||||||
|
|
||||||
|
(8)
|
||||||
|
Similar to ``%U`` and ``%W``, ``%V`` is only used in calculations when the
|
||||||
|
day of the week and the ISO year (``%G``) are specified in a
|
||||||
|
:meth:`strptime` format string. Also note that ``%G`` and ``%Y`` are not
|
||||||
|
interchangable.
|
||||||
|
|
||||||
.. rubric:: Footnotes
|
.. rubric:: Footnotes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,14 @@ Private and special attribute names now are omitted unless the prefix starts
|
||||||
with underscores. A space or a colon can be added after completed keyword.
|
with underscores. A space or a colon can be added after completed keyword.
|
||||||
(Contributed by Serhiy Storchaka in :issue:`25011` and :issue:`25209`.)
|
(Contributed by Serhiy Storchaka in :issue:`25011` and :issue:`25209`.)
|
||||||
|
|
||||||
|
datetime
|
||||||
|
--------
|
||||||
|
|
||||||
|
* :meth:`datetime.stftime <datetime.datetime.stftime>` and
|
||||||
|
:meth:`date.stftime <datetime.date.stftime>` methods now support ISO 8601
|
||||||
|
date directives ``%G``, ``%u`` and ``%V``.
|
||||||
|
(Contributed by Ashley Anderson in :issue:`12006`.)
|
||||||
|
|
||||||
|
|
||||||
Optimizations
|
Optimizations
|
||||||
=============
|
=============
|
||||||
|
|
|
||||||
|
|
@ -195,12 +195,15 @@ class TimeRE(dict):
|
||||||
'f': r"(?P<f>[0-9]{1,6})",
|
'f': r"(?P<f>[0-9]{1,6})",
|
||||||
'H': r"(?P<H>2[0-3]|[0-1]\d|\d)",
|
'H': r"(?P<H>2[0-3]|[0-1]\d|\d)",
|
||||||
'I': r"(?P<I>1[0-2]|0[1-9]|[1-9])",
|
'I': r"(?P<I>1[0-2]|0[1-9]|[1-9])",
|
||||||
|
'G': r"(?P<G>\d\d\d\d)",
|
||||||
'j': r"(?P<j>36[0-6]|3[0-5]\d|[1-2]\d\d|0[1-9]\d|00[1-9]|[1-9]\d|0[1-9]|[1-9])",
|
'j': r"(?P<j>36[0-6]|3[0-5]\d|[1-2]\d\d|0[1-9]\d|00[1-9]|[1-9]\d|0[1-9]|[1-9])",
|
||||||
'm': r"(?P<m>1[0-2]|0[1-9]|[1-9])",
|
'm': r"(?P<m>1[0-2]|0[1-9]|[1-9])",
|
||||||
'M': r"(?P<M>[0-5]\d|\d)",
|
'M': r"(?P<M>[0-5]\d|\d)",
|
||||||
'S': r"(?P<S>6[0-1]|[0-5]\d|\d)",
|
'S': r"(?P<S>6[0-1]|[0-5]\d|\d)",
|
||||||
'U': r"(?P<U>5[0-3]|[0-4]\d|\d)",
|
'U': r"(?P<U>5[0-3]|[0-4]\d|\d)",
|
||||||
'w': r"(?P<w>[0-6])",
|
'w': r"(?P<w>[0-6])",
|
||||||
|
'u': r"(?P<u>[1-7])",
|
||||||
|
'V': r"(?P<V>5[0-3]|0[1-9]|[1-4]\d|\d)",
|
||||||
# W is set below by using 'U'
|
# W is set below by using 'U'
|
||||||
'y': r"(?P<y>\d\d)",
|
'y': r"(?P<y>\d\d)",
|
||||||
#XXX: Does 'Y' need to worry about having less or more than
|
#XXX: Does 'Y' need to worry about having less or more than
|
||||||
|
|
@ -295,6 +298,22 @@ def _calc_julian_from_U_or_W(year, week_of_year, day_of_week, week_starts_Mon):
|
||||||
return 1 + days_to_week + day_of_week
|
return 1 + days_to_week + day_of_week
|
||||||
|
|
||||||
|
|
||||||
|
def _calc_julian_from_V(iso_year, iso_week, iso_weekday):
|
||||||
|
"""Calculate the Julian day based on the ISO 8601 year, week, and weekday.
|
||||||
|
ISO weeks start on Mondays, with week 01 being the week containing 4 Jan.
|
||||||
|
ISO week days range from 1 (Monday) to 7 (Sunday).
|
||||||
|
"""
|
||||||
|
correction = datetime_date(iso_year, 1, 4).isoweekday() + 3
|
||||||
|
ordinal = (iso_week * 7) + iso_weekday - correction
|
||||||
|
# ordinal may be negative or 0 now, which means the date is in the previous
|
||||||
|
# calendar year
|
||||||
|
if ordinal < 1:
|
||||||
|
ordinal += datetime_date(iso_year, 1, 1).toordinal()
|
||||||
|
iso_year -= 1
|
||||||
|
ordinal -= datetime_date(iso_year, 1, 1).toordinal()
|
||||||
|
return iso_year, ordinal
|
||||||
|
|
||||||
|
|
||||||
def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
|
def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
|
||||||
"""Return a 2-tuple consisting of a time struct and an int containing
|
"""Return a 2-tuple consisting of a time struct and an int containing
|
||||||
the number of microseconds based on the input string and the
|
the number of microseconds based on the input string and the
|
||||||
|
|
@ -339,15 +358,15 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
|
||||||
raise ValueError("unconverted data remains: %s" %
|
raise ValueError("unconverted data remains: %s" %
|
||||||
data_string[found.end():])
|
data_string[found.end():])
|
||||||
|
|
||||||
year = None
|
iso_year = year = None
|
||||||
month = day = 1
|
month = day = 1
|
||||||
hour = minute = second = fraction = 0
|
hour = minute = second = fraction = 0
|
||||||
tz = -1
|
tz = -1
|
||||||
tzoffset = None
|
tzoffset = None
|
||||||
# Default to -1 to signify that values not known; not critical to have,
|
# Default to -1 to signify that values not known; not critical to have,
|
||||||
# though
|
# though
|
||||||
week_of_year = -1
|
iso_week = week_of_year = None
|
||||||
week_of_year_start = -1
|
week_of_year_start = None
|
||||||
# weekday and julian defaulted to None so as to signal need to calculate
|
# weekday and julian defaulted to None so as to signal need to calculate
|
||||||
# values
|
# values
|
||||||
weekday = julian = None
|
weekday = julian = None
|
||||||
|
|
@ -369,6 +388,8 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
|
||||||
year += 1900
|
year += 1900
|
||||||
elif group_key == 'Y':
|
elif group_key == 'Y':
|
||||||
year = int(found_dict['Y'])
|
year = int(found_dict['Y'])
|
||||||
|
elif group_key == 'G':
|
||||||
|
iso_year = int(found_dict['G'])
|
||||||
elif group_key == 'm':
|
elif group_key == 'm':
|
||||||
month = int(found_dict['m'])
|
month = int(found_dict['m'])
|
||||||
elif group_key == 'B':
|
elif group_key == 'B':
|
||||||
|
|
@ -414,6 +435,9 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
|
||||||
weekday = 6
|
weekday = 6
|
||||||
else:
|
else:
|
||||||
weekday -= 1
|
weekday -= 1
|
||||||
|
elif group_key == 'u':
|
||||||
|
weekday = int(found_dict['u'])
|
||||||
|
weekday -= 1
|
||||||
elif group_key == 'j':
|
elif group_key == 'j':
|
||||||
julian = int(found_dict['j'])
|
julian = int(found_dict['j'])
|
||||||
elif group_key in ('U', 'W'):
|
elif group_key in ('U', 'W'):
|
||||||
|
|
@ -424,6 +448,8 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
|
||||||
else:
|
else:
|
||||||
# W starts week on Monday.
|
# W starts week on Monday.
|
||||||
week_of_year_start = 0
|
week_of_year_start = 0
|
||||||
|
elif group_key == 'V':
|
||||||
|
iso_week = int(found_dict['V'])
|
||||||
elif group_key == 'z':
|
elif group_key == 'z':
|
||||||
z = found_dict['z']
|
z = found_dict['z']
|
||||||
tzoffset = int(z[1:3]) * 60 + int(z[3:5])
|
tzoffset = int(z[1:3]) * 60 + int(z[3:5])
|
||||||
|
|
@ -444,28 +470,57 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
|
||||||
else:
|
else:
|
||||||
tz = value
|
tz = value
|
||||||
break
|
break
|
||||||
|
# Deal with the cases where ambiguities arize
|
||||||
|
# don't assume default values for ISO week/year
|
||||||
|
if year is None and iso_year is not None:
|
||||||
|
if iso_week is None or weekday is None:
|
||||||
|
raise ValueError("ISO year directive '%G' must be used with "
|
||||||
|
"the ISO week directive '%V' and a weekday "
|
||||||
|
"directive ('%A', '%a', '%w', or '%u').")
|
||||||
|
if julian is not None:
|
||||||
|
raise ValueError("Day of the year directive '%j' is not "
|
||||||
|
"compatible with ISO year directive '%G'. "
|
||||||
|
"Use '%Y' instead.")
|
||||||
|
elif week_of_year is None and iso_week is not None:
|
||||||
|
if weekday is None:
|
||||||
|
raise ValueError("ISO week directive '%V' must be used with "
|
||||||
|
"the ISO year directive '%G' and a weekday "
|
||||||
|
"directive ('%A', '%a', '%w', or '%u').")
|
||||||
|
else:
|
||||||
|
raise ValueError("ISO week directive '%V' is incompatible with "
|
||||||
|
"the year directive '%Y'. Use the ISO year '%G' "
|
||||||
|
"instead.")
|
||||||
|
|
||||||
leap_year_fix = False
|
leap_year_fix = False
|
||||||
if year is None and month == 2 and day == 29:
|
if year is None and month == 2 and day == 29:
|
||||||
year = 1904 # 1904 is first leap year of 20th century
|
year = 1904 # 1904 is first leap year of 20th century
|
||||||
leap_year_fix = True
|
leap_year_fix = True
|
||||||
elif year is None:
|
elif year is None:
|
||||||
year = 1900
|
year = 1900
|
||||||
|
|
||||||
|
|
||||||
# If we know the week of the year and what day of that week, we can figure
|
# If we know the week of the year and what day of that week, we can figure
|
||||||
# out the Julian day of the year.
|
# out the Julian day of the year.
|
||||||
if julian is None and week_of_year != -1 and weekday is not None:
|
if julian is None and weekday is not None:
|
||||||
|
if week_of_year is not None:
|
||||||
week_starts_Mon = True if week_of_year_start == 0 else False
|
week_starts_Mon = True if week_of_year_start == 0 else False
|
||||||
julian = _calc_julian_from_U_or_W(year, week_of_year, weekday,
|
julian = _calc_julian_from_U_or_W(year, week_of_year, weekday,
|
||||||
week_starts_Mon)
|
week_starts_Mon)
|
||||||
# Cannot pre-calculate datetime_date() since can change in Julian
|
elif iso_year is not None and iso_week is not None:
|
||||||
# calculation and thus could have different value for the day of the week
|
year, julian = _calc_julian_from_V(iso_year, iso_week, weekday + 1)
|
||||||
# calculation.
|
|
||||||
if julian is None:
|
if julian is None:
|
||||||
|
# Cannot pre-calculate datetime_date() since can change in Julian
|
||||||
|
# calculation and thus could have different value for the day of
|
||||||
|
# the week calculation.
|
||||||
# Need to add 1 to result since first day of the year is 1, not 0.
|
# Need to add 1 to result since first day of the year is 1, not 0.
|
||||||
julian = datetime_date(year, month, day).toordinal() - \
|
julian = datetime_date(year, month, day).toordinal() - \
|
||||||
datetime_date(year, 1, 1).toordinal() + 1
|
datetime_date(year, 1, 1).toordinal() + 1
|
||||||
else: # Assume that if they bothered to include Julian day it will
|
else: # Assume that if they bothered to include Julian day (or if it was
|
||||||
# be accurate.
|
# calculated above with year/week/weekday) it will be accurate.
|
||||||
datetime_result = datetime_date.fromordinal((julian - 1) + datetime_date(year, 1, 1).toordinal())
|
datetime_result = datetime_date.fromordinal(
|
||||||
|
(julian - 1) +
|
||||||
|
datetime_date(year, 1, 1).toordinal())
|
||||||
year = datetime_result.year
|
year = datetime_result.year
|
||||||
month = datetime_result.month
|
month = datetime_result.month
|
||||||
day = datetime_result.day
|
day = datetime_result.day
|
||||||
|
|
|
||||||
|
|
@ -152,8 +152,8 @@ class TimeRETests(unittest.TestCase):
|
||||||
"'%s' using '%s'; group 'a' = '%s', group 'b' = %s'" %
|
"'%s' using '%s'; group 'a' = '%s', group 'b' = %s'" %
|
||||||
(found.string, found.re.pattern, found.group('a'),
|
(found.string, found.re.pattern, found.group('a'),
|
||||||
found.group('b')))
|
found.group('b')))
|
||||||
for directive in ('a','A','b','B','c','d','H','I','j','m','M','p','S',
|
for directive in ('a','A','b','B','c','d','G','H','I','j','m','M','p',
|
||||||
'U','w','W','x','X','y','Y','Z','%'):
|
'S','u','U','V','w','W','x','X','y','Y','Z','%'):
|
||||||
compiled = self.time_re.compile("%" + directive)
|
compiled = self.time_re.compile("%" + directive)
|
||||||
found = compiled.match(time.strftime("%" + directive))
|
found = compiled.match(time.strftime("%" + directive))
|
||||||
self.assertTrue(found, "Matching failed on '%s' using '%s' regex" %
|
self.assertTrue(found, "Matching failed on '%s' using '%s' regex" %
|
||||||
|
|
@ -218,6 +218,26 @@ class StrptimeTests(unittest.TestCase):
|
||||||
else:
|
else:
|
||||||
self.fail("'%s' did not raise ValueError" % bad_format)
|
self.fail("'%s' did not raise ValueError" % bad_format)
|
||||||
|
|
||||||
|
# Ambiguous or incomplete cases using ISO year/week/weekday directives
|
||||||
|
# 1. ISO week (%V) is specified, but the year is specified with %Y
|
||||||
|
# instead of %G
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
_strptime._strptime("1999 50", "%Y %V")
|
||||||
|
# 2. ISO year (%G) and ISO week (%V) are specified, but weekday is not
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
_strptime._strptime("1999 51", "%G %V")
|
||||||
|
# 3. ISO year (%G) and weekday are specified, but ISO week (%V) is not
|
||||||
|
for w in ('A', 'a', 'w', 'u'):
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
_strptime._strptime("1999 51","%G %{}".format(w))
|
||||||
|
# 4. ISO year is specified alone (e.g. time.strptime('2015', '%G'))
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
_strptime._strptime("2015", "%G")
|
||||||
|
# 5. Julian/ordinal day (%j) is specified with %G, but not %Y
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
_strptime._strptime("1999 256", "%G %j")
|
||||||
|
|
||||||
|
|
||||||
def test_strptime_exception_context(self):
|
def test_strptime_exception_context(self):
|
||||||
# check that this doesn't chain exceptions needlessly (see #17572)
|
# check that this doesn't chain exceptions needlessly (see #17572)
|
||||||
with self.assertRaises(ValueError) as e:
|
with self.assertRaises(ValueError) as e:
|
||||||
|
|
@ -289,7 +309,7 @@ class StrptimeTests(unittest.TestCase):
|
||||||
|
|
||||||
def test_weekday(self):
|
def test_weekday(self):
|
||||||
# Test weekday directives
|
# Test weekday directives
|
||||||
for directive in ('A', 'a', 'w'):
|
for directive in ('A', 'a', 'w', 'u'):
|
||||||
self.helper(directive,6)
|
self.helper(directive,6)
|
||||||
|
|
||||||
def test_julian(self):
|
def test_julian(self):
|
||||||
|
|
@ -458,16 +478,20 @@ class CalculationTests(unittest.TestCase):
|
||||||
# Should be able to infer date if given year, week of year (%U or %W)
|
# Should be able to infer date if given year, week of year (%U or %W)
|
||||||
# and day of the week
|
# and day of the week
|
||||||
def test_helper(ymd_tuple, test_reason):
|
def test_helper(ymd_tuple, test_reason):
|
||||||
for directive in ('W', 'U'):
|
for year_week_format in ('%Y %W', '%Y %U', '%G %V'):
|
||||||
format_string = "%%Y %%%s %%w" % directive
|
for weekday_format in ('%w', '%u', '%a', '%A'):
|
||||||
|
format_string = year_week_format + ' ' + weekday_format
|
||||||
|
with self.subTest(test_reason,
|
||||||
|
date=ymd_tuple,
|
||||||
|
format=format_string):
|
||||||
dt_date = datetime_date(*ymd_tuple)
|
dt_date = datetime_date(*ymd_tuple)
|
||||||
strp_input = dt_date.strftime(format_string)
|
strp_input = dt_date.strftime(format_string)
|
||||||
strp_output = _strptime._strptime_time(strp_input, format_string)
|
strp_output = _strptime._strptime_time(strp_input,
|
||||||
self.assertTrue(strp_output[:3] == ymd_tuple,
|
format_string)
|
||||||
"%s(%s) test failed w/ '%s': %s != %s (%s != %s)" %
|
msg = "%r: %s != %s" % (strp_input,
|
||||||
(test_reason, directive, strp_input,
|
strp_output[7],
|
||||||
strp_output[:3], ymd_tuple,
|
dt_date.timetuple()[7])
|
||||||
strp_output[7], dt_date.timetuple()[7]))
|
self.assertEqual(strp_output[:3], ymd_tuple, msg)
|
||||||
test_helper((1901, 1, 3), "week 0")
|
test_helper((1901, 1, 3), "week 0")
|
||||||
test_helper((1901, 1, 8), "common case")
|
test_helper((1901, 1, 8), "common case")
|
||||||
test_helper((1901, 1, 13), "day on Sunday")
|
test_helper((1901, 1, 13), "day on Sunday")
|
||||||
|
|
@ -499,18 +523,25 @@ class CalculationTests(unittest.TestCase):
|
||||||
self.assertEqual(_strptime._strptime_time(value, format)[:-1], expected)
|
self.assertEqual(_strptime._strptime_time(value, format)[:-1], expected)
|
||||||
check('2015 0 0', '%Y %U %w', 2014, 12, 28, 0, 0, 0, 6, -3)
|
check('2015 0 0', '%Y %U %w', 2014, 12, 28, 0, 0, 0, 6, -3)
|
||||||
check('2015 0 0', '%Y %W %w', 2015, 1, 4, 0, 0, 0, 6, 4)
|
check('2015 0 0', '%Y %W %w', 2015, 1, 4, 0, 0, 0, 6, 4)
|
||||||
|
check('2015 1 1', '%G %V %u', 2014, 12, 29, 0, 0, 0, 0, 363)
|
||||||
check('2015 0 1', '%Y %U %w', 2014, 12, 29, 0, 0, 0, 0, -2)
|
check('2015 0 1', '%Y %U %w', 2014, 12, 29, 0, 0, 0, 0, -2)
|
||||||
check('2015 0 1', '%Y %W %w', 2014, 12, 29, 0, 0, 0, 0, -2)
|
check('2015 0 1', '%Y %W %w', 2014, 12, 29, 0, 0, 0, 0, -2)
|
||||||
|
check('2015 1 2', '%G %V %u', 2014, 12, 30, 0, 0, 0, 1, 364)
|
||||||
check('2015 0 2', '%Y %U %w', 2014, 12, 30, 0, 0, 0, 1, -1)
|
check('2015 0 2', '%Y %U %w', 2014, 12, 30, 0, 0, 0, 1, -1)
|
||||||
check('2015 0 2', '%Y %W %w', 2014, 12, 30, 0, 0, 0, 1, -1)
|
check('2015 0 2', '%Y %W %w', 2014, 12, 30, 0, 0, 0, 1, -1)
|
||||||
|
check('2015 1 3', '%G %V %u', 2014, 12, 31, 0, 0, 0, 2, 365)
|
||||||
check('2015 0 3', '%Y %U %w', 2014, 12, 31, 0, 0, 0, 2, 0)
|
check('2015 0 3', '%Y %U %w', 2014, 12, 31, 0, 0, 0, 2, 0)
|
||||||
check('2015 0 3', '%Y %W %w', 2014, 12, 31, 0, 0, 0, 2, 0)
|
check('2015 0 3', '%Y %W %w', 2014, 12, 31, 0, 0, 0, 2, 0)
|
||||||
|
check('2015 1 4', '%G %V %u', 2015, 1, 1, 0, 0, 0, 3, 1)
|
||||||
check('2015 0 4', '%Y %U %w', 2015, 1, 1, 0, 0, 0, 3, 1)
|
check('2015 0 4', '%Y %U %w', 2015, 1, 1, 0, 0, 0, 3, 1)
|
||||||
check('2015 0 4', '%Y %W %w', 2015, 1, 1, 0, 0, 0, 3, 1)
|
check('2015 0 4', '%Y %W %w', 2015, 1, 1, 0, 0, 0, 3, 1)
|
||||||
|
check('2015 1 5', '%G %V %u', 2015, 1, 2, 0, 0, 0, 4, 2)
|
||||||
check('2015 0 5', '%Y %U %w', 2015, 1, 2, 0, 0, 0, 4, 2)
|
check('2015 0 5', '%Y %U %w', 2015, 1, 2, 0, 0, 0, 4, 2)
|
||||||
check('2015 0 5', '%Y %W %w', 2015, 1, 2, 0, 0, 0, 4, 2)
|
check('2015 0 5', '%Y %W %w', 2015, 1, 2, 0, 0, 0, 4, 2)
|
||||||
|
check('2015 1 6', '%G %V %u', 2015, 1, 3, 0, 0, 0, 5, 3)
|
||||||
check('2015 0 6', '%Y %U %w', 2015, 1, 3, 0, 0, 0, 5, 3)
|
check('2015 0 6', '%Y %U %w', 2015, 1, 3, 0, 0, 0, 5, 3)
|
||||||
check('2015 0 6', '%Y %W %w', 2015, 1, 3, 0, 0, 0, 5, 3)
|
check('2015 0 6', '%Y %W %w', 2015, 1, 3, 0, 0, 0, 5, 3)
|
||||||
|
check('2015 1 7', '%G %V %u', 2015, 1, 4, 0, 0, 0, 6, 4)
|
||||||
|
|
||||||
|
|
||||||
class CacheTests(unittest.TestCase):
|
class CacheTests(unittest.TestCase):
|
||||||
|
|
|
||||||
|
|
@ -383,6 +383,9 @@ Library
|
||||||
- Issue #23572: Fixed functools.singledispatch on classes with falsy
|
- Issue #23572: Fixed functools.singledispatch on classes with falsy
|
||||||
metaclasses. Patch by Ethan Furman.
|
metaclasses. Patch by Ethan Furman.
|
||||||
|
|
||||||
|
- Issue #12006: Add ISO 8601 year, week, and day directives (%G, %V, %u) to
|
||||||
|
strptime.
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue