<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 3262: Formatting of negative durations is not specified</title>
<meta property="og:title" content="Issue 3262: Formatting of negative durations is not specified">
<meta property="og:description" content="C++ library issue. Status: C++20">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue3262.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++20">C++20</a> status.</em></p>
<h3 id="3262"><a href="lwg-defects.html#3262">3262</a>. Formatting of negative durations is not specified</h3>
<p><b>Section:</b> 30.12 <a href="https://wg21.link/time.format">[time.format]</a> <b>Status:</b> <a href="lwg-active.html#C++20">C++20</a>
 <b>Submitter:</b> Tomasz Kami&nacute;ski <b>Opened:</b> 2019-08-18 <b>Last modified:</b> 2021-02-25</p>
<p><b>Priority: </b>2
</p>
<p><b>View other</b> <a href="lwg-index-open.html#time.format">active issues</a> in [time.format].</p>
<p><b>View all other</b> <a href="lwg-index.html#time.format">issues</a> in [time.format].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++20">C++20</a> status.</p>
<p><b>Discussion:</b></p>
<p>
The current specification of the formatting for <code>std::chrono::duration</code> and 
<code>std::hh_mm_ss</code> types is unclear in regards the the handling of negative values. 
To illustrate:
</p>
<blockquote><pre>
std::cout &lt;&lt; std::format("%H:%M:%S", -10'000s); <i>// prints either -02:46:40 or -02:-46:-40</i>
</pre></blockquote>
<p>
The indented behavior (and currently implemented, see 
<a href="https://wandbox.org/permlink/mrw03IaAldP7Bdx1">here</a>) is to apply the
sign once, before the leftmost converted field.
</p>

<p><i>[2019-09-14 Priority set to 2 based on reflector discussion]</i></p>


<strong>Previous resolution [SUPERSEDED]:</strong>
<blockquote class="note">
<p>This wording is relative to <a href="https://wg21.link/n4830">N4830</a>.</p>

<blockquote class="note">
<p>
[<i>Drafting note:</i> With the above clarification, the specification of the
<code>operator&lt;&lt;</code> for <code>hh_mm_ss</code> may be simplified to
<code>format("{:%T}", hms)</code>.]
</p>
</blockquote>

<ol>
<li><p>Modify 30.12 <a href="https://wg21.link/time.format">[time.format]</a> as indicated:</p>

<blockquote>
<p>
-2- Each conversion specifier <i>conversion-spec</i> is replaced by appropriate 
characters as described in Table [tab:time.format.spec]. Some of the conversion 
specifiers depend on the locale that is passed to the formatting function if 
the latter takes one, or the global locale otherwise. If the formatted object 
does not contain the information the conversion specifier refers to, an 
exception of type <code>format_error</code> is thrown.
<p/>
<ins>-?- The result of formatting a <code>std::chrono::duration</code> instance holding 
a negative value, or of an <code>hh_mm_ss</code> object <code>h</code> for which <code>h.is_negative()</code> 
is <code>true</code>, is equivalent to the output of the corresponding positive value, 
with a <code>-</code> character placed before the replacement of the leftmost conversion
specifier.</ins>
<p/>
<ins>[<i>Example:</i></ins>
</p>
<blockquote><pre>
<ins>cout &lt;&lt; format("%T", -10'000s); <i>// prints:</i> -02:46:40
cout &lt;&lt; format("%H:%M:%S", -10'000s); <i>// prints:</i> -02:46:40
cout &lt;&lt; format("minutes %M, hours %H, seconds %S", -10'000s); <i>// prints:</i> minutes -46, hours 02, seconds 40</ins>
</pre></blockquote>
<p>
<ins>&mdash; <i>end example</i>]</ins>
<p/>
-3- Unless explicitly requested, [&hellip;]
</p>
</blockquote>
</li>

<li><p>Modify 30.9.3 <a href="https://wg21.link/time.hms.nonmembers">[time.hms.nonmembers]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class charT, class traits, class Duration&gt;
basic_ostream&lt;charT, traits&gt;&amp;
operator&lt;&lt;(basic_ostream&lt;charT, traits&gt;&amp; os, const hh_mm_ss&lt;Duration&gt;&amp; hms);
</pre>
<blockquote>
<p>
-1- <i>Effects:</i> Equivalent to:
</p>
<blockquote><pre>
return os &lt;&lt; format(os.getloc(),
             <del>hms.is_negative() ? <i>STATICALLY-WIDEN</i>&lt;charT&gt;("-{:%T}")
                               : </del><i>STATICALLY-WIDEN</i>&lt;charT&gt;("{:%T}"),
             <del>abs(</del>hms<del>.to_duration())</del>);
</pre></blockquote>
</blockquote>
</blockquote>
</li>
</ol>
</blockquote>

<p><i>[2019-09-14; Howard improves wording]</i></p>

<p><i>[2020-02; Status set to Immediate after LWG discussion Thursday in Prague. (Minor example wording cleanup)]</i></p>



<p id="res-3262"><b>Proposed resolution:</b></p>
<p>This wording is relative to <a href="https://wg21.link/n4830">N4830</a>.</p>

<blockquote class="note">
<p>
[<i>Drafting note:</i> With the above clarification, the specification of the
<code>operator&lt;&lt;</code> for <code>hh_mm_ss</code> may be simplified to
<code>format("{:%T}", hms)</code>.]
</p>
</blockquote>

<ol>
<li><p>Modify 30.12 <a href="https://wg21.link/time.format">[time.format]</a> as indicated:</p>

<blockquote>
<p>
-2- Each conversion specifier <i>conversion-spec</i> is replaced by appropriate 
characters as described in Table [tab:time.format.spec]. Some of the conversion 
specifiers depend on the locale that is passed to the formatting function if 
the latter takes one, or the global locale otherwise. If the formatted object 
does not contain the information the conversion specifier refers to, an 
exception of type <code>format_error</code> is thrown.
<p/>
<ins>-?- The result of formatting a <code>std::chrono::duration</code> instance holding 
a negative value, or of an <code>hh_mm_ss</code> object <code>h</code> for which <code>h.is_negative()</code> 
is <code>true</code>, is equivalent to the output of the corresponding positive value, 
with a <code><i>STATICALLY-WIDEN</i>&lt;charT&gt;("-")</code> character sequence placed 
before the replacement of the leftmost conversion specifier.</ins>
<p/>
<ins>[<i>Example:</i></ins>
</p>
<blockquote><pre>
<ins>cout &lt;&lt; format("{%:T}", -10'000s); <i>// prints:</i> -02:46:40
cout &lt;&lt; format("{:%H:%M:%S}", -10'000s); <i>// prints:</i> -02:46:40
cout &lt;&lt; format("{:minutes %M, hours %H, seconds %S}", -10'000s); <i>// prints:</i> minutes -46, hours 02, seconds 40</ins>
</pre></blockquote>
<p>
<ins>&mdash; <i>end example</i>]</ins>
<p/>
-3- Unless explicitly requested, [&hellip;]
</p>
</blockquote>
</li>

<li><p>Modify 30.9.3 <a href="https://wg21.link/time.hms.nonmembers">[time.hms.nonmembers]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class charT, class traits, class Duration&gt;
basic_ostream&lt;charT, traits&gt;&amp;
operator&lt;&lt;(basic_ostream&lt;charT, traits&gt;&amp; os, const hh_mm_ss&lt;Duration&gt;&amp; hms);
</pre>
<blockquote>
<p>
-1- <i>Effects:</i> Equivalent to:
</p>
<blockquote><pre>
return os &lt;&lt; format(os.getloc(),
             <del>hms.is_negative() ? <i>STATICALLY-WIDEN</i>&lt;charT&gt;("-{:%T}")
                               : </del><i>STATICALLY-WIDEN</i>&lt;charT&gt;("{:%T}"),
             <del>abs(</del>hms<del>.to_duration())</del>);
</pre></blockquote>
</blockquote>
</blockquote>
</li>
</ol>



</body>
</html>
