@@ -152,8 +152,8 @@ def test_compile(self):
152152 "'%s' using '%s'; group 'a' = '%s', group 'b' = %s'" %
153153 (found .string , found .re .pattern , found .group ('a' ),
154154 found .group ('b' )))
155- for directive in ('a' ,'A' ,'b' ,'B' ,'c' ,'d' ,'H' ,'I' ,'j' ,'m' ,'M' ,'p' , 'S ' ,
156- 'U ' ,'w' ,'W' ,'x' ,'X' ,'y' ,'Y' ,'Z' ,'%' ):
155+ for directive in ('a' ,'A' ,'b' ,'B' ,'c' ,'d' ,'G' , ' H' ,'I' ,'j' ,'m' ,'M' ,'p' ,
156+ 'S' , 'u' , 'U' , 'V ' ,'w' ,'W' ,'x' ,'X' ,'y' ,'Y' ,'Z' ,'%' ):
157157 compiled = self .time_re .compile ("%" + directive )
158158 found = compiled .match (time .strftime ("%" + directive ))
159159 self .assertTrue (found , "Matching failed on '%s' using '%s' regex" %
@@ -218,6 +218,26 @@ def test_ValueError(self):
218218 else :
219219 self .fail ("'%s' did not raise ValueError" % bad_format )
220220
221+ # Ambiguous or incomplete cases using ISO year/week/weekday directives
222+ # 1. ISO week (%V) is specified, but the year is specified with %Y
223+ # instead of %G
224+ with self .assertRaises (ValueError ):
225+ _strptime ._strptime ("1999 50" , "%Y %V" )
226+ # 2. ISO year (%G) and ISO week (%V) are specified, but weekday is not
227+ with self .assertRaises (ValueError ):
228+ _strptime ._strptime ("1999 51" , "%G %V" )
229+ # 3. ISO year (%G) and weekday are specified, but ISO week (%V) is not
230+ for w in ('A' , 'a' , 'w' , 'u' ):
231+ with self .assertRaises (ValueError ):
232+ _strptime ._strptime ("1999 51" ,"%G %{}" .format (w ))
233+ # 4. ISO year is specified alone (e.g. time.strptime('2015', '%G'))
234+ with self .assertRaises (ValueError ):
235+ _strptime ._strptime ("2015" , "%G" )
236+ # 5. Julian/ordinal day (%j) is specified with %G, but not %Y
237+ with self .assertRaises (ValueError ):
238+ _strptime ._strptime ("1999 256" , "%G %j" )
239+
240+
221241 def test_strptime_exception_context (self ):
222242 # check that this doesn't chain exceptions needlessly (see #17572)
223243 with self .assertRaises (ValueError ) as e :
@@ -289,7 +309,7 @@ def test_fraction(self):
289309
290310 def test_weekday (self ):
291311 # Test weekday directives
292- for directive in ('A' , 'a' , 'w' ):
312+ for directive in ('A' , 'a' , 'w' , 'u' ):
293313 self .helper (directive ,6 )
294314
295315 def test_julian (self ):
@@ -458,16 +478,20 @@ def test_week_of_year_and_day_of_week_calculation(self):
458478 # Should be able to infer date if given year, week of year (%U or %W)
459479 # and day of the week
460480 def test_helper (ymd_tuple , test_reason ):
461- for directive in ('W' , 'U' ):
462- format_string = "%%Y %%%s %%w" % directive
463- dt_date = datetime_date (* ymd_tuple )
464- strp_input = dt_date .strftime (format_string )
465- strp_output = _strptime ._strptime_time (strp_input , format_string )
466- self .assertTrue (strp_output [:3 ] == ymd_tuple ,
467- "%s(%s) test failed w/ '%s': %s != %s (%s != %s)" %
468- (test_reason , directive , strp_input ,
469- strp_output [:3 ], ymd_tuple ,
470- strp_output [7 ], dt_date .timetuple ()[7 ]))
481+ for year_week_format in ('%Y %W' , '%Y %U' , '%G %V' ):
482+ for weekday_format in ('%w' , '%u' , '%a' , '%A' ):
483+ format_string = year_week_format + ' ' + weekday_format
484+ with self .subTest (test_reason ,
485+ date = ymd_tuple ,
486+ format = format_string ):
487+ dt_date = datetime_date (* ymd_tuple )
488+ strp_input = dt_date .strftime (format_string )
489+ strp_output = _strptime ._strptime_time (strp_input ,
490+ format_string )
491+ msg = "%r: %s != %s" % (strp_input ,
492+ strp_output [7 ],
493+ dt_date .timetuple ()[7 ])
494+ self .assertEqual (strp_output [:3 ], ymd_tuple , msg )
471495 test_helper ((1901 , 1 , 3 ), "week 0" )
472496 test_helper ((1901 , 1 , 8 ), "common case" )
473497 test_helper ((1901 , 1 , 13 ), "day on Sunday" )
@@ -499,18 +523,25 @@ def check(value, format, *expected):
499523 self .assertEqual (_strptime ._strptime_time (value , format )[:- 1 ], expected )
500524 check ('2015 0 0' , '%Y %U %w' , 2014 , 12 , 28 , 0 , 0 , 0 , 6 , - 3 )
501525 check ('2015 0 0' , '%Y %W %w' , 2015 , 1 , 4 , 0 , 0 , 0 , 6 , 4 )
526+ check ('2015 1 1' , '%G %V %u' , 2014 , 12 , 29 , 0 , 0 , 0 , 0 , 363 )
502527 check ('2015 0 1' , '%Y %U %w' , 2014 , 12 , 29 , 0 , 0 , 0 , 0 , - 2 )
503528 check ('2015 0 1' , '%Y %W %w' , 2014 , 12 , 29 , 0 , 0 , 0 , 0 , - 2 )
529+ check ('2015 1 2' , '%G %V %u' , 2014 , 12 , 30 , 0 , 0 , 0 , 1 , 364 )
504530 check ('2015 0 2' , '%Y %U %w' , 2014 , 12 , 30 , 0 , 0 , 0 , 1 , - 1 )
505531 check ('2015 0 2' , '%Y %W %w' , 2014 , 12 , 30 , 0 , 0 , 0 , 1 , - 1 )
532+ check ('2015 1 3' , '%G %V %u' , 2014 , 12 , 31 , 0 , 0 , 0 , 2 , 365 )
506533 check ('2015 0 3' , '%Y %U %w' , 2014 , 12 , 31 , 0 , 0 , 0 , 2 , 0 )
507534 check ('2015 0 3' , '%Y %W %w' , 2014 , 12 , 31 , 0 , 0 , 0 , 2 , 0 )
535+ check ('2015 1 4' , '%G %V %u' , 2015 , 1 , 1 , 0 , 0 , 0 , 3 , 1 )
508536 check ('2015 0 4' , '%Y %U %w' , 2015 , 1 , 1 , 0 , 0 , 0 , 3 , 1 )
509537 check ('2015 0 4' , '%Y %W %w' , 2015 , 1 , 1 , 0 , 0 , 0 , 3 , 1 )
538+ check ('2015 1 5' , '%G %V %u' , 2015 , 1 , 2 , 0 , 0 , 0 , 4 , 2 )
510539 check ('2015 0 5' , '%Y %U %w' , 2015 , 1 , 2 , 0 , 0 , 0 , 4 , 2 )
511540 check ('2015 0 5' , '%Y %W %w' , 2015 , 1 , 2 , 0 , 0 , 0 , 4 , 2 )
541+ check ('2015 1 6' , '%G %V %u' , 2015 , 1 , 3 , 0 , 0 , 0 , 5 , 3 )
512542 check ('2015 0 6' , '%Y %U %w' , 2015 , 1 , 3 , 0 , 0 , 0 , 5 , 3 )
513543 check ('2015 0 6' , '%Y %W %w' , 2015 , 1 , 3 , 0 , 0 , 0 , 5 , 3 )
544+ check ('2015 1 7' , '%G %V %u' , 2015 , 1 , 4 , 0 , 0 , 0 , 6 , 4 )
514545
515546
516547class CacheTests (unittest .TestCase ):
0 commit comments