@@ -1079,6 +1079,24 @@ Other constructors, all class methods:
10791079 time tuple. See also :ref: `strftime-strptime-behavior ` and
10801080 :meth: `datetime.fromisoformat `.
10811081
1082+ .. versionchanged :: 3.13
1083+
1084+ If *format * specifies a day of month without a year a
1085+ :exc: `DeprecationWarning ` is now emitted. This is to avoid a quadrennial
1086+ leap year bug in code seeking to parse only a month and day as the
1087+ default year used in absence of one in the format is not a leap year.
1088+ Such *format * values may raise an error as of Python 3.15. The
1089+ workaround is to always include a year in your *format *. If parsing
1090+ *date_string * values that do not have a year, explicitly add a year that
1091+ is a leap year before parsing:
1092+
1093+ .. doctest ::
1094+
1095+ >>> from datetime import datetime
1096+ >>> date_string = " 02/29"
1097+ >>> when = datetime.strptime(f " { date_string} ;1984 " , " %m/%d ;%Y" ) # Avoids leap year bug.
1098+ >>> when.strftime(" %B %d " ) # doctest: +SKIP
1099+ 'February 29'
10821100
10831101
10841102Class attributes:
@@ -2657,6 +2675,25 @@ Notes:
26572675 for formats ``%d ``, ``%m ``, ``%H ``, ``%I ``, ``%M ``, ``%S ``, ``%j ``, ``%U ``,
26582676 ``%W ``, and ``%V ``. Format ``%y `` does require a leading zero.
26592677
2678+ (10)
2679+ When parsing a month and day using :meth: `~.datetime.strptime `, always
2680+ include a year in the format. If the value you need to parse lacks a year,
2681+ append an explicit dummy leap year. Otherwise your code will raise an
2682+ exception when it encounters leap day because the default year used by the
2683+ parser is not a leap year. Users run into this bug every four years...
2684+
2685+ .. doctest ::
2686+
2687+ >>> month_day = " 02/29"
2688+ >>> datetime.strptime(f " { month_day} ;1984 " , " %m/%d ;%Y" ) # No leap year bug.
2689+ datetime.datetime(1984, 2, 29, 0, 0)
2690+
2691+ .. deprecated-removed :: 3.13 3.15
2692+ :meth: `~.datetime.strptime ` calls using a format string containing
2693+ a day of month without a year now emit a
2694+ :exc: `DeprecationWarning `. In 3.15 or later we may change this into
2695+ an error or change the default year to a leap year. See :gh: `70647 `.
2696+
26602697.. rubric :: Footnotes
26612698
26622699.. [# ] If, that is, we ignore the effects of Relativity
0 commit comments