2009-03-04 04:28:35 +01:00
|
|
|
/*
|
|
|
|
** This file is in the public domain, so clarified as of
|
|
|
|
** 1996-06-05 by Arthur David Olson.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*LINTLIBRARY*/
|
|
|
|
|
Upgrade to tzcode2013f plus Android modifications (from tzcode2013d plus Android modifications).
localtime.c and strftime.c are still quite different from upstream because of
our extensions, but the other files continue to be identical, and the two
exceptions should be otherwise identical.
From the tzcode2013e release notes:
Changes affecting Godthab time stamps after 2037 if version mismatch
Allow POSIX-like TZ strings where the transition time's hour can
range from -167 through 167, instead of the POSIX-required 0
through 24. E.g., TZ='FJT-12FJST,M10.3.1/146,M1.3.4/75' for the
new Fiji rules. This is a more-compact way to represent
far-future time stamps for America/Godthab, America/Santiago,
Antarctica/Palmer, Asia/Gaza, Asia/Hebron, Asia/Jerusalem,
Pacific/Easter, and Pacific/Fiji. Other zones are unaffected by
this change. (Derived from a suggestion by Arthur David Olson.)
Allow POSIX-like TZ strings where daylight saving time is in
effect all year. E.g., TZ='WART4WARST,J1/0,J365/25' for Western
Argentina Summer Time all year. This supports a more-compact way
to represent the 2013d data for America/Argentina/San_Luis.
Because of the change for San Luis noted above this change does not
affect the current data. (Thanks to Andrew Main (Zefram) for
suggestions that improved this change.)
Where these two TZ changes take effect, there is a minor extension
to the tz file format in that it allows new values for the
embedded TZ-format string, and the tz file format version number
has therefore been increased from 2 to 3 as a precaution.
Version-2-based client code should continue to work as before for
all time stamps before 2038. Existing version-2-based client code
(tzcode, GNU/Linux, Solaris) has been tested on version-3-format
files, and typically works in practice even for time stamps after
2037; the only known exception is America/Godthab.
Changes affecting API
Support for floating-point time_t has been removed.
It was always dicey, and POSIX no longer requires it.
(Thanks to Eric Blake for suggesting to the POSIX committee to
remove it, and thanks to Alan Barrett, Clive D.W. Feather, Andy
Heninger, Arthur David Olson, and Alois Treindl, for reporting
bugs and elucidating some of the corners of the old floating-point
implementation.)
The signatures of 'offtime', 'timeoff', and 'gtime' have been
changed back to the old practice of using 'long' to represent UT
offsets. This had been inadvertently and mistakenly changed to
'int_fast32_t'. (Thanks to Christos Zoulos.)
The code avoids undefined behavior on integer overflow in some
more places, including gmtime, localtime, mktime and zdump.
Changes affecting code internals
Minor changes pacify GCC 4.7.3 and GCC 4.8.1.
Changes affecting documentation and commentary
Documentation and commentary is more careful to distinguish UT in
general from UTC in particular. (Thanks to Steve Allen.)
From the tzcode2013f release notes:
Changes affecting API
The types of the global variables 'timezone' and 'altzone' (if present)
have been changed back to 'long'. This is required for 'timezone'
by POSIX, and for 'altzone' by common practice, e.g., Solaris 11.
These variables were originally 'long' in the tz code, but were
mistakenly changed to 'time_t' in 1987; nobody reported the
incompatibility until now. The difference matters on x32, where
'long' is 32 bits and 'time_t' is 64. (Thanks to Elliott Hughes.)
Change-Id: I14937c42a391ddb865e4d89f0783961bcc6baa21
2013-09-27 09:04:30 +02:00
|
|
|
#include "private.h" /* for time_t and TYPE_SIGNED */
|
2009-03-04 04:28:35 +01:00
|
|
|
|
2013-07-13 02:31:11 +02:00
|
|
|
double ATTRIBUTE_CONST
|
|
|
|
difftime(const time_t time1, const time_t time0)
|
2009-03-04 04:28:35 +01:00
|
|
|
{
|
2013-07-13 02:31:11 +02:00
|
|
|
/*
|
|
|
|
** If (sizeof (double) > sizeof (time_t)) simply convert and subtract
|
|
|
|
** (assuming that the larger type has more precision).
|
|
|
|
*/
|
|
|
|
if (sizeof (double) > sizeof (time_t))
|
|
|
|
return (double) time1 - (double) time0;
|
|
|
|
if (!TYPE_SIGNED(time_t)) {
|
|
|
|
/*
|
|
|
|
** The difference of two unsigned values can't overflow
|
|
|
|
** if the minuend is greater than or equal to the subtrahend.
|
|
|
|
*/
|
|
|
|
if (time1 >= time0)
|
|
|
|
return time1 - time0;
|
|
|
|
else return -(double) (time0 - time1);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
** 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;
|
|
|
|
/*
|
|
|
|
** time1 and time0 have opposite signs.
|
|
|
|
** Punt if uintmax_t is too narrow.
|
|
|
|
** This suffers from double rounding; attempt to lessen that
|
|
|
|
** by using long double temporaries.
|
|
|
|
*/
|
|
|
|
if (sizeof (uintmax_t) < sizeof (time_t))
|
|
|
|
return (long double) time1 - (long double) time0;
|
|
|
|
/*
|
|
|
|
** Stay calm...decent optimizers will eliminate the complexity below.
|
|
|
|
*/
|
|
|
|
if (time1 >= 0 /* && time0 < 0 */)
|
|
|
|
return (uintmax_t) time1 + (uintmax_t) (-1 - time0) + 1;
|
|
|
|
return -(double) ((uintmax_t) time0 + (uintmax_t) (-1 - time1) + 1);
|
2009-03-04 04:28:35 +01:00
|
|
|
}
|