$NetBSD: time2posix.3,v 1.23 2022/12/11 17:57:23 christos Exp $
@(#)time2posix.3 7.7
This file is in the public domain, so clarified as of
1996-06-05 by Arthur David Olson.
.Dd October 6, 2014 .Dt TIME2POSIX 3 .Os .Sh NAME .Nm time2posix , .Nm time2posix_z , .Nm posix2time , .Nm posix2time_z .Nd convert seconds since the Epoch .Sh LIBRARY .Lb libc .Sh SYNOPSIS n time.h .Ft time_t .Fn time2posix "time_t t" .Ft time_t .Fn time2posix_z "const timezone_t tz" "time_t t" .Ft time_t .Fn posix2time "time_t t" .Ft time_t .Fn posix2time_z "const timezone_t tz" "time_t t" .Sh DESCRIPTION .St -p1003.1 requires the .Ft time_t value of .Dv 536457599 to stand for .Dl Wed Dec 31 23:59:59 UTC 1986 . This effectively implies that POSIX .Ft time_t values cannot include leap seconds and, therefore, that the system time must be adjusted as each leap occurs.

p If the time package is configured with leap-second support enabled, however, no such adjustment is needed and .Va time_t values continue to increase over leap events (as a true .Dq "seconds since..." value). This means that these values will differ from those required by POSIX by the net number of leap seconds inserted since the Epoch.

p Typically this is not a problem as the type .Va time_t is intended to be (mostly) opaque \(em .Va time_t values should only be obtained-from and passed-to functions such as .Xr time 3 , .Xr localtime 3 , .Xr localtime_r 3 , .Xr localtime_rz 3 , .Xr mktime 3 , .Xr mktime_z 3 , and .Xr difftime 3 . However, POSIX gives an arithmetic expression for directly computing a .Va time_t value from a given date/time, and the same relationship is assumed by some (usually older) applications. Any programs creating/dissecting .Va time_t values using such a relationship will typically not handle intervals over leap seconds correctly.

p The .Fn time2posix , .Fn time2posix_z , .Fn posix2time , and .Fn posix2time_z functions are provided to address this .Va time_t mismatch by converting between local .Va time_t values and their POSIX equivalents. This is done by accounting for the number of time-base changes that would have taken place on a POSIX system as leap seconds were inserted or deleted. These converted values can then be used in lieu of correcting the older applications, or when communicating with POSIX-compliant systems.

p .Fn time2posix and .Fn time2posix_z are single-valued. That is, every local .Va time_t corresponds to a single POSIX .Va time_t . .Fn posix2time and .Fn posix2time are less well-behaved: for a positive leap second hit the result is not unique, and for a negative leap second hit the corresponding POSIX .Va time_t doesn't exist so an adjacent value is returned. Both of these are good indicators of the inferiority of the POSIX representation.

p The .Dq z variants of the two functions behave exactly like their counterparts, but they operate in the given .Fa tz argument which was previously allocated using .Xr tzalloc 3 and are re-entrant.

p The following table summarizes the relationship between a .Va time_t and its conversion to, and back from, the POSIX representation over the leap second inserted at the end of June, 1993. l -column "93/06/30" "23:59:59" "A+0" "X=time2posix(T)" "posix2time(X)" -offset indent t Sy DATE TIME T X=time2posix(T) posix2time(X) t 93/06/30 23:59:59 A+0 B+0 A+0 t 93/06/30 23:59:60 A+1 B+1 A+1 or A+2 t 93/07/01 00:00:00 A+2 B+1 A+1 or A+2 t 93/07/01 00:00:01 A+3 B+2 A+3 .El

p A leap second deletion would look like... l -column "??/06/30" "23:59:58" "A+0" "X=time2posix(T)" "posix2time(X)" -offset indent t Sy DATE TIME T X=time2posix(T) posix2time(X) t ??/06/30 23:59:58 A+0 B+0 A+0 t ??/07/01 00:00:00 A+1 B+2 A+1 t ??/07/01 00:00:01 A+2 B+3 A+2 .El [Note: posix2time(B+1) => A+0 or A+1]

p If leap-second support is not enabled, local .Va time_t and POSIX .Va time_t values are equivalent, and both .Fn time2posix and .Fn posix2time degenerate to the identity function. .Sh SEE ALSO .Xr difftime 3 , .Xr localtime 3 , .Xr localtime_r 3 , .Xr localtime_rz 3 , .Xr mktime 3 , .Xr mktime_z 3 , .Xr time 3 , .Xr tzalloc 3