1
/* mktime - convert struct tm to a time_t value */
3
/* Copyright (C) 1993-2002 Free Software Foundation, Inc.
5
This file is part of GNU Bash, the Bourne Again SHell.
6
Contributed by Paul Eggert (eggert@twinsun.com).
8
Bash is free software: you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation, either version 3 of the License, or
11
(at your option) any later version.
13
Bash is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with Bash. If not, see <http://www.gnu.org/licenses/>.
21
/* Define this to have a standalone program to test this implementation of
30
# define HAVE_LIMITS_H 1
31
# define HAVE_LOCALTIME_R 1
32
# define STDC_HEADERS 1
35
/* Assume that leap seconds are possible, unless told otherwise.
36
If the host has a `zic' command with a `-L leapsecondfilename' option,
37
then it supports leap seconds; otherwise it probably doesn't. */
38
#ifndef LEAP_SECONDS_POSSIBLE
39
#define LEAP_SECONDS_POSSIBLE 1
43
#include <sys/types.h> /* Some systems define `time_t' here. */
55
/* Make it work even if the system's libc has its own mktime routine. */
56
#define mktime my_mktime
60
#if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
61
#define __P(args) args
72
#define INT_MIN (~0 << (sizeof (int) * CHAR_BIT - 1))
75
#define INT_MAX (~0 - INT_MIN)
79
#define TIME_T_MIN (0 < (time_t) -1 ? (time_t) 0 \
80
: ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
83
#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
86
#define TM_YEAR_BASE 1900
87
#define EPOCH_YEAR 1970
90
/* Nonzero if YEAR is a leap year (every 4 years,
91
except every 100th isn't, and every 400th is). */
92
#define __isleap(year) \
93
((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
96
/* How many days come before each month (0-12). */
97
const unsigned short int __mon_yday[2][13] =
100
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
102
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
105
static time_t ydhms_tm_diff __P ((int, int, int, int, int, const struct tm *));
106
time_t __mktime_internal __P ((struct tm *,
107
struct tm *(*) (const time_t *, struct tm *),
111
static struct tm *my_localtime_r __P ((const time_t *, struct tm *));
113
my_localtime_r (t, tp)
117
struct tm *l = localtime (t);
125
/* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
126
measured in seconds, ignoring leap seconds.
127
YEAR uses the same numbering as TM->tm_year.
128
All values are in range, except possibly YEAR.
129
If overflow occurs, yield the low order bits of the correct answer. */
131
ydhms_tm_diff (year, yday, hour, min, sec, tp)
132
int year, yday, hour, min, sec;
135
/* Compute intervening leap days correctly even if year is negative.
136
Take care to avoid int overflow. time_t overflow is OK, since
137
only the low order bits of the correct time_t answer are needed.
138
Don't convert to time_t until after all divisions are done, since
139
time_t might be unsigned. */
140
int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
141
int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
142
int a100 = a4 / 25 - (a4 % 25 < 0);
143
int b100 = b4 / 25 - (b4 % 25 < 0);
144
int a400 = a100 >> 2;
145
int b400 = b100 >> 2;
146
int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
147
time_t years = year - (time_t) tp->tm_year;
148
time_t days = (365 * years + intervening_leap_days
149
+ (yday - tp->tm_yday));
150
return (60 * (60 * (24 * days + (hour - tp->tm_hour))
151
+ (min - tp->tm_min))
152
+ (sec - tp->tm_sec));
156
static time_t localtime_offset;
158
/* Convert *TP to a time_t value. */
164
/* POSIX.1 8.1.1 requires that whenever mktime() is called, the
165
time zone names contained in the external variable `tzname' shall
166
be set as if the tzset() function had been called. */
170
return __mktime_internal (tp, my_localtime_r, &localtime_offset);
173
/* Convert *TP to a time_t value, inverting
174
the monotonic and mostly-unit-linear conversion function CONVERT.
175
Use *OFFSET to keep track of a guess at the offset of the result,
176
compared to what the result would be for UTC without leap seconds.
177
If *OFFSET's guess is correct, only one CONVERT call is needed. */
179
__mktime_internal (tp, convert, offset)
181
struct tm *(*convert) __P ((const time_t *, struct tm *));
187
/* The maximum number of probes (calls to CONVERT) should be enough
188
to handle any combinations of time zone rule changes, solar time,
189
and leap seconds. Posix.1 prohibits leap seconds, but some hosts
191
int remaining_probes = 4;
193
/* Time requested. Copy it in case CONVERT modifies *TP; this can
194
occur if TP is localtime's returned value and CONVERT is localtime. */
195
int sec = tp->tm_sec;
196
int min = tp->tm_min;
197
int hour = tp->tm_hour;
198
int mday = tp->tm_mday;
199
int mon = tp->tm_mon;
200
int year_requested = tp->tm_year;
201
int isdst = tp->tm_isdst;
203
/* Ensure that mon is in range, and set year accordingly. */
204
int mon_remainder = mon % 12;
205
int negative_mon_remainder = mon_remainder < 0;
206
int mon_years = mon / 12 - negative_mon_remainder;
207
int year = year_requested + mon_years;
209
/* The other values need not be in range:
210
the remaining code handles minor overflows correctly,
211
assuming int and time_t arithmetic wraps around.
212
Major overflows are caught at the end. */
214
/* Calculate day of year from year, month, and day of month.
215
The result need not be in range. */
216
int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
217
[mon_remainder + 12 * negative_mon_remainder])
220
#if LEAP_SECONDS_POSSIBLE
221
/* Handle out-of-range seconds specially,
222
since ydhms_tm_diff assumes every minute has 60 seconds. */
223
int sec_requested = sec;
230
/* Invert CONVERT by probing. First assume the same offset as last time.
231
Then repeatedly use the error to improve the guess. */
233
tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
234
tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
235
t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
237
for (t = t0 + *offset;
238
(dt = ydhms_tm_diff (year, yday, hour, min, sec, (*convert) (&t, &tm)));
240
if (--remaining_probes == 0)
243
/* Check whether tm.tm_isdst has the requested value, if any. */
244
if (0 <= isdst && 0 <= tm.tm_isdst)
246
int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
249
/* Move two hours in the direction indicated by the disagreement,
250
probe some more, and switch to a new time if found.
251
The largest known fallback due to daylight savings is two hours:
252
once, in Newfoundland, 1988-10-30 02:00 -> 00:00. */
253
time_t ot = t - 2 * 60 * 60 * dst_diff;
254
while (--remaining_probes != 0)
257
if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
258
(*convert) (&ot, &otm))))
265
break; /* Avoid a redundant probe. */
272
#if LEAP_SECONDS_POSSIBLE
273
if (sec_requested != tm.tm_sec)
275
/* Adjust time to reflect the tm_sec requested, not the normalized value.
276
Also, repair any damage from a false match due to a leap second. */
277
t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
278
(*convert) (&t, &tm);
282
if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
284
/* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
285
so check for major overflows. A gross check suffices,
286
since if t has overflowed, it is off by a multiple of
287
TIME_T_MAX - TIME_T_MIN + 1. So ignore any component of
288
the difference that is bounded by a small value. */
290
double dyear = (double) year_requested + mon_years - tm.tm_year;
291
double dday = 366 * dyear + mday;
292
double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
294
if (TIME_T_MAX / 3 - TIME_T_MIN / 3 < (dsec < 0 ? - dsec : dsec))
303
weak_alias (mktime, timelocal)
313
return ((a->tm_sec ^ b->tm_sec)
314
| (a->tm_min ^ b->tm_min)
315
| (a->tm_hour ^ b->tm_hour)
316
| (a->tm_mday ^ b->tm_mday)
317
| (a->tm_mon ^ b->tm_mon)
318
| (a->tm_year ^ b->tm_year)
319
| (a->tm_mday ^ b->tm_mday)
320
| (a->tm_yday ^ b->tm_yday)
321
| (a->tm_isdst ^ b->tm_isdst));
328
printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
329
tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
330
tp->tm_hour, tp->tm_min, tp->tm_sec,
331
tp->tm_yday, tp->tm_wday, tp->tm_isdst);
335
check_result (tk, tmk, tl, tml)
341
if (tk != tl || not_equal_tm (&tmk, &tml))
345
printf (")\nyields (");
347
printf (") == %ld, should be %ld\n", (long) tl, (long) tk);
360
struct tm tm, tmk, tml;
364
if ((argc == 3 || argc == 4)
365
&& (sscanf (argv[1], "%d-%d-%d%c",
366
&tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
368
&& (sscanf (argv[2], "%d:%d:%d%c",
369
&tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
372
tm.tm_year -= TM_YEAR_BASE;
374
tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
377
tml = *localtime (&tl);
378
printf ("mktime returns %ld == ", (long) tl);
381
status = check_result (tl, tmk, tl, tml);
383
else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
385
time_t from = atol (argv[1]);
386
time_t by = atol (argv[2]);
387
time_t to = atol (argv[3]);
390
for (tl = from; tl <= to; tl += by)
392
tml = *localtime (&tl);
395
status |= check_result (tk, tmk, tl, tml);
398
for (tl = from; tl <= to; tl += by)
400
/* Null benchmark. */
401
tml = *localtime (&tl);
404
status |= check_result (tk, tmk, tl, tml);
409
\t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
410
\t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
411
\t%s FROM BY TO - # Do not test those values (for benchmark).\n",
412
argv[0], argv[0], argv[0]);
421
compile-command: "gcc -DDEBUG=1 -Wall -O -g mktime.c -o mktime"