Boost C++ Libraries: Ticket #3109: time_duration::total_seconds() - overflow https://svn.boost.org/trac10/ticket/3109 <p> time_duration::total_seconds() overflow value </p> <p> minimal sample (based on boost example) <em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em> #include &lt;string&gt; #include &lt;boost/date_time/local_time/local_time.hpp&gt; </em></p> <p> int main() { </p> <blockquote> <p> using namespace boost::gregorian; using namespace boost::local_time; using namespace boost::posix_time; </p> </blockquote> <blockquote> <p> date in_date(2039, 10, 04); time_duration td(12,14,32); std::string z("PST-8PDT,M4.1.0,M10.1.0"); time_zone_ptr zone(new posix_time_zone(z)); local_date_time my_time(in_date, td, zone, local_date_time::NOT_DATE_TIME_ON_ERROR); std::cout &lt;&lt; my_time &lt;&lt; std::endl; <em> ptime time_t_epoch( date(1970,1,1) ); std::cout &lt;&lt; time_t_epoch &lt;&lt; std::endl; </em> time_duration diff = my_time.utc_time() - time_t_epoch; std::cout &lt;&lt; "Seconds diff: " &lt;&lt; diff.total_seconds() &lt;&lt; std::endl; return 0; </p> </blockquote> <p> } <em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em></em><em> </em></p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/3109 Trac 1.4.3 rehor@… Tue, 19 Jan 2010 20:38:14 GMT version changed https://svn.boost.org/trac10/ticket/3109#comment:1 https://svn.boost.org/trac10/ticket/3109#comment:1 <ul> <li><strong>version</strong> <span class="trac-field-old">Boost 1.39.0</span> → <span class="trac-field-new">Boost 1.41.0</span> </li> </ul> <p> platform: MSVC 8, Windows XP Boost 1.41 </p> <p> time_duration::total_seconds should be returning 64bit int instead of 32bit int. All underlying code is correct, only the return type of time_duration::total_seconds() is only a 32bit int, which is not wide enough for time durations lasting several decades or a century. When changed to 64bit int, total_seconds() works as expected. The problem possibly applies to other total_* methods as well. </p> <pre class="wiki">time_duration d = ptime(boost::gregorian::date(2010,1,1)) - ptime(boost::gregorian::date(1899,12,30)); unsigned long long s = d.total_seconds(); // returns a negative int </pre><p> Proposed fix: time_duration.hpp </p> <pre class="wiki"> //! Returns total number of seconds truncating any fractional seconds tick_type total_seconds() const //changed type from sec_type to tick_type { return static_cast&lt;tick_type&gt;(ticks() / ticks_per_second()); } </pre> Ticket Klemens Schindler Wed, 08 Feb 2012 13:28:55 GMT <link>https://svn.boost.org/trac10/ticket/3109#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3109#comment:2</guid> <description> <p> This problem still applies to Boost version 1.47 (I didn't check even newer versions) </p> <p> The following code: </p> <div class="wiki-code"><div class="code"><pre> <span class="k">using</span> <span class="k">namespace</span> <span class="n">boost</span><span class="o">::</span><span class="n">posix_time</span><span class="p">;</span> <span class="k">using</span> <span class="k">namespace</span> <span class="n">boost</span><span class="o">::</span><span class="n">gregorian</span><span class="p">;</span> <span class="k">using</span> <span class="k">namespace</span> <span class="n">boost</span><span class="o">::</span><span class="n">local_time</span><span class="p">;</span> <span class="n">local_date_time</span> <span class="nf">now</span><span class="p">(</span><span class="n">local_sec_clock</span><span class="o">::</span><span class="n">local_time</span><span class="p">(</span><span class="n">time_zone_ptr</span><span class="p">()));</span> <span class="n">local_date_time</span> <span class="nf">baseADTime</span><span class="p">(</span> <span class="n">date</span><span class="p">(</span><span class="mi">1601</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="n">hours</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="n">time_zone_ptr</span><span class="p">(),</span> <span class="n">local_date_time</span><span class="o">::</span><span class="n">NOT_DATE_TIME_ON_ERROR</span><span class="p">);</span> <span class="n">time_duration</span> <span class="nf">timeInterval</span><span class="p">(</span><span class="n">now</span><span class="p">.</span><span class="n">utc_time</span><span class="p">()</span> <span class="o">-</span> <span class="n">baseADTime</span><span class="p">.</span><span class="n">utc_time</span><span class="p">());</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;BaseTime: &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">baseADTime</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;Time: &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">now</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;MicroSeconds: &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">timeInterval</span><span class="p">.</span><span class="n">total_microseconds</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;MilliSeconds: &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">timeInterval</span><span class="p">.</span><span class="n">total_milliseconds</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;Seconds: &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">timeInterval</span><span class="p">.</span><span class="n">total_seconds</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> </pre></div></div><p> produces the following output: </p> <div class="wiki-code"><div class="code"><pre>BaseTime: <span class="m">1601</span>-Jan-01 <span class="m">00</span>:00:00 UTC Time: <span class="m">2012</span>-Feb-08 <span class="m">12</span>:36:54 UTC MicroSeconds: <span class="m">12973178214000000</span> MilliSeconds: <span class="m">12973178214000</span> Seconds: <span class="m">88276326</span> </pre></div></div><p> In case you're wondering why it would be interesting to calculate the time interval between 01-01-1601 and now: the time representation in Microsoft Active Directory uses a time representation based on the time between 1601 and now. </p> <p> It is at least counterintuitive that types with a higher resolution/precision are able to store larger intervals. According to the documentation <a href="http://www.boost.org/doc/libs/1_47_0/doc/html/date_time/posix_time.html "> documentation</a>, all "total_x" methods should return the same type, that doesn't seem to be the case. </p> <p> It is probably possible to use type traits to set the internal representation, but this is somewhat complex to do. (Thanks to Andrei Korostelev for pointing out this possibility). In any case as far as I know it cannot be done in an obvious/self-explanatory way. </p> <p> Another proposed solution would be to add a template parameter to total_seconds and similar methods so you can explicitly specify the representation type. For example: </p> <div class="wiki-code"><div class="code"><pre><span class="kt">int_fast64_t</span> <span class="n">numSeconds</span> <span class="o">=</span> <span class="n">timeInterval</span><span class="p">.</span><span class="n">total_seconds</span><span class="o">&lt;</span><span class="kt">int_fast64_t</span><span class="o">&gt;</span><span class="p">()</span> </pre></div></div><p> This way a user explicitly states what he wants and will not run into surprises. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Tue, 02 Aug 2016 05:45:16 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3109#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3109#comment:3</guid> <description> <p> This problem still exists in Boost version 1.61. It may also cause confusion in calculating total milliseconds from epoch(1/1/1970). </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Tue, 02 Aug 2016 05:45:20 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3109#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3109#comment:3</guid> <description> <p> This problem still exists in Boost version 1.61. It may also cause confusion in calculating total milliseconds from epoch(1/1/1970). </p> </description> <category>Ticket</category> </item> </channel> </rss>