A NOTE has been added to this issue. 
====================================================================== 
https://austingroupbugs.net/view.php?id=1627 
====================================================================== 
Reported By:                kre
Assigned To:                
====================================================================== 
Project:                    1003.1(2016/18)/Issue7+TC2
Issue ID:                   1627
Category:                   System Interfaces
Type:                       Enhancement Request
Severity:                   Objection
Priority:                   normal
Status:                     New
Name:                       Robert Elz 
Organization:                
User Reference:              
Section:                    XSH 3/mktime 
Page Number:                1331 
Line Number:                44310-44332, 44361 
Interp Status:              --- 
Final Accepted Text:         
====================================================================== 
Date Submitted:             2023-01-05 12:17 UTC
Last Modified:              2023-08-07 09:05 UTC
====================================================================== 
Summary:                    XSH 3 / mktime() is woefully underspecified
======================================================================
Relationships       ID      Summary
----------------------------------------------------------------------
related to          0001614 XSH 3/mktime does not specify EINVAL an...
====================================================================== 

---------------------------------------------------------------------- 
 (0006415) geoffclare (manager) - 2023-08-07 09:05
 https://austingroupbugs.net/view.php?id=1627#c6415 
---------------------------------------------------------------------- 
Suggested resolution ...

On page 113 line 3186 section 4.16 Seconds Since the Epoch,
change:<blockquote>The relationship between the actual time of day and the
current value for seconds since the Epoch is
unspecified.</blockquote>to:<blockquote>The relationship between the actual
date and time in Coordinated Universal Time, as determined by the
International Earth Rotation Service, and the system's current value for
seconds since the Epoch is unspecified.</blockquote>
On page 1331 line 44320 section mktime(), after applying bugs 1613 and 1614
change:<blockquote>The relationship between the <b>tm</b> structure
(defined in the <b><time.h></b> header) and the time in seconds since the
Epoch is that the result shall be as specified in the expression given in
the definition of seconds since the Epoch (see [xref to XBD 4.19])
corrected for the offset of the timezone's standard time from Coordinated
Universal Time and further corrected (if applicable--see below) for
Daylight Saving Time, where the names other than <i>tm_yday</i> in the
structure and in the expression correspond, and the <i>tm_yday</i> value
used in the expression is the day of the year from 0 to 365 inclusive,
calculated from the members of the <b>tm</b> structure specified
above.</blockquote>to:<blockquote>The <i>mktime<i>() function shall
calculate the time in seconds since the Epoch to be returned as if by
manipulating the members of the <b>tm</b> structure according to the
following steps.

1. The <i>tm_sec</i> member may, but should not, be brought into the range
0 to 60, inclusive. For each 60 seconds added to or subtracted from
<i>tm_sec</i>, a decrement or increment, respectively, of 1 minute shall be
saved for later application.

2. The <i>tm_min</i> member shall be brought into the range 0 to 59,
inclusive, and any saved decrement or increment of minutes shall then be
applied, repeating the range adjustment afterwards if necessary. For each
60 minutes added to or subtracted from <i>tm_min</i>, a decrement or
increment, respectively, of 1 hour shall be saved for later application.

3. The <i>tm_hour</i> member shall be brought into the range 0 to 23,
inclusive, and any saved decrement or increment of hours shall then be
applied, repeating the range adjustment afterwards if necessary. For each
24 hours added to or subtracted from <i>tm_hour</i>, a decrement or
increment, respectively, of 1 day shall be saved for later application.

4. The <i>tm_mon</i> member shall be brought into the range 0 to 11,
inclusive. For each 12 months added to or subtracted from <i>tm_mon</i>, a
decrement or increment, respectively, of 1 year shall be saved for later
use.

5. The <i>tm_mday</i> member shall be brought into the range 1 to 31,
inclusive, and any saved decrement or increment of days shall then be
applied, repeating the range adjustment afterwards if necessary.
Adjustments downwards shall be applied by subtracting the number of days
(according to the Gregorian calendar) in month <i>tm_mon</i>+1 of the year
obtained by adding/subtracting any saved increment/decrement of years to
the value <i>tm_year</i>+1900, and then incrementing <i>tm_mon</i> by 1,
repeated as necessary. Adjustments upwards shall be applied by adding the
number of days in the month before month <i>tm_mon</i>+1 of the year
obtained by adding/subtracting any saved increment/decrement of years to
the value <i>tm_year</i>+1900, and then decrementing <i>tm_mon</i> by 1,
repeated as necessary. During these adjustments, the <i>tm_mon</i> value
shall be kept within the range 0 to 11, inclusive, by applying step 4 as
necessary.

