Boost C++ Libraries: Ticket #13159: Assert hit in wcsftime.cpp on MSVC due to tm_year out of range https://svn.boost.org/trac10/ticket/13159 <p> The issue is only reproducible on MSVC (toolsets tested v120, v140, v141) and caused by a limitation imposed on <code>tm_year</code> of <code>tm</code> to belong to the range <code>[-1900; 8099]</code> (see assert below). </p> <p> Here is the sample code that reproduces the problem: </p> <pre class="wiki">#include "stdafx.h" #include &lt;sstream&gt; #include &lt;boost/date_time.hpp&gt; int main() { std::ostringstream os; os.imbue(std::locale(std::locale::classic(), new boost::posix_time::time_facet("%Y"))); os &lt;&lt; boost::posix_time::ptime(boost::gregorian::date(10000, 1, 1)); return 0; } </pre><p> Stack trace: </p> <pre class="wiki"> ucrtbased.dll!expand_time(__crt_locale_pointers * locale, wchar_t specifier, const tm * timeptr, wchar_t * * string, unsigned __int64 * left, const __crt_lc_time_data * lc_time, bool alternate_form) Line 971 C++ ucrtbased.dll!_Wcsftime_l(wchar_t * string, unsigned __int64 max_size, const wchar_t * format, const tm * timeptr, void * lc_time_arg, __crt_locale_pointers * locale) Line 1134 C++ ucrtbased.dll!_Strftime_l(char * const string, const unsigned __int64 maxsize, const char * const format, const tm * const timeptr, void * const lc_time_arg, __crt_locale_pointers * const locale) Line 169 C++ ucrtbased.dll!_Strftime(char * string, unsigned __int64 max_size, const char * format, const tm * timeptr, void * lc_time_arg) Line 197 C++ &gt; msvcp140d.dll!std::time_put&lt;char,std::ostreambuf_iterator&lt;char,std::char_traits&lt;char&gt; &gt; &gt;::do_put(std::ostreambuf_iterator&lt;char,std::char_traits&lt;char&gt; &gt; _Dest, std::ios_base &amp; __formal, char __formal, const tm * _Pt, char _Specifier, char _Modifier) Line 799 C++ msvcp140d.dll!std::time_put&lt;char,std::ostreambuf_iterator&lt;char,std::char_traits&lt;char&gt; &gt; &gt;::put(std::ostreambuf_iterator&lt;char,std::char_traits&lt;char&gt; &gt; _Dest, std::ios_base &amp; _Iosbase, char _Fill, const tm * _Pt, const char * _Fmtfirst, const char * _Fmtlast) Line 732 C++ DateTimePlayground.exe!boost::date_time::date_facet&lt;boost::gregorian::date,char,std::ostreambuf_iterator&lt;char,std::char_traits&lt;char&gt; &gt; &gt;::do_put_tm(std::ostreambuf_iterator&lt;char,std::char_traits&lt;char&gt; &gt; next, std::ios_base &amp; a_ios, char fill_char, const tm &amp; tm_value, std::basic_string&lt;char,std::char_traits&lt;char&gt;,std::allocator&lt;char&gt; &gt; a_format) Line 342 C++ DateTimePlayground.exe!boost::date_time::time_facet&lt;boost::posix_time::ptime,char,std::ostreambuf_iterator&lt;char,std::char_traits&lt;char&gt; &gt; &gt;::put(std::ostreambuf_iterator&lt;char,std::char_traits&lt;char&gt; &gt; next_arg, std::ios_base &amp; ios_arg, char fill_arg, const boost::posix_time::ptime &amp; time_arg) Line 427 C++ DateTimePlayground.exe!boost::posix_time::operator&lt;&lt;&lt;char,std::char_traits&lt;char&gt; &gt;(std::basic_ostream&lt;char,std::char_traits&lt;char&gt; &gt; &amp; os, const boost::posix_time::ptime &amp; p) Line 52 C++ DateTimePlayground.exe!main() Line 11 C++ [External Code] </pre><p> Assert: </p> <pre class="wiki">Debug Assertion Failed! Program: ...\Projects\DateTimePlayground\x64\Debug\DateTimePlayground.exe File: minkernel\crts\ucrt\src\appcrt\time\wcsftime.cpp Line: 971 Expression: timeptr-&gt;tm_year &gt;= -1900 &amp;&amp; timeptr-&gt;tm_year &lt;= 8099 For information on how your program can cause an assertion failure, see the Visual C++ documentation on asserts. (Press Retry to debug the application) </pre><p> Any date with year <code>10000</code> will hit this assert. Starting with year <code>10001</code> <code>boost::gregorian::bad_year</code> is thrown instead. </p> <p> Such behavior is caused by max year (include/boost/date_time/gregorian/greg_year.hpp#L28) that allows year <code>10000</code>. This causes <code>tm_year</code> of <code>tm</code> to be <code>8100</code> out of range <code>[-1900; 8099]</code> when converting ptime to tm (include/boost/date_time/time_facet.hpp#L428). </p> <p> I would expect consistent <code>boost::gregorian::bad_year</code> thrown in all cases without crashes. </p> <p> One possible solution is to consider changing max year to <code>9999</code>. This would also fix <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/12630" title="#12630: Bugs: Limits for boost::gregorian are inconsistent (closed: fixed)">#12630</a> and make <code>%Y</code> format specifier to be more consistent with its definition (xmldoc/format_flags.xml#L220) - a <code>Four digit year</code>. Currently, the following code on Linux outputs <code>10000</code> instead of throwing <code>boost::gregorian::bad_year</code> that is at least confusing since <code>10000</code> does not look like a four digit number as promised by <code>%Y</code>: </p> <pre class="wiki">#include &lt;sstream&gt; #include &lt;boost/date_time.hpp&gt; int main() { std::ostringstream os; os.imbue(std::locale(std::locale::classic(), new boost::posix_time::time_facet("%Y"))); os &lt;&lt; boost::posix_time::ptime(boost::gregorian::date(10000, 1, 1)); std::cout &lt;&lt; os.str(); return 0; } </pre> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/13159 Trac 1.4.3 anonymous Sat, 12 Aug 2017 08:01:34 GMT summary changed https://svn.boost.org/trac10/ticket/13159#comment:1 https://svn.boost.org/trac10/ticket/13159#comment:1 <ul> <li><strong>summary</strong> <span class="trac-field-old">Assert hit in wcsftime.cpp on Windows due to tm_year out of range</span> → <span class="trac-field-new">Assert hit in wcsftime.cpp on MSVC due to tm_year out of range</span> </li> </ul> Ticket anonymous Sat, 12 Aug 2017 08:02:00 GMT version, component changed; owner set https://svn.boost.org/trac10/ticket/13159#comment:2 https://svn.boost.org/trac10/ticket/13159#comment:2 <ul> <li><strong>owner</strong> set to <span class="trac-author">az_sw_dude</span> </li> <li><strong>version</strong> <span class="trac-field-old">Boost 1.63.0</span> → <span class="trac-field-new">Boost Development Trunk</span> </li> <li><strong>component</strong> <span class="trac-field-old">None</span> → <span class="trac-field-new">date_time</span> </li> </ul> Ticket James E. King, III Thu, 18 Jan 2018 03:41:35 GMT owner, status changed https://svn.boost.org/trac10/ticket/13159#comment:3 https://svn.boost.org/trac10/ticket/13159#comment:3 <ul> <li><strong>owner</strong> changed from <span class="trac-author">az_sw_dude</span> to <span class="trac-author">James E. King, III</span> </li> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> </ul> Ticket James E. King, III Thu, 18 Jan 2018 03:42:31 GMT version changed https://svn.boost.org/trac10/ticket/13159#comment:4 https://svn.boost.org/trac10/ticket/13159#comment:4 <ul> <li><strong>version</strong> <span class="trac-field-old">Boost Development Trunk</span> → <span class="trac-field-new">Boost 1.63.0</span> </li> </ul> <p> Moving original version found back to 1.63.0. Not saying older versions don't do this, but it's better than "development trunk". </p> Ticket James E. King, III Thu, 18 Jan 2018 13:38:50 GMT <link>https://svn.boost.org/trac10/ticket/13159#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/13159#comment:5</guid> <description> <p> <a class="ext-link" href="https://github.com/boostorg/date_time/pull/71"><span class="icon">​</span>https://github.com/boostorg/date_time/pull/71</a> </p> </description> <category>Ticket</category> </item> <item> <dc:creator>James E. King, III</dc:creator> <pubDate>Thu, 18 Jan 2018 13:51:55 GMT</pubDate> <title>milestone changed https://svn.boost.org/trac10/ticket/13159#comment:6 https://svn.boost.org/trac10/ticket/13159#comment:6 <ul> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.67.0</span> </li> </ul> Ticket James E. King, III Sun, 28 Jan 2018 16:25:44 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/13159#comment:7 https://svn.boost.org/trac10/ticket/13159#comment:7 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> Fix merged to master; resolved. </p> Ticket