]>
git.saurik.com Git - apple/icu.git/blob - icuSources/tools/tzcode/localtime.c
2 ** This file is in the public domain, so clarified as of
3 ** 1996-06-05 by Arthur David Olson.
8 static char elsieid
[] = "@(#)localtime.c 8.5";
9 #endif /* !defined NOID */
10 #endif /* !defined lint */
13 ** Leap second handling from Bradley White.
14 ** POSIX-style TZ environment variable handling from Guy Harris.
22 #include "float.h" /* for FLT_MAX and DBL_MAX */
24 #ifndef TZ_ABBR_MAX_LEN
25 #define TZ_ABBR_MAX_LEN 16
26 #endif /* !defined TZ_ABBR_MAX_LEN */
28 #ifndef TZ_ABBR_CHAR_SET
29 #define TZ_ABBR_CHAR_SET \
30 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
31 #endif /* !defined TZ_ABBR_CHAR_SET */
33 #ifndef TZ_ABBR_ERR_CHAR
34 #define TZ_ABBR_ERR_CHAR '_'
35 #endif /* !defined TZ_ABBR_ERR_CHAR */
38 ** SunOS 4.1.1 headers lack O_BINARY.
42 #define OPEN_MODE (O_RDONLY | O_BINARY)
43 #endif /* defined O_BINARY */
45 #define OPEN_MODE O_RDONLY
46 #endif /* !defined O_BINARY */
50 ** Someone might make incorrect use of a time zone abbreviation:
51 ** 1. They might reference tzname[0] before calling tzset (explicitly
53 ** 2. They might reference tzname[1] before calling tzset (explicitly
55 ** 3. They might reference tzname[1] after setting to a time zone
56 ** in which Daylight Saving Time is never observed.
57 ** 4. They might reference tzname[0] after setting to a time zone
58 ** in which Standard Time is never observed.
59 ** 5. They might reference tm.TM_ZONE after calling offtime.
60 ** What's best to do in the above cases is open to debate;
61 ** for now, we just set things up so that in any of the five cases
62 ** WILDABBR is used. Another possibility: initialize tzname[0] to the
63 ** string "tzname[0] used before set", and similarly for the other cases.
64 ** And another: initialize tzname[0] to "ERA", with an explanation in the
65 ** manual page of what this "time zone abbreviation" means (doing this so
66 ** that tzname[0] has the "normal" length of three characters).
69 #endif /* !defined WILDABBR */
71 static char wildabbr
[] = WILDABBR
;
73 static const char gmt
[] = "GMT";
76 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
77 ** We default to US rules as of 1999-08-17.
78 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
79 ** implementation dependent; for historical reasons, US rules are a
82 #ifndef TZDEFRULESTRING
83 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
84 #endif /* !defined TZDEFDST */
86 struct ttinfo
{ /* time type information */
87 long tt_gmtoff
; /* UTC offset in seconds */
88 int tt_isdst
; /* used to set tm_isdst */
89 int tt_abbrind
; /* abbreviation list index */
90 int tt_ttisstd
; /* TRUE if transition is std time */
91 int tt_ttisgmt
; /* TRUE if transition is UTC */
94 struct lsinfo
{ /* leap second information */
95 time_t ls_trans
; /* transition time */
96 long ls_corr
; /* correction to apply */
99 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
102 #define MY_TZNAME_MAX TZNAME_MAX
103 #endif /* defined TZNAME_MAX */
105 #define MY_TZNAME_MAX 255
106 #endif /* !defined TZNAME_MAX */
115 time_t ats
[TZ_MAX_TIMES
];
116 unsigned char types
[TZ_MAX_TIMES
];
117 struct ttinfo ttis
[TZ_MAX_TYPES
];
118 char chars
[BIGGEST(BIGGEST(TZ_MAX_CHARS
+ 1, sizeof gmt
),
119 (2 * (MY_TZNAME_MAX
+ 1)))];
120 struct lsinfo lsis
[TZ_MAX_LEAPS
];
124 int r_type
; /* type of rule--see below */
125 int r_day
; /* day number of rule */
126 int r_week
; /* week number of rule */
127 int r_mon
; /* month number of rule */
128 long r_time
; /* transition time of rule */
131 #define JULIAN_DAY 0 /* Jn - Julian day */
132 #define DAY_OF_YEAR 1 /* n - day of year */
133 #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
136 ** Prototypes for static functions.
139 static long detzcode
P((const char * codep
));
140 static time_t detzcode64
P((const char * codep
));
141 static int differ_by_repeat
P((time_t t1
, time_t t0
));
142 static const char * getzname
P((const char * strp
));
143 static const char * getqzname
P((const char * strp
, const int delim
));
144 static const char * getnum
P((const char * strp
, int * nump
, int min
,
146 static const char * getsecs
P((const char * strp
, long * secsp
));
147 static const char * getoffset
P((const char * strp
, long * offsetp
));
148 static const char * getrule
P((const char * strp
, struct rule
* rulep
));
149 static void gmtload
P((struct state
* sp
));
150 static struct tm
* gmtsub
P((const time_t * timep
, long offset
,
152 static struct tm
* localsub
P((const time_t * timep
, long offset
,
154 static int increment_overflow
P((int * number
, int delta
));
155 static int leaps_thru_end_of
P((int y
));
156 static int long_increment_overflow
P((long * number
, int delta
));
157 static int long_normalize_overflow
P((long * tensptr
,
158 int * unitsptr
, int base
));
159 static int normalize_overflow
P((int * tensptr
, int * unitsptr
,
161 static void settzname
P((void));
162 static time_t time1
P((struct tm
* tmp
,
163 struct tm
* (*funcp
) P((const time_t *,
166 static time_t time2
P((struct tm
*tmp
,
167 struct tm
* (*funcp
) P((const time_t *,
169 long offset
, int * okayp
));
170 static time_t time2sub
P((struct tm
*tmp
,
171 struct tm
* (*funcp
) P((const time_t *,
173 long offset
, int * okayp
, int do_norm_secs
));
174 static struct tm
* timesub
P((const time_t * timep
, long offset
,
175 const struct state
* sp
, struct tm
* tmp
));
176 static int tmcomp
P((const struct tm
* atmp
,
177 const struct tm
* btmp
));
178 static time_t transtime
P((time_t janfirst
, int year
,
179 const struct rule
* rulep
, long offset
));
180 static int tzload
P((const char * name
, struct state
* sp
,
182 static int tzparse
P((const char * name
, struct state
* sp
,
186 static struct state
* lclptr
;
187 static struct state
* gmtptr
;
188 #endif /* defined ALL_STATE */
191 static struct state lclmem
;
192 static struct state gmtmem
;
193 #define lclptr (&lclmem)
194 #define gmtptr (&gmtmem)
195 #endif /* State Farm */
197 #ifndef TZ_STRLEN_MAX
198 #define TZ_STRLEN_MAX 255
199 #endif /* !defined TZ_STRLEN_MAX */
201 static char lcl_TZname
[TZ_STRLEN_MAX
+ 1];
202 static int lcl_is_set
;
203 static int gmt_is_set
;
211 ** Section 4.12.3 of X3.159-1989 requires that
212 ** Except for the strftime function, these functions [asctime,
213 ** ctime, gmtime, localtime] return values in one of two static
214 ** objects: a broken-down time structure and an array of char.
215 ** Thanks to Paul Eggert for noting this.
223 #endif /* defined USG_COMPAT */
227 #endif /* defined ALTZONE */
231 const char * const codep
;
233 register long result
;
236 result
= (codep
[0] & 0x80) ? ~0L : 0;
237 for (i
= 0; i
< 4; ++i
)
238 result
= (result
<< 8) | (codep
[i
] & 0xff);
244 const char * const codep
;
246 register time_t result
;
249 result
= (codep
[0] & 0x80) ? (~(int_fast64_t) 0) : 0;
250 for (i
= 0; i
< 8; ++i
)
251 result
= result
* 256 + (codep
[i
] & 0xff);
258 register struct state
* const sp
= lclptr
;
261 tzname
[0] = wildabbr
;
262 tzname
[1] = wildabbr
;
266 #endif /* defined USG_COMPAT */
269 #endif /* defined ALTZONE */
272 tzname
[0] = tzname
[1] = gmt
;
275 #endif /* defined ALL_STATE */
276 for (i
= 0; i
< sp
->typecnt
; ++i
) {
277 register const struct ttinfo
* const ttisp
= &sp
->ttis
[i
];
279 tzname
[ttisp
->tt_isdst
] =
280 &sp
->chars
[ttisp
->tt_abbrind
];
284 if (i
== 0 || !ttisp
->tt_isdst
)
285 timezone
= -(ttisp
->tt_gmtoff
);
286 #endif /* defined USG_COMPAT */
288 if (i
== 0 || ttisp
->tt_isdst
)
289 altzone
= -(ttisp
->tt_gmtoff
);
290 #endif /* defined ALTZONE */
293 ** And to get the latest zone names into tzname. . .
295 for (i
= 0; i
< sp
->timecnt
; ++i
) {
296 register const struct ttinfo
* const ttisp
=
300 tzname
[ttisp
->tt_isdst
] =
301 &sp
->chars
[ttisp
->tt_abbrind
];
304 ** Finally, scrub the abbreviations.
305 ** First, replace bogus characters.
307 for (i
= 0; i
< sp
->charcnt
; ++i
)
308 if (strchr(TZ_ABBR_CHAR_SET
, sp
->chars
[i
]) == NULL
)
309 sp
->chars
[i
] = TZ_ABBR_ERR_CHAR
;
311 ** Second, truncate long abbreviations.
313 for (i
= 0; i
< sp
->typecnt
; ++i
) {
314 register const struct ttinfo
* const ttisp
= &sp
->ttis
[i
];
315 register char * cp
= &sp
->chars
[ttisp
->tt_abbrind
];
317 if (strlen(cp
) > TZ_ABBR_MAX_LEN
&&
318 strcmp(cp
, GRANDPARENTED
) != 0)
319 *(cp
+ TZ_ABBR_MAX_LEN
) = '\0';
324 differ_by_repeat(t1
, t0
)
328 if (TYPE_INTEGRAL(time_t) &&
329 TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS
)
331 return t1
- t0
== SECSPERREPEAT
;
335 tzload(name
, sp
, doextend
)
336 register const char * name
;
337 register struct state
* const sp
;
338 register const int doextend
;
340 register const char * p
;
346 struct tzhead tzhead
;
347 char buf
[2 * sizeof(struct tzhead
) +
352 if (name
== NULL
&& (name
= TZDEFAULT
) == NULL
)
355 register int doaccess
;
357 ** Section 4.9.1 of the C standard says that
358 ** "FILENAME_MAX expands to an integral constant expression
359 ** that is the size needed for an array of char large enough
360 ** to hold the longest file name string that the implementation
361 ** guarantees can be opened."
363 char fullname
[FILENAME_MAX
+ 1];
367 doaccess
= name
[0] == '/';
369 if ((p
= TZDIR
) == NULL
)
371 if ((strlen(p
) + strlen(name
) + 1) >= sizeof fullname
)
373 (void) strcpy(fullname
, p
);
374 (void) strcat(fullname
, "/");
375 (void) strcat(fullname
, name
);
377 ** Set doaccess if '.' (as in "../") shows up in name.
379 if (strchr(name
, '.') != NULL
)
383 if (doaccess
&& access(name
, R_OK
) != 0)
385 if ((fid
= open(name
, OPEN_MODE
)) == -1)
388 nread
= read(fid
, u
.buf
, sizeof u
.buf
);
389 if (close(fid
) < 0 || nread
<= 0)
391 for (stored
= 4; stored
<= 8; stored
*= 2) {
395 ttisstdcnt
= (int) detzcode(u
.tzhead
.tzh_ttisstdcnt
);
396 ttisgmtcnt
= (int) detzcode(u
.tzhead
.tzh_ttisgmtcnt
);
397 sp
->leapcnt
= (int) detzcode(u
.tzhead
.tzh_leapcnt
);
398 sp
->timecnt
= (int) detzcode(u
.tzhead
.tzh_timecnt
);
399 sp
->typecnt
= (int) detzcode(u
.tzhead
.tzh_typecnt
);
400 sp
->charcnt
= (int) detzcode(u
.tzhead
.tzh_charcnt
);
401 p
= u
.tzhead
.tzh_charcnt
+ sizeof u
.tzhead
.tzh_charcnt
;
402 if (sp
->leapcnt
< 0 || sp
->leapcnt
> TZ_MAX_LEAPS
||
403 sp
->typecnt
<= 0 || sp
->typecnt
> TZ_MAX_TYPES
||
404 sp
->timecnt
< 0 || sp
->timecnt
> TZ_MAX_TIMES
||
405 sp
->charcnt
< 0 || sp
->charcnt
> TZ_MAX_CHARS
||
406 (ttisstdcnt
!= sp
->typecnt
&& ttisstdcnt
!= 0) ||
407 (ttisgmtcnt
!= sp
->typecnt
&& ttisgmtcnt
!= 0))
409 if (nread
- (p
- u
.buf
) <
410 sp
->timecnt
* stored
+ /* ats */
411 sp
->timecnt
+ /* types */
412 sp
->typecnt
* 6 + /* ttinfos */
413 sp
->charcnt
+ /* chars */
414 sp
->leapcnt
* (stored
+ 4) + /* lsinfos */
415 ttisstdcnt
+ /* ttisstds */
416 ttisgmtcnt
) /* ttisgmts */
418 for (i
= 0; i
< sp
->timecnt
; ++i
) {
419 sp
->ats
[i
] = (stored
== 4) ?
420 detzcode(p
) : detzcode64(p
);
423 for (i
= 0; i
< sp
->timecnt
; ++i
) {
424 sp
->types
[i
] = (unsigned char) *p
++;
425 if (sp
->types
[i
] >= sp
->typecnt
)
428 for (i
= 0; i
< sp
->typecnt
; ++i
) {
429 register struct ttinfo
* ttisp
;
431 ttisp
= &sp
->ttis
[i
];
432 ttisp
->tt_gmtoff
= detzcode(p
);
434 ttisp
->tt_isdst
= (unsigned char) *p
++;
435 if (ttisp
->tt_isdst
!= 0 && ttisp
->tt_isdst
!= 1)
437 ttisp
->tt_abbrind
= (unsigned char) *p
++;
438 if (ttisp
->tt_abbrind
< 0 ||
439 ttisp
->tt_abbrind
> sp
->charcnt
)
442 for (i
= 0; i
< sp
->charcnt
; ++i
)
444 sp
->chars
[i
] = '\0'; /* ensure '\0' at end */
445 for (i
= 0; i
< sp
->leapcnt
; ++i
) {
446 register struct lsinfo
* lsisp
;
448 lsisp
= &sp
->lsis
[i
];
449 lsisp
->ls_trans
= (stored
== 4) ?
450 detzcode(p
) : detzcode64(p
);
452 lsisp
->ls_corr
= detzcode(p
);
455 for (i
= 0; i
< sp
->typecnt
; ++i
) {
456 register struct ttinfo
* ttisp
;
458 ttisp
= &sp
->ttis
[i
];
460 ttisp
->tt_ttisstd
= FALSE
;
462 ttisp
->tt_ttisstd
= *p
++;
463 if (ttisp
->tt_ttisstd
!= TRUE
&&
464 ttisp
->tt_ttisstd
!= FALSE
)
468 for (i
= 0; i
< sp
->typecnt
; ++i
) {
469 register struct ttinfo
* ttisp
;
471 ttisp
= &sp
->ttis
[i
];
473 ttisp
->tt_ttisgmt
= FALSE
;
475 ttisp
->tt_ttisgmt
= *p
++;
476 if (ttisp
->tt_ttisgmt
!= TRUE
&&
477 ttisp
->tt_ttisgmt
!= FALSE
)
482 ** Out-of-sort ats should mean we're running on a
483 ** signed time_t system but using a data file with
484 ** unsigned values (or vice versa).
486 for (i
= 0; i
< sp
->timecnt
- 2; ++i
)
487 if (sp
->ats
[i
] > sp
->ats
[i
+ 1]) {
489 if (TYPE_SIGNED(time_t)) {
491 ** Ignore the end (easy).
496 ** Ignore the beginning (harder).
500 for (j
= 0; j
+ i
< sp
->timecnt
; ++j
) {
501 sp
->ats
[j
] = sp
->ats
[j
+ i
];
502 sp
->types
[j
] = sp
->types
[j
+ i
];
509 ** If this is an old file, we're done.
511 if (u
.tzhead
.tzh_version
[0] == '\0')
514 for (i
= 0; i
< nread
; ++i
)
517 ** If this is a narrow integer time_t system, we're done.
519 if (stored
>= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
522 if (doextend
&& nread
> 2 &&
523 u
.buf
[0] == '\n' && u
.buf
[nread
- 1] == '\n' &&
524 sp
->typecnt
+ 2 <= TZ_MAX_TYPES
) {
528 u
.buf
[nread
- 1] = '\0';
529 result
= tzparse(&u
.buf
[1], &ts
, FALSE
);
530 if (result
== 0 && ts
.typecnt
== 2 &&
531 sp
->charcnt
+ ts
.charcnt
<= TZ_MAX_CHARS
) {
532 for (i
= 0; i
< 2; ++i
)
533 ts
.ttis
[i
].tt_abbrind
+=
535 for (i
= 0; i
< ts
.charcnt
; ++i
)
536 sp
->chars
[sp
->charcnt
++] =
539 while (i
< ts
.timecnt
&&
541 sp
->ats
[sp
->timecnt
- 1])
543 while (i
< ts
.timecnt
&&
544 sp
->timecnt
< TZ_MAX_TIMES
) {
545 sp
->ats
[sp
->timecnt
] =
547 sp
->types
[sp
->timecnt
] =
553 sp
->ttis
[sp
->typecnt
++] = ts
.ttis
[0];
554 sp
->ttis
[sp
->typecnt
++] = ts
.ttis
[1];
557 i
= 2 * YEARSPERREPEAT
;
558 sp
->goback
= sp
->goahead
= sp
->timecnt
> i
;
559 sp
->goback
= sp
->goback
&& sp
->types
[i
] == sp
->types
[0] &&
560 differ_by_repeat(sp
->ats
[i
], sp
->ats
[0]);
561 sp
->goahead
= sp
->goahead
&&
562 sp
->types
[sp
->timecnt
- 1] == sp
->types
[sp
->timecnt
- 1 - i
] &&
563 differ_by_repeat(sp
->ats
[sp
->timecnt
- 1],
564 sp
->ats
[sp
->timecnt
- 1 - i
]);
568 static const int mon_lengths
[2][MONSPERYEAR
] = {
569 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
570 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
573 static const int year_lengths
[2] = {
574 DAYSPERNYEAR
, DAYSPERLYEAR
578 ** Given a pointer into a time zone string, scan until a character that is not
579 ** a valid character in a zone name is found. Return a pointer to that
585 register const char * strp
;
589 while ((c
= *strp
) != '\0' && !is_digit(c
) && c
!= ',' && c
!= '-' &&
596 ** Given a pointer into an extended time zone string, scan until the ending
597 ** delimiter of the zone name is located. Return a pointer to the delimiter.
599 ** As with getzname above, the legal character set is actually quite
600 ** restricted, with other characters producing undefined results.
601 ** We don't do any checking here; checking is done later in common-case code.
605 getqzname(register const char *strp
, const int delim
)
609 while ((c
= *strp
) != '\0' && c
!= delim
)
615 ** Given a pointer into a time zone string, extract a number from that string.
616 ** Check that the number is within a specified range; if it is not, return
618 ** Otherwise, return a pointer to the first character not part of the number.
622 getnum(strp
, nump
, min
, max
)
623 register const char * strp
;
631 if (strp
== NULL
|| !is_digit(c
= *strp
))
635 num
= num
* 10 + (c
- '0');
637 return NULL
; /* illegal value */
639 } while (is_digit(c
));
641 return NULL
; /* illegal value */
647 ** Given a pointer into a time zone string, extract a number of seconds,
648 ** in hh[:mm[:ss]] form, from the string.
649 ** If any error occurs, return NULL.
650 ** Otherwise, return a pointer to the first character not part of the number
656 register const char * strp
;
662 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
663 ** "M10.4.6/26", which does not conform to Posix,
664 ** but which specifies the equivalent of
665 ** ``02:00 on the first Sunday on or after 23 Oct''.
667 strp
= getnum(strp
, &num
, 0, HOURSPERDAY
* DAYSPERWEEK
- 1);
670 *secsp
= num
* (long) SECSPERHOUR
;
673 strp
= getnum(strp
, &num
, 0, MINSPERHOUR
- 1);
676 *secsp
+= num
* SECSPERMIN
;
679 /* `SECSPERMIN' allows for leap seconds. */
680 strp
= getnum(strp
, &num
, 0, SECSPERMIN
);
690 ** Given a pointer into a time zone string, extract an offset, in
691 ** [+-]hh[:mm[:ss]] form, from the string.
692 ** If any error occurs, return NULL.
693 ** Otherwise, return a pointer to the first character not part of the time.
697 getoffset(strp
, offsetp
)
698 register const char * strp
;
699 long * const offsetp
;
701 register int neg
= 0;
706 } else if (*strp
== '+')
708 strp
= getsecs(strp
, offsetp
);
710 return NULL
; /* illegal time */
712 *offsetp
= -*offsetp
;
717 ** Given a pointer into a time zone string, extract a rule in the form
718 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
719 ** If a valid rule is not found, return NULL.
720 ** Otherwise, return a pointer to the first character not part of the rule.
726 register struct rule
* const rulep
;
732 rulep
->r_type
= JULIAN_DAY
;
734 strp
= getnum(strp
, &rulep
->r_day
, 1, DAYSPERNYEAR
);
735 } else if (*strp
== 'M') {
739 rulep
->r_type
= MONTH_NTH_DAY_OF_WEEK
;
741 strp
= getnum(strp
, &rulep
->r_mon
, 1, MONSPERYEAR
);
746 strp
= getnum(strp
, &rulep
->r_week
, 1, 5);
751 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERWEEK
- 1);
752 } else if (is_digit(*strp
)) {
756 rulep
->r_type
= DAY_OF_YEAR
;
757 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERLYEAR
- 1);
758 } else return NULL
; /* invalid format */
766 strp
= getsecs(strp
, &rulep
->r_time
);
767 } else rulep
->r_time
= 2 * SECSPERHOUR
; /* default = 2:00:00 */
772 ** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
773 ** year, a rule, and the offset from UTC at the time that rule takes effect,
774 ** calculate the Epoch-relative time that rule takes effect.
778 transtime(janfirst
, year
, rulep
, offset
)
779 const time_t janfirst
;
781 register const struct rule
* const rulep
;
784 register int leapyear
;
785 register time_t value
;
787 int d
, m1
, yy0
, yy1
, yy2
, dow
;
790 leapyear
= isleap(year
);
791 switch (rulep
->r_type
) {
795 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
797 ** In non-leap years, or if the day number is 59 or less, just
798 ** add SECSPERDAY times the day number-1 to the time of
799 ** January 1, midnight, to get the day.
801 value
= janfirst
+ (rulep
->r_day
- 1) * SECSPERDAY
;
802 if (leapyear
&& rulep
->r_day
>= 60)
809 ** Just add SECSPERDAY times the day number to the time of
810 ** January 1, midnight, to get the day.
812 value
= janfirst
+ rulep
->r_day
* SECSPERDAY
;
815 case MONTH_NTH_DAY_OF_WEEK
:
817 ** Mm.n.d - nth "dth day" of month m.
820 for (i
= 0; i
< rulep
->r_mon
- 1; ++i
)
821 value
+= mon_lengths
[leapyear
][i
] * SECSPERDAY
;
824 ** Use Zeller's Congruence to get day-of-week of first day of
827 m1
= (rulep
->r_mon
+ 9) % 12 + 1;
828 yy0
= (rulep
->r_mon
<= 2) ? (year
- 1) : year
;
831 dow
= ((26 * m1
- 2) / 10 +
832 1 + yy2
+ yy2
/ 4 + yy1
/ 4 - 2 * yy1
) % 7;
837 ** "dow" is the day-of-week of the first day of the month. Get
838 ** the day-of-month (zero-origin) of the first "dow" day of the
841 d
= rulep
->r_day
- dow
;
844 for (i
= 1; i
< rulep
->r_week
; ++i
) {
845 if (d
+ DAYSPERWEEK
>=
846 mon_lengths
[leapyear
][rulep
->r_mon
- 1])
852 ** "d" is the day-of-month (zero-origin) of the day we want.
854 value
+= d
* SECSPERDAY
;
859 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
860 ** question. To get the Epoch-relative time of the specified local
861 ** time on that day, add the transition time and the current offset
864 return value
+ rulep
->r_time
+ offset
;
868 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
873 tzparse(name
, sp
, lastditch
)
875 register struct state
* const sp
;
878 const char * stdname
;
879 const char * dstname
;
884 register time_t * atp
;
885 register unsigned char * typep
;
887 register int load_result
;
892 stdlen
= strlen(name
); /* length of standard zone name */
894 if (stdlen
>= sizeof sp
->chars
)
895 stdlen
= (sizeof sp
->chars
) - 1;
901 name
= getqzname(name
, '>');
904 stdlen
= name
- stdname
;
907 name
= getzname(name
);
908 stdlen
= name
- stdname
;
912 name
= getoffset(name
, &stdoffset
);
916 load_result
= tzload(TZDEFRULES
, sp
, FALSE
);
917 if (load_result
!= 0)
918 sp
->leapcnt
= 0; /* so, we're off a little */
922 name
= getqzname(name
, '>');
925 dstlen
= name
- dstname
;
929 name
= getzname(name
);
930 dstlen
= name
- dstname
; /* length of DST zone name */
932 if (*name
!= '\0' && *name
!= ',' && *name
!= ';') {
933 name
= getoffset(name
, &dstoffset
);
936 } else dstoffset
= stdoffset
- SECSPERHOUR
;
937 if (*name
== '\0' && load_result
!= 0)
938 name
= TZDEFRULESTRING
;
939 if (*name
== ',' || *name
== ';') {
943 register time_t janfirst
;
948 if ((name
= getrule(name
, &start
)) == NULL
)
952 if ((name
= getrule(name
, &end
)) == NULL
)
956 sp
->typecnt
= 2; /* standard time and DST */
958 ** Two transitions per year, from EPOCH_YEAR forward.
960 sp
->ttis
[0].tt_gmtoff
= -dstoffset
;
961 sp
->ttis
[0].tt_isdst
= 1;
962 sp
->ttis
[0].tt_abbrind
= stdlen
+ 1;
963 sp
->ttis
[1].tt_gmtoff
= -stdoffset
;
964 sp
->ttis
[1].tt_isdst
= 0;
965 sp
->ttis
[1].tt_abbrind
= 0;
970 for (year
= EPOCH_YEAR
;
971 sp
->timecnt
+ 2 <= TZ_MAX_TIMES
;
975 starttime
= transtime(janfirst
, year
, &start
,
977 endtime
= transtime(janfirst
, year
, &end
,
979 if (starttime
> endtime
) {
981 *typep
++ = 1; /* DST ends */
983 *typep
++ = 0; /* DST begins */
986 *typep
++ = 0; /* DST begins */
988 *typep
++ = 1; /* DST ends */
992 newfirst
+= year_lengths
[isleap(year
)] *
994 if (newfirst
<= janfirst
)
999 register long theirstdoffset
;
1000 register long theirdstoffset
;
1001 register long theiroffset
;
1009 ** Initial values of theirstdoffset and theirdstoffset.
1012 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1014 if (!sp
->ttis
[j
].tt_isdst
) {
1016 -sp
->ttis
[j
].tt_gmtoff
;
1021 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1023 if (sp
->ttis
[j
].tt_isdst
) {
1025 -sp
->ttis
[j
].tt_gmtoff
;
1030 ** Initially we're assumed to be in standard time.
1033 theiroffset
= theirstdoffset
;
1035 ** Now juggle transition times and types
1036 ** tracking offsets as you do.
1038 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1040 sp
->types
[i
] = sp
->ttis
[j
].tt_isdst
;
1041 if (sp
->ttis
[j
].tt_ttisgmt
) {
1042 /* No adjustment to transition time */
1045 ** If summer time is in effect, and the
1046 ** transition time was not specified as
1047 ** standard time, add the summer time
1048 ** offset to the transition time;
1049 ** otherwise, add the standard time
1050 ** offset to the transition time.
1053 ** Transitions from DST to DDST
1054 ** will effectively disappear since
1055 ** POSIX provides for only one DST
1058 if (isdst
&& !sp
->ttis
[j
].tt_ttisstd
) {
1059 sp
->ats
[i
] += dstoffset
-
1062 sp
->ats
[i
] += stdoffset
-
1066 theiroffset
= -sp
->ttis
[j
].tt_gmtoff
;
1067 if (sp
->ttis
[j
].tt_isdst
)
1068 theirdstoffset
= theiroffset
;
1069 else theirstdoffset
= theiroffset
;
1072 ** Finally, fill in ttis.
1073 ** ttisstd and ttisgmt need not be handled.
1075 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
1076 sp
->ttis
[0].tt_isdst
= FALSE
;
1077 sp
->ttis
[0].tt_abbrind
= 0;
1078 sp
->ttis
[1].tt_gmtoff
= -dstoffset
;
1079 sp
->ttis
[1].tt_isdst
= TRUE
;
1080 sp
->ttis
[1].tt_abbrind
= stdlen
+ 1;
1085 sp
->typecnt
= 1; /* only standard time */
1087 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
1088 sp
->ttis
[0].tt_isdst
= 0;
1089 sp
->ttis
[0].tt_abbrind
= 0;
1091 sp
->charcnt
= stdlen
+ 1;
1093 sp
->charcnt
+= dstlen
+ 1;
1094 if ((size_t) sp
->charcnt
> sizeof sp
->chars
)
1097 (void) strncpy(cp
, stdname
, stdlen
);
1101 (void) strncpy(cp
, dstname
, dstlen
);
1102 *(cp
+ dstlen
) = '\0';
1109 struct state
* const sp
;
1111 if (tzload(gmt
, sp
, TRUE
) != 0)
1112 (void) tzparse(gmt
, sp
, TRUE
);
1115 #ifndef STD_INSPIRED
1117 ** A non-static declaration of tzsetwall in a system header file
1118 ** may cause a warning about this upcoming static declaration...
1121 #endif /* !defined STD_INSPIRED */
1130 if (lclptr
== NULL
) {
1131 lclptr
= (struct state
*) malloc(sizeof *lclptr
);
1132 if (lclptr
== NULL
) {
1133 settzname(); /* all we can do */
1137 #endif /* defined ALL_STATE */
1138 if (tzload((char *) NULL
, lclptr
, TRUE
) != 0)
1146 register const char * name
;
1148 name
= getenv("TZ");
1154 if (lcl_is_set
> 0 && strcmp(lcl_TZname
, name
) == 0)
1156 lcl_is_set
= strlen(name
) < sizeof lcl_TZname
;
1158 (void) strcpy(lcl_TZname
, name
);
1161 if (lclptr
== NULL
) {
1162 lclptr
= (struct state
*) malloc(sizeof *lclptr
);
1163 if (lclptr
== NULL
) {
1164 settzname(); /* all we can do */
1168 #endif /* defined ALL_STATE */
1169 if (*name
== '\0') {
1171 ** User wants it fast rather than right.
1173 lclptr
->leapcnt
= 0; /* so, we're off a little */
1174 lclptr
->timecnt
= 0;
1175 lclptr
->typecnt
= 0;
1176 lclptr
->ttis
[0].tt_isdst
= 0;
1177 lclptr
->ttis
[0].tt_gmtoff
= 0;
1178 lclptr
->ttis
[0].tt_abbrind
= 0;
1179 (void) strcpy(lclptr
->chars
, gmt
);
1180 } else if (tzload(name
, lclptr
, TRUE
) != 0)
1181 if (name
[0] == ':' || tzparse(name
, lclptr
, FALSE
) != 0)
1182 (void) gmtload(lclptr
);
1187 ** The easy way to behave "as if no library function calls" localtime
1188 ** is to not call it--so we drop its guts into "localsub", which can be
1189 ** freely called. (And no, the PANS doesn't require the above behavior--
1190 ** but it *is* desirable.)
1192 ** The unused offset argument is for the benefit of mktime variants.
1197 localsub(timep
, offset
, tmp
)
1198 const time_t * const timep
;
1200 struct tm
* const tmp
;
1202 register struct state
* sp
;
1203 register const struct ttinfo
* ttisp
;
1205 register struct tm
* result
;
1206 const time_t t
= *timep
;
1211 return gmtsub(timep
, offset
, tmp
);
1212 #endif /* defined ALL_STATE */
1213 if ((sp
->goback
&& t
< sp
->ats
[0]) ||
1214 (sp
->goahead
&& t
> sp
->ats
[sp
->timecnt
- 1])) {
1216 register time_t seconds
;
1217 register time_t tcycles
;
1218 register int_fast64_t icycles
;
1221 seconds
= sp
->ats
[0] - t
;
1222 else seconds
= t
- sp
->ats
[sp
->timecnt
- 1];
1224 tcycles
= seconds
/ YEARSPERREPEAT
/ AVGSECSPERYEAR
;
1227 if (tcycles
- icycles
>= 1 || icycles
- tcycles
>= 1)
1230 seconds
*= YEARSPERREPEAT
;
1231 seconds
*= AVGSECSPERYEAR
;
1234 else newt
-= seconds
;
1235 if (newt
< sp
->ats
[0] ||
1236 newt
> sp
->ats
[sp
->timecnt
- 1])
1237 return NULL
; /* "cannot happen" */
1238 result
= localsub(&newt
, offset
, tmp
);
1239 if (result
== tmp
) {
1240 register time_t newy
;
1242 newy
= tmp
->tm_year
;
1244 newy
-= icycles
* YEARSPERREPEAT
;
1245 else newy
+= icycles
* YEARSPERREPEAT
;
1246 tmp
->tm_year
= newy
;
1247 if (tmp
->tm_year
!= newy
)
1252 if (sp
->timecnt
== 0 || t
< sp
->ats
[0]) {
1254 while (sp
->ttis
[i
].tt_isdst
)
1255 if (++i
>= sp
->typecnt
) {
1260 register int lo
= 1;
1261 register int hi
= sp
->timecnt
;
1264 register int mid
= (lo
+ hi
) >> 1;
1266 if (t
< sp
->ats
[mid
])
1270 i
= (int) sp
->types
[lo
- 1];
1272 ttisp
= &sp
->ttis
[i
];
1274 ** To get (wrong) behavior that's compatible with System V Release 2.0
1275 ** you'd replace the statement below with
1276 ** t += ttisp->tt_gmtoff;
1277 ** timesub(&t, 0L, sp, tmp);
1279 result
= timesub(&t
, ttisp
->tt_gmtoff
, sp
, tmp
);
1280 tmp
->tm_isdst
= ttisp
->tt_isdst
;
1281 tzname
[tmp
->tm_isdst
] = &sp
->chars
[ttisp
->tt_abbrind
];
1283 tmp
->TM_ZONE
= &sp
->chars
[ttisp
->tt_abbrind
];
1284 #endif /* defined TM_ZONE */
1290 const time_t * const timep
;
1293 return localsub(timep
, 0L, &tm
);
1297 ** Re-entrant version of localtime.
1301 localtime_r(timep
, tmp
)
1302 const time_t * const timep
;
1305 return localsub(timep
, 0L, tmp
);
1309 ** gmtsub is to gmtime as localsub is to localtime.
1313 gmtsub(timep
, offset
, tmp
)
1314 const time_t * const timep
;
1316 struct tm
* const tmp
;
1318 register struct tm
* result
;
1323 gmtptr
= (struct state
*) malloc(sizeof *gmtptr
);
1325 #endif /* defined ALL_STATE */
1328 result
= timesub(timep
, offset
, gmtptr
, tmp
);
1331 ** Could get fancy here and deliver something such as
1332 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
1333 ** but this is no time for a treasure hunt.
1336 tmp
->TM_ZONE
= wildabbr
;
1341 else tmp
->TM_ZONE
= gmtptr
->chars
;
1342 #endif /* defined ALL_STATE */
1344 tmp
->TM_ZONE
= gmtptr
->chars
;
1345 #endif /* State Farm */
1347 #endif /* defined TM_ZONE */
1353 const time_t * const timep
;
1355 return gmtsub(timep
, 0L, &tm
);
1359 * Re-entrant version of gmtime.
1363 gmtime_r(timep
, tmp
)
1364 const time_t * const timep
;
1367 return gmtsub(timep
, 0L, tmp
);
1373 offtime(timep
, offset
)
1374 const time_t * const timep
;
1377 return gmtsub(timep
, offset
, &tm
);
1380 #endif /* defined STD_INSPIRED */
1383 ** Return the number of leap years through the end of the given year
1384 ** where, to make the math easy, the answer for year zero is defined as zero.
1388 leaps_thru_end_of(y
)
1389 register const int y
;
1391 return (y
>= 0) ? (y
/ 4 - y
/ 100 + y
/ 400) :
1392 -(leaps_thru_end_of(-(y
+ 1)) + 1);
1396 timesub(timep
, offset
, sp
, tmp
)
1397 const time_t * const timep
;
1399 register const struct state
* const sp
;
1400 register struct tm
* const tmp
;
1402 register const struct lsinfo
* lp
;
1403 register time_t tdays
;
1404 register int idays
; /* unsigned would be so 2003 */
1407 register const int * ip
;
1415 i
= (sp
== NULL
) ? 0 : sp
->leapcnt
;
1416 #endif /* defined ALL_STATE */
1419 #endif /* State Farm */
1422 if (*timep
>= lp
->ls_trans
) {
1423 if (*timep
== lp
->ls_trans
) {
1424 hit
= ((i
== 0 && lp
->ls_corr
> 0) ||
1425 lp
->ls_corr
> sp
->lsis
[i
- 1].ls_corr
);
1428 sp
->lsis
[i
].ls_trans
==
1429 sp
->lsis
[i
- 1].ls_trans
+ 1 &&
1430 sp
->lsis
[i
].ls_corr
==
1431 sp
->lsis
[i
- 1].ls_corr
+ 1) {
1441 tdays
= *timep
/ SECSPERDAY
;
1442 rem
= *timep
- tdays
* SECSPERDAY
;
1443 while (tdays
< 0 || tdays
>= year_lengths
[isleap(y
)]) {
1445 register time_t tdelta
;
1446 register int idelta
;
1447 register int leapdays
;
1449 tdelta
= tdays
/ DAYSPERLYEAR
;
1451 if (tdelta
- idelta
>= 1 || idelta
- tdelta
>= 1)
1454 idelta
= (tdays
< 0) ? -1 : 1;
1456 if (increment_overflow(&newy
, idelta
))
1458 leapdays
= leaps_thru_end_of(newy
- 1) -
1459 leaps_thru_end_of(y
- 1);
1460 tdays
-= ((time_t) newy
- y
) * DAYSPERNYEAR
;
1465 register long seconds
;
1467 seconds
= tdays
* SECSPERDAY
+ 0.5;
1468 tdays
= seconds
/ SECSPERDAY
;
1469 rem
+= seconds
- tdays
* SECSPERDAY
;
1472 ** Given the range, we can now fearlessly cast...
1475 rem
+= offset
- corr
;
1480 while (rem
>= SECSPERDAY
) {
1485 if (increment_overflow(&y
, -1))
1487 idays
+= year_lengths
[isleap(y
)];
1489 while (idays
>= year_lengths
[isleap(y
)]) {
1490 idays
-= year_lengths
[isleap(y
)];
1491 if (increment_overflow(&y
, 1))
1495 if (increment_overflow(&tmp
->tm_year
, -TM_YEAR_BASE
))
1497 tmp
->tm_yday
= idays
;
1499 ** The "extra" mods below avoid overflow problems.
1501 tmp
->tm_wday
= EPOCH_WDAY
+
1502 ((y
- EPOCH_YEAR
) % DAYSPERWEEK
) *
1503 (DAYSPERNYEAR
% DAYSPERWEEK
) +
1504 leaps_thru_end_of(y
- 1) -
1505 leaps_thru_end_of(EPOCH_YEAR
- 1) +
1507 tmp
->tm_wday
%= DAYSPERWEEK
;
1508 if (tmp
->tm_wday
< 0)
1509 tmp
->tm_wday
+= DAYSPERWEEK
;
1510 tmp
->tm_hour
= (int) (rem
/ SECSPERHOUR
);
1512 tmp
->tm_min
= (int) (rem
/ SECSPERMIN
);
1514 ** A positive leap second requires a special
1515 ** representation. This uses "... ??:59:60" et seq.
1517 tmp
->tm_sec
= (int) (rem
% SECSPERMIN
) + hit
;
1518 ip
= mon_lengths
[isleap(y
)];
1519 for (tmp
->tm_mon
= 0; idays
>= ip
[tmp
->tm_mon
]; ++(tmp
->tm_mon
))
1520 idays
-= ip
[tmp
->tm_mon
];
1521 tmp
->tm_mday
= (int) (idays
+ 1);
1524 tmp
->TM_GMTOFF
= offset
;
1525 #endif /* defined TM_GMTOFF */
1531 const time_t * const timep
;
1534 ** Section 4.12.3.2 of X3.159-1989 requires that
1535 ** The ctime function converts the calendar time pointed to by timer
1536 ** to local time in the form of a string. It is equivalent to
1537 ** asctime(localtime(timer))
1539 return asctime(localtime(timep
));
1544 const time_t * const timep
;
1549 return asctime_r(localtime_r(timep
, &mytm
), buf
);
1553 ** Adapted from code provided by Robert Elz, who writes:
1554 ** The "best" way to do mktime I think is based on an idea of Bob
1555 ** Kridle's (so its said...) from a long time ago.
1556 ** It does a binary search of the time_t space. Since time_t's are
1557 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
1558 ** would still be very reasonable).
1563 #endif /* !defined WRONG */
1566 ** Simplified normalize logic courtesy Paul Eggert.
1570 increment_overflow(number
, delta
)
1578 return (*number
< number0
) != (delta
< 0);
1582 long_increment_overflow(number
, delta
)
1590 return (*number
< number0
) != (delta
< 0);
1594 normalize_overflow(tensptr
, unitsptr
, base
)
1595 int * const tensptr
;
1596 int * const unitsptr
;
1599 register int tensdelta
;
1601 tensdelta
= (*unitsptr
>= 0) ?
1602 (*unitsptr
/ base
) :
1603 (-1 - (-1 - *unitsptr
) / base
);
1604 *unitsptr
-= tensdelta
* base
;
1605 return increment_overflow(tensptr
, tensdelta
);
1609 long_normalize_overflow(tensptr
, unitsptr
, base
)
1610 long * const tensptr
;
1611 int * const unitsptr
;
1614 register int tensdelta
;
1616 tensdelta
= (*unitsptr
>= 0) ?
1617 (*unitsptr
/ base
) :
1618 (-1 - (-1 - *unitsptr
) / base
);
1619 *unitsptr
-= tensdelta
* base
;
1620 return long_increment_overflow(tensptr
, tensdelta
);
1625 register const struct tm
* const atmp
;
1626 register const struct tm
* const btmp
;
1628 register int result
;
1630 if ((result
= (atmp
->tm_year
- btmp
->tm_year
)) == 0 &&
1631 (result
= (atmp
->tm_mon
- btmp
->tm_mon
)) == 0 &&
1632 (result
= (atmp
->tm_mday
- btmp
->tm_mday
)) == 0 &&
1633 (result
= (atmp
->tm_hour
- btmp
->tm_hour
)) == 0 &&
1634 (result
= (atmp
->tm_min
- btmp
->tm_min
)) == 0)
1635 result
= atmp
->tm_sec
- btmp
->tm_sec
;
1640 time2sub(tmp
, funcp
, offset
, okayp
, do_norm_secs
)
1641 struct tm
* const tmp
;
1642 struct tm
* (* const funcp
) P((const time_t*, long, struct tm
*));
1645 const int do_norm_secs
;
1647 register const struct state
* sp
;
1650 register int saved_seconds
;
1657 struct tm yourtm
, mytm
;
1662 if (normalize_overflow(&yourtm
.tm_min
, &yourtm
.tm_sec
,
1666 if (normalize_overflow(&yourtm
.tm_hour
, &yourtm
.tm_min
, MINSPERHOUR
))
1668 if (normalize_overflow(&yourtm
.tm_mday
, &yourtm
.tm_hour
, HOURSPERDAY
))
1671 if (long_normalize_overflow(&y
, &yourtm
.tm_mon
, MONSPERYEAR
))
1674 ** Turn y into an actual year number for now.
1675 ** It is converted back to an offset from TM_YEAR_BASE later.
1677 if (long_increment_overflow(&y
, TM_YEAR_BASE
))
1679 while (yourtm
.tm_mday
<= 0) {
1680 if (long_increment_overflow(&y
, -1))
1682 li
= y
+ (1 < yourtm
.tm_mon
);
1683 yourtm
.tm_mday
+= year_lengths
[isleap(li
)];
1685 while (yourtm
.tm_mday
> DAYSPERLYEAR
) {
1686 li
= y
+ (1 < yourtm
.tm_mon
);
1687 yourtm
.tm_mday
-= year_lengths
[isleap(li
)];
1688 if (long_increment_overflow(&y
, 1))
1692 i
= mon_lengths
[isleap(y
)][yourtm
.tm_mon
];
1693 if (yourtm
.tm_mday
<= i
)
1695 yourtm
.tm_mday
-= i
;
1696 if (++yourtm
.tm_mon
>= MONSPERYEAR
) {
1698 if (long_increment_overflow(&y
, 1))
1702 if (long_increment_overflow(&y
, -TM_YEAR_BASE
))
1705 if (yourtm
.tm_year
!= y
)
1707 if (yourtm
.tm_sec
>= 0 && yourtm
.tm_sec
< SECSPERMIN
)
1709 else if (y
+ TM_YEAR_BASE
< EPOCH_YEAR
) {
1711 ** We can't set tm_sec to 0, because that might push the
1712 ** time below the minimum representable time.
1713 ** Set tm_sec to 59 instead.
1714 ** This assumes that the minimum representable time is
1715 ** not in the same minute that a leap second was deleted from,
1716 ** which is a safer assumption than using 58 would be.
1718 if (increment_overflow(&yourtm
.tm_sec
, 1 - SECSPERMIN
))
1720 saved_seconds
= yourtm
.tm_sec
;
1721 yourtm
.tm_sec
= SECSPERMIN
- 1;
1723 saved_seconds
= yourtm
.tm_sec
;
1727 ** Do a binary search (this works whatever time_t's type is).
1729 if (!TYPE_SIGNED(time_t)) {
1732 } else if (!TYPE_INTEGRAL(time_t)) {
1733 if (sizeof(time_t) > sizeof(float))
1734 hi
= (time_t) DBL_MAX
;
1735 else hi
= (time_t) FLT_MAX
;
1739 for (i
= 0; i
< (int) TYPE_BIT(time_t) - 1; ++i
)
1744 t
= lo
/ 2 + hi
/ 2;
1749 if ((*funcp
)(&t
, offset
, &mytm
) == NULL
) {
1751 ** Assume that t is too extreme to be represented in
1752 ** a struct tm; arrange things so that it is less
1753 ** extreme on the next pass.
1755 dir
= (t
> 0) ? 1 : -1;
1756 } else dir
= tmcomp(&mytm
, &yourtm
);
1763 } else if (t
== hi
) {
1776 if (yourtm
.tm_isdst
< 0 || mytm
.tm_isdst
== yourtm
.tm_isdst
)
1779 ** Right time, wrong type.
1780 ** Hunt for right time, right type.
1781 ** It's okay to guess wrong since the guess
1785 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
1787 sp
= (const struct state
*)
1788 (((void *) funcp
== (void *) localsub
) ?
1793 #endif /* defined ALL_STATE */
1794 for (i
= sp
->typecnt
- 1; i
>= 0; --i
) {
1795 if (sp
->ttis
[i
].tt_isdst
!= yourtm
.tm_isdst
)
1797 for (j
= sp
->typecnt
- 1; j
>= 0; --j
) {
1798 if (sp
->ttis
[j
].tt_isdst
== yourtm
.tm_isdst
)
1800 newt
= t
+ sp
->ttis
[j
].tt_gmtoff
-
1801 sp
->ttis
[i
].tt_gmtoff
;
1802 if ((*funcp
)(&newt
, offset
, &mytm
) == NULL
)
1804 if (tmcomp(&mytm
, &yourtm
) != 0)
1806 if (mytm
.tm_isdst
!= yourtm
.tm_isdst
)
1818 newt
= t
+ saved_seconds
;
1819 if ((newt
< t
) != (saved_seconds
< 0))
1822 if ((*funcp
)(&t
, offset
, tmp
))
1828 time2(tmp
, funcp
, offset
, okayp
)
1829 struct tm
* const tmp
;
1830 struct tm
* (* const funcp
) P((const time_t*, long, struct tm
*));
1837 ** First try without normalization of seconds
1838 ** (in case tm_sec contains a value associated with a leap second).
1839 ** If that fails, try with normalization of seconds.
1841 t
= time2sub(tmp
, funcp
, offset
, okayp
, FALSE
);
1842 return *okayp
? t
: time2sub(tmp
, funcp
, offset
, okayp
, TRUE
);
1846 time1(tmp
, funcp
, offset
)
1847 struct tm
* const tmp
;
1848 struct tm
* (* const funcp
) P((const time_t *, long, struct tm
*));
1852 register const struct state
* sp
;
1853 register int samei
, otheri
;
1854 register int sameind
, otherind
;
1857 int seen
[TZ_MAX_TYPES
];
1858 int types
[TZ_MAX_TYPES
];
1861 if (tmp
->tm_isdst
> 1)
1863 t
= time2(tmp
, funcp
, offset
, &okay
);
1866 ** PCTS code courtesy Grant Sullivan.
1870 if (tmp
->tm_isdst
< 0)
1871 tmp
->tm_isdst
= 0; /* reset to std and try again */
1872 #endif /* defined PCTS */
1874 if (okay
|| tmp
->tm_isdst
< 0)
1876 #endif /* !defined PCTS */
1878 ** We're supposed to assume that somebody took a time of one type
1879 ** and did some math on it that yielded a "struct tm" that's bad.
1880 ** We try to divine the type they started from and adjust to the
1884 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
1886 sp
= (const struct state
*) (((void *) funcp
== (void *) localsub
) ?
1891 #endif /* defined ALL_STATE */
1892 for (i
= 0; i
< sp
->typecnt
; ++i
)
1895 for (i
= sp
->timecnt
- 1; i
>= 0; --i
)
1896 if (!seen
[sp
->types
[i
]]) {
1897 seen
[sp
->types
[i
]] = TRUE
;
1898 types
[nseen
++] = sp
->types
[i
];
1900 for (sameind
= 0; sameind
< nseen
; ++sameind
) {
1901 samei
= types
[sameind
];
1902 if (sp
->ttis
[samei
].tt_isdst
!= tmp
->tm_isdst
)
1904 for (otherind
= 0; otherind
< nseen
; ++otherind
) {
1905 otheri
= types
[otherind
];
1906 if (sp
->ttis
[otheri
].tt_isdst
== tmp
->tm_isdst
)
1908 tmp
->tm_sec
+= sp
->ttis
[otheri
].tt_gmtoff
-
1909 sp
->ttis
[samei
].tt_gmtoff
;
1910 tmp
->tm_isdst
= !tmp
->tm_isdst
;
1911 t
= time2(tmp
, funcp
, offset
, &okay
);
1914 tmp
->tm_sec
-= sp
->ttis
[otheri
].tt_gmtoff
-
1915 sp
->ttis
[samei
].tt_gmtoff
;
1916 tmp
->tm_isdst
= !tmp
->tm_isdst
;
1924 struct tm
* const tmp
;
1927 return time1(tmp
, localsub
, 0L);
1934 struct tm
* const tmp
;
1936 tmp
->tm_isdst
= -1; /* in case it wasn't initialized */
1942 struct tm
* const tmp
;
1945 return time1(tmp
, gmtsub
, 0L);
1949 timeoff(tmp
, offset
)
1950 struct tm
* const tmp
;
1954 return time1(tmp
, gmtsub
, offset
);
1957 #endif /* defined STD_INSPIRED */
1962 ** The following is supplied for compatibility with
1963 ** previous versions of the CMUCS runtime library.
1968 struct tm
* const tmp
;
1970 const time_t t
= mktime(tmp
);
1977 #endif /* defined CMUCS */
1980 ** XXX--is the below the right way to conditionalize??
1986 ** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
1987 ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
1988 ** is not the case if we are accounting for leap seconds.
1989 ** So, we provide the following conversion routines for use
1990 ** when exchanging timestamps with POSIX conforming systems.
1997 register struct state
* sp
;
1998 register struct lsinfo
* lp
;
2005 if (*timep
>= lp
->ls_trans
)
2016 return t
- leapcorr(&t
);
2028 ** For a positive leap second hit, the result
2029 ** is not unique. For a negative leap second
2030 ** hit, the corresponding time doesn't exist,
2031 ** so we return an adjacent second.
2033 x
= t
+ leapcorr(&t
);
2034 y
= x
- leapcorr(&x
);
2038 y
= x
- leapcorr(&x
);
2045 y
= x
- leapcorr(&x
);
2053 #endif /* defined STD_INSPIRED */