6. If the <i>tm_mday</i> member is greater than the number of days in month
<i>tm_mon</i>+1 of the year obtained by adding/subtracting any saved
increment/decrement of years to the value <i>tm_year</i>+1900, that number
of days shall be subtracted from <i>tm_mday</i>, and <i>tm_mon</i> shall be
incremented by 1. If this results in <i>tm_mon</i> having the value 12,
step 4 shall be applied.

7. The number of seconds since the Epoch in Coordinated Universal Time
shall be calculated from the range-corrected values of the relevant
<b>tm</b> structure members (or the original value where a member was not
range corrected) as specified in the expression given in the definition of
seconds since the Epoch (see [xref to XBD 4.19]), where the names other
than <i>tm_year</i> and <i>tm_yday</i> in the structure and in the
expression correspond, the <i>tm_year</i> value used in the expression is
the <i>tm_year</i> in the structure plus/minus any saved
increment/decrement of years, and the <i>tm_yday</i> value used in the
expression is the day of the year from 0 to 365 inclusive, calculated from
the <i>tm_mon</i> and </i>tm_mday</i> members of the <b>tm</b> structure,
for that year.

8. The time since the Epoch shall be corrected for the offset of the local
timezone's standard time from Coordinated Universal Time.

9. The time since the Epoch shall be further corrected (if applicable--see
below) for Daylight Saving Time.</blockquote>
On page 1332 line 44357 section mktime(), change APPLICATION USAGE from
"None" to:<blockquote>When using <i>mktime</i>() to add or subtract a fixed
time period (one that always corresponds to a fixed number of seconds) to
or from a broken-down time in the local timezone, reliable results for
arbitrary <i>TZ</i> can only be assured by using <i>mktime</i>() to convert
the original broken-down time to a time since the Epoch, adding or
subtracting the desired number of seconds to that value, and then calling
<i>localtime</i>() with the result. The alternative of adjusting the
broken-down time before calling <i>mktime</i>() may produce unexpected
results if the original and updated times are on different sides of a
geographical timezone change. On implementations that follow the
recommendation of not range-correcting <i>tm_sec</i> (see step 1 in the
DESCRIPTION), reliable results can also be assured by adding or subtracting
the desired number of seconds to <i>tm_sec</i> (and not modifying any other
members of the <b>tm</b> structure). In applications needing to be portable
to non-POSIX systems where the <b>time_t</b> encoding is not a count of
seconds, it is recommended that conditional compilation is used such that
the adjustment is performed on the <i>mktime</i>() return value when
possible, and otherwise on the <i>tm_sec</i> member. For timezones that are
known not to have geographical timezone changes, such as <tt>TZ=UTC0</tt>,
adjustments using just <i>mktime</i>() do not have this problem.

The way the <i>mktime</i>() function interprets out-of-range <b>tm</b>
structure fields might not produce the expected result when multiple
adjustments are made at the same time. For example, if an application tries
to go back one day first and then one year by calling localtime(),
decrementing <i>tm_mday</i> and <i>tm_year</i>, and then calling
<i>mktime</i>() this would not produce the expected result if it was called
on 2021-03-01 because <i>mktime</i>() would see the supplied year as 2020
(a leap year) and correct Mar 0 to Feb 29, whereas the intended result was
Feb 28. Such issues can be avoided by doing multiple adjustments one at a
time when the order in which they are done matters.

