[BACK]Return to difftime.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / time

File: [cvs.NetBSD.org] / src / lib / libc / time / difftime.c (download)

Revision 1.19, Fri Oct 19 23:05:35 2018 UTC (5 years, 6 months ago) by christos
Branch: MAIN
CVS Tags: pgoyette-compat-20190127, pgoyette-compat-20190118, pgoyette-compat-1226, pgoyette-compat-1126, pgoyette-compat-1020
Changes since 1.18: +4 -2 lines

Update to 2018f:

  Changes to code

    zic now always generates TZif files where time type 0 is used for
    timestamps before the first transition.  This simplifies the
    reading of TZif files and should not affect behavior of existing
    TZif readers because the same set of time types is used; only
    their internal indexes may have changed.  This affects only the
    legacy zones EST5EDT, CST6CDT, MST7MDT, PST8PDT, CET, MET, and
    EET, which previously used nonzero types for these timestamps.

    Because of the type 0 change, zic no longer outputs a dummy
    transition at time -2**59 (before the Big Bang), as clients should
    no longer need this to handle historical timestamps correctly.
    This reverts a change introduced in 2013d and shrinks most TZif
    files by a few bytes.

    zic now supports negative time-of-day in Rule and Leap lines, e.g.,
    "Rule X min max - Apr lastSun -6:00 1:00 -" means the transition
    occurs at 18:00 on the Saturday before the last Sunday in April.
    This behavior was documented in 2018a but the code did not
    entirely match the documentation.

    localtime.c no longer requires at least one time type in TZif
    files that lack transitions or have a POSIX-style TZ string.  This
    future-proofs the code against possible future extensions to the
    format that would allow TZif files with POSIX-style TZ strings and
    without transitions or time types.

    A read-access subscript error in localtime.c has been fixed.
    It could occur only in TZif files with timecnt == 0, something that
    does not happen in practice now but could happen in future versions.

    localtime.c no longer ignores TZif POSIX-style TZ strings that
    specify only standard time.  Instead, these TZ strings now
    override the default time type for timestamps after the last
    transition (or for all time stamps if there are no transitions),
    just as DST strings specifying DST have always done.

    leapseconds.awk now outputs "#updated" and "#expires" comments,
    and supports leap seconds at the ends of months other than June
    and December.  (Inspired by suggestions from Chris Woodbury.)

  Changes to documentation

    New restrictions: A Rule name must start with a character that
    is neither an ASCII digit nor "-" nor "+", and an unquoted name
    should not use characters in the set "!$%&'()*,/:;<=>?@[\]^`{|}~".
    The latter restriction makes room for future extensions (a
    possibility noted by Tom Lane).

    tzfile.5 now documents what time types apply before the first and
    after the last transition, if any.

    Documentation now uses the spelling "timezone" for a TZ setting
    that determines timestamp history, and "time zone" for a
    geographic region currently sharing the same standard time.

    The name "TZif" is now used for the tz binary data format.

    tz-link.htm now mentions the A0 TimeZone Migration utilities.
    (Thanks to Aldrin Martoq for the link.)

/*	$NetBSD: difftime.c,v 1.19 2018/10/19 23:05:35 christos Exp $	*/

/* Return the difference between two timestamps.  */

/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
*/

#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
static char	elsieid[] = "@(#)difftime.c	8.1";
#else
__RCSID("$NetBSD: difftime.c,v 1.19 2018/10/19 23:05:35 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */

/*LINTLIBRARY*/

#include "private.h"	/* for time_t and TYPE_SIGNED */

/* Return -X as a double.  Using this avoids casting to 'double'.  */
static double
dminus(double x)
{
	return -x;
}

double
difftime(time_t time1, time_t time0)
{
	/*
	** If double is large enough, simply convert and subtract
	** (assuming that the larger type has more precision).
	*/
	/*CONSTCOND*/
	if (sizeof (time_t) < sizeof (double)) {
		double t1 = time1, t0 = time0;
		return t1 - t0;
 	}

	/*
	** The difference of two unsigned values can't overflow
	** if the minuend is greater than or equal to the subtrahend.
	*/
	if (!TYPE_SIGNED(time_t))
		return time0 <= time1 ? time1 - time0 : dminus(time0 - time1);

	/* Use uintmax_t if wide enough.  */
	/*CONSTCOND*/
	if (sizeof (time_t) <= sizeof (uintmax_t)) {
		uintmax_t t1 = time1, t0 = time0;
		return time0 <= time1 ? t1 - t0 : dminus(t0 - t1);
	}

	/*
	** Handle cases where both time1 and time0 have the same sign
	** (meaning that their difference cannot overflow).
	*/
	if ((time1 < 0) == (time0 < 0))
		return time1 - time0;

	/*
	** The values have opposite signs and uintmax_t is too narrow.
	** This suffers from double rounding; attempt to lessen that
	** by using long double temporaries.
	*/
	{
		long double t1 = time1, t0 = time0;
		return t1 - t0;
	}
}