#include "private.h"
#include "tzfile.h"
#include "fcntl.h"
-#include "float.h" /* for FLT_MAX and DBL_MAX */
#ifndef TZ_ABBR_MAX_LEN
#define TZ_ABBR_MAX_LEN 16
#endif /* !defined TZDEFDST */
struct ttinfo { /* time type information */
- int_fast32_t tt_gmtoff; /* UTC offset in seconds */
+ int_fast32_t tt_gmtoff; /* UT offset in seconds */
int tt_isdst; /* used to set tm_isdst */
int tt_abbrind; /* abbreviation list index */
int tt_ttisstd; /* TRUE if transition is std time */
- int tt_ttisgmt; /* TRUE if transition is UTC */
+ int tt_ttisgmt; /* TRUE if transition is UT */
};
struct lsinfo { /* leap second information */
static struct tm tmGlobal;
#ifdef USG_COMPAT
-time_t timezone = 0;
-int daylight = 0;
+long timezone = 0;
+int daylight = 0;
#endif /* defined USG_COMPAT */
#ifdef ALTZONE
-time_t altzone = 0;
+long altzone = 0;
#endif /* defined ALTZONE */
static int_fast32_t
static int
differ_by_repeat(const time_t t1, const time_t t0)
{
- if (TYPE_INTEGRAL(time_t) &&
- TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
+ if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
return 0;
return t1 - t0 == SECSPERREPEAT;
}
for (i = 0; i < nread; ++i)
up->buf[i] = p[i];
/*
- ** If this is a narrow integer time_t system, we're done.
+ ** If this is a narrow time_t system, we're done.
*/
- if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
+ if (stored >= (int) sizeof(time_t))
break;
}
if (doextend && nread > 2 &&
** Time specified.
*/
++strp;
- strp = getsecs(strp, &rulep->r_time);
+ strp = getoffset(strp, &rulep->r_time);
} else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
return strp;
}
/*
** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
-** year, a rule, and the offset from UTC at the time that rule takes effect,
+** year, a rule, and the offset from UT at the time that rule takes effect,
** calculate the Epoch-relative time that rule takes effect.
*/
}
/*
- ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
+ ** "value" is the Epoch-relative time of 00:00:00 UT on the day in
** question. To get the Epoch-relative time of the specified local
** time on that day, add the transition time and the current offset
- ** from UTC.
+ ** from UT.
*/
return value + rulep->r_time + offset;
}
struct rule start;
struct rule end;
register int year;
+ register int yearlim;
register time_t janfirst;
time_t starttime;
time_t endtime;
atp = sp->ats;
typep = sp->types;
janfirst = 0;
- sp->timecnt = 0;
- for (year = EPOCH_YEAR;
- sp->timecnt + 2 <= TZ_MAX_TIMES;
- ++year) {
- time_t newfirst;
+ yearlim = EPOCH_YEAR + YEARSPERREPEAT;
+ for (year = EPOCH_YEAR; year < yearlim; year++) {
+ int_fast32_t yearsecs;
starttime = transtime(janfirst, year, &start,
stdoffset);
endtime = transtime(janfirst, year, &end,
dstoffset);
- if (starttime > endtime) {
- *atp++ = endtime;
- *typep++ = 1; /* DST ends */
- *atp++ = starttime;
- *typep++ = 0; /* DST begins */
- } else {
- *atp++ = starttime;
- *typep++ = 0; /* DST begins */
- *atp++ = endtime;
- *typep++ = 1; /* DST ends */
+ yearsecs = (year_lengths[isleap(year)]
+ * SECSPERDAY);
+ if (starttime > endtime
+ || (starttime < endtime
+ && (endtime - starttime
+ < (yearsecs
+ + (stdoffset - dstoffset))))) {
+ if (&sp->ats[TZ_MAX_TIMES - 2] < atp)
+ break;
+ yearlim = year + YEARSPERREPEAT + 1;
+ if (starttime > endtime) {
+ *atp++ = endtime;
+ *typep++ = 1; /* DST ends */
+ *atp++ = starttime;
+ *typep++ = 0; /* DST begins */
+ } else {
+ *atp++ = starttime;
+ *typep++ = 0; /* DST begins */
+ *atp++ = endtime;
+ *typep++ = 1; /* DST ends */
+ }
}
- sp->timecnt += 2;
- newfirst = janfirst;
- newfirst += year_lengths[isleap(year)] *
- SECSPERDAY;
- if (newfirst <= janfirst)
+ if (time_t_max - janfirst < yearsecs)
break;
- janfirst = newfirst;
+ janfirst += yearsecs;
}
+ sp->timecnt = atp - sp->ats;
+ if (!sp->timecnt)
+ sp->typecnt = 1; /* Perpetual DST. */
} else {
register int_fast32_t theirstdoffset;
register int_fast32_t theirdstoffset;
(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
time_t newt = t;
register time_t seconds;
- register time_t tcycles;
- register int_fast64_t icycles;
+ register time_t years;
if (t < sp->ats[0])
seconds = sp->ats[0] - t;
else seconds = t - sp->ats[sp->timecnt - 1];
--seconds;
- tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
- ++tcycles;
- icycles = tcycles;
- if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
- return NULL;
- seconds = icycles;
- seconds *= YEARSPERREPEAT;
- seconds *= AVGSECSPERYEAR;
+ years = (seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT;
+ seconds = years * AVGSECSPERYEAR;
if (t < sp->ats[0])
newt += seconds;
else newt -= seconds;
newy = tmp->tm_year;
if (t < sp->ats[0])
- newy -= icycles * YEARSPERREPEAT;
- else newy += icycles * YEARSPERREPEAT;
+ newy -= years;
+ else newy += years;
tmp->tm_year = newy;
if (tmp->tm_year != newy)
return NULL;
#ifdef TM_ZONE
/*
** Could get fancy here and deliver something such as
- ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
+ ** "UT+xxxx" or "UT-xxxx" if offset is non-zero,
** but this is no time for a treasure hunt.
*/
if (offset != 0)
register int leapdays;
tdelta = tdays / DAYSPERLYEAR;
+ if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
+ && tdelta <= INT_MAX))
+ return NULL;
idelta = tdelta;
- if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
- return NULL;
if (idelta == 0)
idelta = (tdays < 0) ? -1 : 1;
newy = y;
}
{
register int_fast32_t seconds;
- register time_t half_second = 0.5;
- seconds = tdays * SECSPERDAY + half_second;
+ seconds = tdays * SECSPERDAY;
tdays = seconds / SECSPERDAY;
rem += seconds - tdays * SECSPERDAY;
}
{
register int result;
- if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
- (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
+ if (atmp->tm_year != btmp->tm_year)
+ return atmp->tm_year < btmp->tm_year ? -1 : 1;
+ if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
(result = (atmp->tm_min - btmp->tm_min)) == 0)
if (!TYPE_SIGNED(time_t)) {
lo = 0;
hi = lo - 1;
- } else if (!TYPE_INTEGRAL(time_t)) {
- if (sizeof(time_t) > sizeof(float))
- hi = (time_t) DBL_MAX;
- else hi = (time_t) FLT_MAX;
- lo = -hi;
} else {
lo = 1;
for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
** previous versions of the CMUCS runtime library.
*/
-int_fast32_t
+long
gtime(struct tm * const tmp)
{
const time_t t = mktime(tmp);
#ifndef INTMAX_MAX
# if defined LLONG_MAX || defined __LONG_LONG_MAX__
typedef long long intmax_t;
+# define strtoimax strtoll
# define PRIdMAX "lld"
+# ifdef LLONG_MAX
+# define INTMAX_MAX LLONG_MAX
+# define INTMAX_MIN LLONG_MIN
+# else
+# define INTMAX_MAX __LONG_LONG_MAX__
+# define INTMAX_MIN __LONG_LONG_MIN__
+# endif
# else
typedef long intmax_t;
+# define strtoimax strtol
# define PRIdMAX "ld"
+# define INTMAX_MAX LONG_MAX
+# define INTMAX_MIN LONG_MIN
# endif
#endif
#if 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
# define ATTRIBUTE_CONST __attribute__ ((const))
# define ATTRIBUTE_PURE __attribute__ ((__pure__))
+# define ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
#else
# define ATTRIBUTE_CONST /* empty */
# define ATTRIBUTE_PURE /* empty */
+# define ATTRIBUTE_FORMAT(spec) /* empty */
#endif
#if !defined _Noreturn && __STDC_VERSION__ < 201112
? - (~ 0 < 0) - ((time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1))
: -1);
-/*
-** Since the definition of TYPE_INTEGRAL contains floating point numbers,
-** it cannot be used in preprocessor directives.
-*/
-
-#ifndef TYPE_INTEGRAL
-#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
-#endif /* !defined TYPE_INTEGRAL */
-
#ifndef INT_STRLEN_MAXIMUM
/*
** 302 / 1000 is log10(2.0) rounded up.
struct tzhead {
char tzh_magic[4]; /* TZ_MAGIC */
- char tzh_version[1]; /* '\0' or '2' as of 2005 */
+ char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
char tzh_reserved[15]; /* reserved--must be zero */
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
** tzh_timecnt (char [4])s coded transition times a la time(2)
** tzh_timecnt (unsigned char)s types of local time starting at above
** tzh_typecnt repetitions of
-** one (char [4]) coded UTC offset in seconds
+** one (char [4]) coded UT offset in seconds
** one (unsigned char) used to set tm_isdst
** one (unsigned char) that's an abbreviation list index
** tzh_charcnt (char)s '\0'-terminated zone abbreviations
** if absent, transition times are
** assumed to be wall clock time
** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
-** time is UTC, if FALSE,
+** time is UT, if FALSE,
** transition time is local time
** if absent, transition times are
** assumed to be local time
** instants after the last transition time stored in the file
** (with nothing between the newlines if there is no POSIX representation for
** such instants).
+**
+** If tz_version is '3' or greater, the above is extended as follows.
+** First, the POSIX TZ string's hour offset may range from -167
+** through 167 as compared to the POSIX-required 0 through 24.
+** Second, its DST start time may be January 1 at 00:00 and its stop
+** time December 31 at 24:00 plus the difference between DST and
+** standard time, indicating DST all year.
*/
/*