Examples of how <i>mktime</i>() handles some adjustments are: <ul><li>If
given Feb 29 in a non-leap year it treats that as the day after Feb 28 and
gives back Mar 1.</li>
<li>If given Feb 0 it treats that as the day before Feb 1 and gives back
Jan 31.</li>
<li>If given 21:65 it treats that as 6 minutes after 21:59 and gives back
22:05.</li>
<li>If given <i>tm_isdst</i>=0 for a time when DST is in effect, it gives
back a positive <i>tm_isdst</i> and alters the other fields
appropriately.</li>
<li>If there is a DST transition where 02:00 standard time becomes 03:00
DST and <i>mktime</i>() is given 02:30 (with negative <i>tm_isdst</i>), it
treats that as either 30 minutes after 02:00 standard time or 30 minutes
before 03:00 DST and gives back a zero or positive <i>tm_isdst</i>,
respectively, with the <i>tm_hour</i> field altered appropriately.</li>
<li>If a geographical timezone changes its UTC offset such that ``old
00:00'' becomes ``new 00:30'' and <i>mktime</i>() is given 00:20, it treats
that as either 20 minutes after ``old 00:00'' or 10 minutes before ``new
00:30'', and gives back appropriately altered <b>struct tm</b> fields.</li>
</ul>
If an application wants to check whether a given broken-down time is one
that is skipped over, it can do so by seeing whether the <i>tm_mday</i>,
<i>tm_hour</i>, and <i>tm_min</i> values it gets back from <i>mktime</i>()
are the same ones it fed in. Just checking <i>tm_hour</i> and <i>tm_min</i>
might appear at first sight to suffice, but <i>tm_mday</i> could also
change--without <i>tm_hour</i> and <i>tm_min</i> changing--if, for example,
<i>TZ</i> is set to "ABC12XYZ-12" (which might be used in a torture test)
or if a geographical timezone changes the offset from Coordinated Universal
Time of its standard time by 24 hours.</blockquote>
On page 1332 line 44359 section mktime(), change RATIONALE from "None"
to:<blockquote>Implementations are encouraged not to range-correct
<i>tm_sec</i> (see step 1 in the DESCRIPTION) in order for the results of
making an adjustment to <i>tm_sec</i> always to be equivalent to making the
same adjustment to the value returned by <i>mktime</i>(), even when the
original and updated times are on different sides of a geographical
timezone change.  This provides a way for applications to do reliable
fixed-period adjustment using only <i>mktime</i>(), as described in
APPLICATION USAGE.

The described method for range-correcting the <b>tm</b> structure members
uses separate variables to hold adjustment values to be applied later to
other members, or (for the year adjustment) used in later calculations,
because this is one way of avoiding intermediate member values that are not
representable as an <b>int</b>. Implementations may use other methods; all
that is required is that <i>tm_year</i> is the only member for which an
[EOVERFLOW] error can occur.

The described method for range-correcting <i>tm_mday</i> would, if
implemented that way, be highly inefficient for very large values. The
efficiency can be improved by observing that any period of 400 years always
has the same number of days, so the month-by-month correction method need
only be applied for a maximum of 4800 months.</blockquote>
On page 1332 line 44361 section mktime(), change FUTURE DIRECTIONS from
"None" to:<blockquote>A future version of this standard may require that
<i>mktime</i>() does not perform the optional range correction of the
<i>tm_sec</i> member of the <b>tm</b> structure described at step 1 in the
DESCRIPTION.

A future version of this standard is expected to add a <i>timegm</i>()
function that is similar to <i>mktime</i>(), except that the <b>tm</b>
structure pointed to by <i>timeptr</i> contains a broken-down time in
Coordinated Universal Time (rather than the local timezone), where
references to <i>localtime</i>() are replaced by references to
<i>gmtime</i>(), and where there are no timezone offset or Daylight Saving
Time adjustments. A combination of <i>gmtime</i>() and <i>timegm</i>() will
be the expected way to perform arithmetic upon a <b>time_t</b> value and
remain compatible with the ISO C standard (where the internal structure of
a <b>time_t</b> is not specified), since attempting such manipulations
using <i>localtime</i>() and <i>mktime</i>() can lead to unexpected
results.</blockquote> 

Issue History 
Date Modified    Username       Field                    Change               
====================================================================== 
2023-01-05 12:17 kre            New Issue                                    
2023-01-05 12:17 kre            Name                      => Robert Elz      
2023-01-05 12:17 kre            Section                   => XSH 3/mktime    
2023-01-05 12:17 kre            Page Number               => 1331            
2023-01-05 12:17 kre            Line Number               => 44310-44332, 44361
2023-01-20 20:54 mirabilos      Note Added: 0006118                          
2023-07-25 14:09 geoffclare     Relationship added       related to 0001614  
2023-08-07 09:05 geoffclare     Note Added: 0006415                          
======================================================================


  • [1003.1(2016... Austin Group Bug Tracker via austin-group-l at The Open Group
    • [1003.1... Austin Group Bug Tracker via austin-group-l at The Open Group
    • [1003.1... Austin Group Bug Tracker via austin-group-l at The Open Group
    • [1003.1... Austin Group Bug Tracker via austin-group-l at The Open Group
    • [1003.1... Austin Group Bug Tracker via austin-group-l at The Open Group
    • [1003.1... Austin Group Bug Tracker via austin-group-l at The Open Group
    • [1003.1... Austin Group Bug Tracker via austin-group-l at The Open Group

Reply via email to