[07/59] Document mktime out-of-range + tm_isdst
Checks
Context |
Check |
Description |
redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
Commit Message
* manual/time.texi (Broken-down Time): Document mktime better
when dealing with out-of-range inputs and nonnegative tm_isdst.
Documentation problem reported by Florian Weimer in:
https://sourceware.org/pipermail/libc-alpha/2024-October/160310.html
---
manual/time.texi | 51 ++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 43 insertions(+), 8 deletions(-)
Comments
* Paul Eggert:
> +If local time ever observes daylight saving time, the @code{tm_isdst}
> +member is inspected after other members are brought into range. If
> +negative, @code{mktime} uses time zone data to determine whether
> +daylight saving time is in effect at the requested time. Then members
> +are adjusted if they would otherwise be inconsistent, e.g., by adding
> +or subtracting an hour if the broken-down time would otherwise have
> +the wrong @code{tm_isdst} member or would occur during a
> +spring-forward gap.
The “Then members are adjusted” part seems unclear to me. If tm_isdst
is negative, is there adjustment based on time zone offset? Would
that even be possible, given that tm_gmtoff may not have been
initialized?
> Ordinarily callers should specify a negative @code{tm_isdst} member.
> The main practical use for nonnegative @code{tm_isdst} is when a the
> broken-down time was produced by @code{localtime} or similar functions
> so its @code{tm_isdst} is already known to be correct.
Please clarify that gmtime does not count as a similar function in
this context.
On 2025-01-05 00:03, Florian Weimer wrote:
> The “Then members are adjusted” part seems unclear to me. If tm_isdst
> is negative, is there adjustment based on time zone offset?
Yes.
> Would that even be possible, given that tm_gmtoff may not have been
> initialized?
Yes, because mktime knows the timezone. It ignores tm_gmtoff when
initially determining the UTC offset; instread, it inspects the timezone
data and infers the UTC offset from that.
The attached followup patch attempts to clarify this.
>> Ordinarily callers should specify a negative @code{tm_isdst} member.
>> The main practical use for nonnegative @code{tm_isdst} is when a the
>> broken-down time was produced by @code{localtime} or similar functions
>> so its @code{tm_isdst} is already known to be correct.
>
> Please clarify that gmtime does not count as a similar function in
> this context.
Also done in the attached, which says that gmtime counts as similar only
if local time is UTC.
Thanks for the review.
@@ -1075,9 +1075,11 @@ This is a flag that indicates whether daylight saving time is (or was, or
will be) in effect at the time described. The value is positive if
daylight saving time is in effect, zero if it is not, and negative if the
information is not available.
-Although this flag is useful when passing a broken-down time to the
-@code{mktime} function, for other uses this flag should be ignored and
-the @code{tm_gmtoff} and @code{tm_zone} fields should be inspected instead.
+This flag should not be inspected; the @code{tm_gmtoff} and
+@code{tm_zone} fields should be inspected instead.
+However, before calling @code{mktime} this flag should be set,
+and set to a negative value unless the application already has a
+correct value for the specified time.
@item long int tm_gmtoff
This field describes the time zone that was used to compute this
@@ -1297,13 +1299,46 @@ The @code{mktime} function ignores the specified contents of the
members of the broken-down time
structure. It uses the values of the other components to determine the
calendar time; it's permissible for these components to have
-unnormalized values outside their normal ranges. The last thing that
-@code{mktime} does is adjust the components of the @var{brokentime}
+unnormalized values outside their normal ranges.
+Out-of-range members are brought into range in reverse order of
+significance: for example, an hour equal to @minus{}1 is first
+increased to 23 and the day decreased by 1, before an out-of-range day
+is brought into range.
+
+If local time ever observes daylight saving time, the @code{tm_isdst}
+member is inspected after other members are brought into range. If
+negative, @code{mktime} uses time zone data to determine whether
+daylight saving time is in effect at the requested time. Then members
+are adjusted if they would otherwise be inconsistent, e.g., by adding
+or subtracting an hour if the broken-down time would otherwise have
+the wrong @code{tm_isdst} member or would occur during a
+spring-forward gap.
+The heuristic used for these adjustments is unspecified.
+@c The heuristic conforms to POSIX.1-2024 for non-geographic timezones.
+@c POSIX-1.2024 is incorrect (and unclear to boot) for geographic timezones,
+@c which is the normal use cases for non-UTC timezones these days.
+
+Ordinarily callers should specify a negative @code{tm_isdst} member.
+The main practical use for nonnegative @code{tm_isdst} is when a the
+broken-down time was produced by @code{localtime} or similar functions
+so its @code{tm_isdst} is already known to be correct. This might
+happen if the original simple time has been lost, in which case the
+nonnegative @code{tm_isdst} usually (but not always) lets
+@code{mktime} disambiguate broken-down times within an overlapping
+window after the clock jumps back during a daylight saving or other
+transition. A nonnegative @code{tm_isdst} might also happen when
+doing broken-down time arithmetic by calling @code{localtime}, adding
+or subtracting to (say) @code{tm_mday}, and then calling
+@code{mktime}; in this case, though, if the time arithmetic crosses a
+time transition boundary the results are unspecified.
+
+If successful, @code{mktime} uses the equivalent of @code{localtime}
+to set all the components of the @code{*@var{brokentime}}
structure, including the members that were initially ignored.
If the specified broken-down time cannot be represented as a simple time,
@code{mktime} returns a value of @code{(time_t)(-1)} and does not modify
-the contents of @var{brokentime}.
+@code{*@var{brokentime}}.
Calling @code{mktime} also sets the time zone state as if
@code{tzset} were called; @code{mktime} uses this information instead
@@ -1342,8 +1377,8 @@ available. @code{timelocal} is rather rare.
@c tzfile_compute(!use_localtime) ok
@code{timegm} is functionally identical to @code{mktime} except it
-always takes the input values to be UTC
-regardless of any local time zone setting.
+operates in UTC, so it ignores @code{tm_isdst} other than setting it
+to zero when successful.
Note that @code{timegm} is the inverse of @code{gmtime}.