1 /* Copyright (C) 1991-2016 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
20 #include <libc-lock.h>
30 #include <timezone/tzfile.h>
32 char *__tzname
[2] = { (char *) "GMT", (char *) "GMT" };
34 long int __timezone
= 0L;
36 weak_alias (__tzname
, tzname
)
37 weak_alias (__daylight
, daylight
)
38 weak_alias (__timezone
, timezone
)
40 /* This locks all the state variables in tzfile.c and this file. */
41 __libc_lock_define_initialized (static, tzset_lock
)
44 #define min(a, b) ((a) < (b) ? (a) : (b))
45 #define max(a, b) ((a) > (b) ? (a) : (b))
46 #define sign(x) ((x) < 0 ? -1 : 1)
49 /* This structure contains all the information about a
50 timezone given in the POSIX standard TZ envariable. */
56 enum { J0
, J1
, M
} type
; /* Interpretation of: */
57 unsigned short int m
, n
, d
; /* Month, week, day. */
58 int secs
; /* Time of day. */
60 long int offset
; /* Seconds east of GMT (west if < 0). */
62 /* We cache the computed time of change for a
63 given year so we don't have to recompute it. */
64 time_t change
; /* When to change to this zone. */
65 int computed_for
; /* Year above is computed for. */
68 /* tz_rules[0] is standard, tz_rules[1] is daylight. */
69 static tz_rule tz_rules
[2];
72 static void compute_change (tz_rule
*rule
, int year
) __THROW internal_function
;
73 static void tzset_internal (int always
, int explicit)
74 __THROW internal_function
;
76 /* List of buffers containing time zone strings. */
79 struct tzstring_l
*next
;
80 size_t len
; /* strlen(data) - doesn't count terminating NUL! */
84 static struct tzstring_l
*tzstring_list
;
86 /* Allocate a permanent home for the first LEN characters of S. It
87 will never be moved or deallocated, but may share space with other
88 strings. Don't modify the returned string. */
90 __tzstring_len (const char *s
, size_t len
)
93 struct tzstring_l
*t
, *u
, *new;
95 /* Walk the list and look for a match. If this string is the same
96 as the end of an already-allocated string, it can share space. */
97 for (u
= t
= tzstring_list
; t
; u
= t
, t
= t
->next
)
100 p
= &t
->data
[t
->len
- len
];
101 if (memcmp (s
, p
, len
) == 0)
105 /* Not found; allocate a new buffer. */
106 new = malloc (sizeof (struct tzstring_l
) + len
+ 1);
112 memcpy (new->data
, s
, len
);
113 new->data
[len
] = '\0';
123 /* Allocate a permanent home for S. It will never be moved or
124 deallocated, but may share space with other strings. Don't modify
125 the returned string. */
127 __tzstring (const char *s
)
129 return __tzstring_len (s
, strlen (s
));
132 /* Maximum length of a timezone name. tzset_internal keeps this up to date
133 (never decreasing it) when ! __use_tzfile.
134 tzfile.c keeps it up to date when __use_tzfile. */
135 size_t __tzname_cur_max
;
140 __libc_lock_lock (tzset_lock
);
142 tzset_internal (0, 0);
144 __libc_lock_unlock (tzset_lock
);
146 return __tzname_cur_max
;
155 __daylight
= tz_rules
[0].offset
!= tz_rules
[1].offset
;
156 __timezone
= -tz_rules
[0].offset
;
157 __tzname
[0] = (char *) tz_rules
[0].name
;
158 __tzname
[1] = (char *) tz_rules
[1].name
;
160 /* Keep __tzname_cur_max up to date. */
161 size_t len0
= strlen (__tzname
[0]);
162 size_t len1
= strlen (__tzname
[1]);
163 if (len0
> __tzname_cur_max
)
164 __tzname_cur_max
= len0
;
165 if (len1
> __tzname_cur_max
)
166 __tzname_cur_max
= len1
;
171 __attribute_noinline__
172 compute_offset (unsigned int ss
, unsigned int mm
, unsigned int hh
)
174 return min (ss
, 59) + min (mm
, 59) * 60 + min (hh
, 24) * 60 * 60;
177 /* Parses the time zone name at *TZP, and writes a pointer to an
178 interned string to tz_rules[WHICHRULE].name. On success, advances
179 *TZP, and returns true. Returns false otherwise. */
181 parse_tzname (const char **tzp
, int whichrule
)
183 const char *start
= *tzp
;
184 const char *p
= start
;
185 while (('a' <= *p
&& *p
<= 'z')
186 || ('A' <= *p
&& *p
<= 'Z'))
188 size_t len
= p
- start
;
192 if (__glibc_unlikely (*p
++ != '<'))
195 while (('a' <= *p
&& *p
<= 'z')
196 || ('A' <= *p
&& *p
<= 'Z')
197 || ('0' <= *p
&& *p
<= '9')
198 || *p
== '+' || *p
== '-')
201 if (*p
++ != '>' || len
< 3)
205 const char *name
= __tzstring_len (start
, len
);
208 tz_rules
[whichrule
].name
= name
;
214 /* Parses the time zone offset at *TZP, and writes it to
215 tz_rules[WHICHRULE].offset. Returns true if the parse was
218 parse_offset (const char **tzp
, int whichrule
)
220 const char *tz
= *tzp
;
222 && (*tz
== '\0' || (*tz
!= '+' && *tz
!= '-' && !isdigit (*tz
))))
226 if (*tz
== '-' || *tz
== '+')
227 sign
= *tz
++ == '-' ? 1L : -1L;
232 unsigned short int hh
;
233 unsigned short mm
= 0;
234 unsigned short ss
= 0;
236 if (sscanf (tz
, "%hu%n:%hu%n:%hu%n",
237 &hh
, &consumed
, &mm
, &consumed
, &ss
, &consumed
) > 0)
238 tz_rules
[whichrule
].offset
= sign
* compute_offset (ss
, mm
, hh
);
240 /* Nothing could be parsed. */
243 /* Standard time defaults to offset zero. */
244 tz_rules
[0].offset
= 0;
248 /* DST defaults to one hour later than standard time. */
249 tz_rules
[1].offset
= tz_rules
[0].offset
+ (60 * 60);
250 *tzp
= tz
+ consumed
;
254 /* Parses the standard <-> DST rules at *TZP. Updates
255 tz_rule[WHICHRULE]. On success, advances *TZP and returns true.
256 Otherwise, returns false. */
258 parse_rule (const char **tzp
, int whichrule
)
260 const char *tz
= *tzp
;
261 tz_rule
*tzr
= &tz_rules
[whichrule
];
263 /* Ignore comma to support string following the incorrect
264 specification in early POSIX.1 printings. */
267 /* Get the date of the change. */
268 if (*tz
== 'J' || isdigit (*tz
))
271 tzr
->type
= *tz
== 'J' ? J1
: J0
;
272 if (tzr
->type
== J1
&& !isdigit (*++tz
))
274 unsigned long int d
= strtoul (tz
, &end
, 10);
275 if (end
== tz
|| d
> 365)
277 if (tzr
->type
== J1
&& d
== 0)
286 if (sscanf (tz
, "M%hu.%hu.%hu%n",
287 &tzr
->m
, &tzr
->n
, &tzr
->d
, &consumed
) != 3
288 || tzr
->m
< 1 || tzr
->m
> 12
289 || tzr
->n
< 1 || tzr
->n
> 5 || tzr
->d
> 6)
293 else if (*tz
== '\0')
295 /* Daylight time rules in the U.S. are defined in the U.S. Code,
296 Title 15, Chapter 6, Subchapter IX - Standard Time. These
297 dates were established by Congress in the Energy Policy Act
298 of 2005 [Pub. L. no. 109-58, 119 Stat 594 (2005)].
299 Below is the equivalent of "M3.2.0,M11.1.0" [/2 not needed
300 since 2:00AM is the default]. */
302 if (tzr
== &tz_rules
[0])
318 if (*tz
!= '\0' && *tz
!= '/' && *tz
!= ',')
322 /* Get the time of day of the change. */
327 negative
= *tz
== '-';
329 /* Default to 2:00 AM. */
330 unsigned short hh
= 2;
331 unsigned short mm
= 0;
332 unsigned short ss
= 0;
334 sscanf (tz
, "%hu%n:%hu%n:%hu%n",
335 &hh
, &consumed
, &mm
, &consumed
, &ss
, &consumed
);;
337 tzr
->secs
= (negative
? -1 : 1) * ((hh
* 60 * 60) + (mm
* 60) + ss
);
340 /* Default to 2:00 AM. */
341 tzr
->secs
= 2 * 60 * 60;
343 tzr
->computed_for
= -1;
348 /* Parse the POSIX TZ-style string. */
350 __tzset_parse_tz (const char *tz
)
352 /* Clear out old state and reset to unnamed UTC. */
353 memset (tz_rules
, '\0', sizeof tz_rules
);
354 tz_rules
[0].name
= tz_rules
[1].name
= "";
356 /* Get the standard timezone name. */
357 if (parse_tzname (&tz
, 0) && parse_offset (&tz
, 0))
359 /* Get the DST timezone name (if any). */
362 if (parse_tzname (&tz
, 1))
364 parse_offset (&tz
, 1);
365 if (*tz
== '\0' || (tz
[0] == ',' && tz
[1] == '\0'))
367 /* There is no rule. See if there is a default rule
369 __tzfile_default (tz_rules
[0].name
, tz_rules
[1].name
,
370 tz_rules
[0].offset
, tz_rules
[1].offset
);
379 /* Figure out the standard <-> DST rules. */
380 if (parse_rule (&tz
, 0))
385 /* There is no DST. */
386 tz_rules
[1].name
= tz_rules
[0].name
;
387 tz_rules
[1].offset
= tz_rules
[0].offset
;
394 /* Interpret the TZ envariable. */
397 tzset_internal (int always
, int explicit)
399 static int is_initialized
;
402 if (is_initialized
&& !always
)
406 /* Examine the TZ environment variable. */
408 if (tz
== NULL
&& !explicit)
409 /* Use the site-wide default. This is a file name which means we
410 would not see changes to the file if we compare only the file
411 name for change. We want to notice file changes if tzset() has
412 been called explicitly. Leave TZ as NULL in this case. */
414 if (tz
&& *tz
== '\0')
415 /* User specified the empty string; use UTC explicitly. */
418 /* A leading colon means "implementation defined syntax".
419 We ignore the colon and always use the same algorithm:
420 try a data file, and if none exists parse the 1003.1 syntax. */
421 if (tz
&& *tz
== ':')
424 /* Check whether the value changed since the last run. */
425 if (old_tz
!= NULL
&& tz
!= NULL
&& strcmp (tz
, old_tz
) == 0)
426 /* No change, simply return. */
430 /* No user specification; use the site-wide default. */
433 tz_rules
[0].name
= NULL
;
434 tz_rules
[1].name
= NULL
;
436 /* Save the value of `tz'. */
438 old_tz
= tz
? __strdup (tz
) : NULL
;
440 /* Try to read a data file. */
441 __tzfile_read (tz
, 0, NULL
);
445 /* No data file found. Default to UTC if nothing specified. */
447 if (tz
== NULL
|| *tz
== '\0'
448 || (TZDEFAULT
!= NULL
&& strcmp (tz
, TZDEFAULT
) == 0))
450 memset (tz_rules
, '\0', sizeof tz_rules
);
451 tz_rules
[0].name
= tz_rules
[1].name
= "UTC";
453 tz_rules
[0].type
= tz_rules
[1].type
= J0
;
454 tz_rules
[0].change
= tz_rules
[1].change
= (time_t) -1;
459 __tzset_parse_tz (tz
);
462 /* Figure out the exact time (as a time_t) in YEAR
463 when the change described by RULE will occur and
464 put it in RULE->change, saving YEAR in RULE->computed_for. */
467 compute_change (tz_rule
*rule
, int year
)
471 if (year
!= -1 && rule
->computed_for
== year
)
472 /* Operations on times in 2 BC will be slower. Oh well. */
475 /* First set T to January 1st, 0:00:00 GMT in YEAR. */
477 t
= ((year
- 1970) * 365
478 + /* Compute the number of leapdays between 1970 and YEAR
479 (exclusive). There is a leapday every 4th year ... */
480 + ((year
- 1) / 4 - 1970 / 4)
481 /* ... except every 100th year ... */
482 - ((year
- 1) / 100 - 1970 / 100)
483 /* ... but still every 400th year. */
484 + ((year
- 1) / 400 - 1970 / 400)) * SECSPERDAY
;
491 /* Jn - Julian day, 1 == January 1, 60 == March 1 even in leap years.
492 In non-leap years, or if the day number is 59 or less, just
493 add SECSPERDAY times the day number-1 to the time of
494 January 1, midnight, to get the day. */
495 t
+= (rule
->d
- 1) * SECSPERDAY
;
496 if (rule
->d
>= 60 && __isleap (year
))
502 Just add SECSPERDAY times the day number to the time of Jan 1st. */
503 t
+= rule
->d
* SECSPERDAY
;
507 /* Mm.n.d - Nth "Dth day" of month M. */
510 int d
, m1
, yy0
, yy1
, yy2
, dow
;
511 const unsigned short int *myday
=
512 &__mon_yday
[__isleap (year
)][rule
->m
];
514 /* First add SECSPERDAY for each day in months before M. */
515 t
+= myday
[-1] * SECSPERDAY
;
517 /* Use Zeller's Congruence to get day-of-week of first day of month. */
518 m1
= (rule
->m
+ 9) % 12 + 1;
519 yy0
= (rule
->m
<= 2) ? (year
- 1) : year
;
522 dow
= ((26 * m1
- 2) / 10 + 1 + yy2
+ yy2
/ 4 + yy1
/ 4 - 2 * yy1
) % 7;
526 /* DOW is the day-of-week of the first day of the month. Get the
527 day-of-month (zero-origin) of the first DOW day of the month. */
531 for (i
= 1; i
< rule
->n
; ++i
)
533 if (d
+ 7 >= (int) myday
[0] - myday
[-1])
538 /* D is the day-of-month (zero-origin) of the day we want. */
544 /* T is now the Epoch-relative time of 0:00:00 GMT on the day we want.
545 Just add the time of day and local offset from GMT, and we're done. */
547 rule
->change
= t
- rule
->offset
+ rule
->secs
;
548 rule
->computed_for
= year
;
552 /* Figure out the correct timezone for TM and set `__tzname',
553 `__timezone', and `__daylight' accordingly. */
556 __tz_compute (time_t timer
, struct tm
*tm
, int use_localtime
)
558 compute_change (&tz_rules
[0], 1900 + tm
->tm_year
);
559 compute_change (&tz_rules
[1], 1900 + tm
->tm_year
);
565 /* We have to distinguish between northern and southern
566 hemisphere. For the latter the daylight saving time
567 ends in the next year. */
568 if (__builtin_expect (tz_rules
[0].change
569 > tz_rules
[1].change
, 0))
570 isdst
= (timer
< tz_rules
[1].change
571 || timer
>= tz_rules
[0].change
);
573 isdst
= (timer
>= tz_rules
[0].change
574 && timer
< tz_rules
[1].change
);
575 tm
->tm_isdst
= isdst
;
576 tm
->tm_zone
= __tzname
[isdst
];
577 tm
->tm_gmtoff
= tz_rules
[isdst
].offset
;
581 /* Reinterpret the TZ environment variable and set `tzname'. */
587 __libc_lock_lock (tzset_lock
);
589 tzset_internal (1, 1);
594 __tzname
[0] = (char *) tz_rules
[0].name
;
595 __tzname
[1] = (char *) tz_rules
[1].name
;
598 __libc_lock_unlock (tzset_lock
);
600 weak_alias (__tzset
, tzset
)
602 /* Return the `struct tm' representation of *TIMER in the local timezone.
603 Use local time if USE_LOCALTIME is nonzero, UTC otherwise. */
605 __tz_convert (const time_t *timer
, int use_localtime
, struct tm
*tp
)
607 long int leap_correction
;
612 __set_errno (EINVAL
);
616 __libc_lock_lock (tzset_lock
);
618 /* Update internal database according to current TZ setting.
619 POSIX.1 8.3.7.2 says that localtime_r is not required to set tzname.
620 This is a good idea since this allows at least a bit more parallelism. */
621 tzset_internal (tp
== &_tmbuf
&& use_localtime
, 1);
624 __tzfile_compute (*timer
, use_localtime
, &leap_correction
,
625 &leap_extra_secs
, tp
);
628 if (! __offtime (timer
, 0, tp
))
631 __tz_compute (*timer
, tp
, use_localtime
);
632 leap_correction
= 0L;
636 __libc_lock_unlock (tzset_lock
);
647 if (__offtime (timer
, tp
->tm_gmtoff
- leap_correction
, tp
))
648 tp
->tm_sec
+= leap_extra_secs
;
657 libc_freeres_fn (free_mem
)
659 while (tzstring_list
!= NULL
)
661 struct tzstring_l
*old
= tzstring_list
;
663 tzstring_list
= tzstring_list
->next
;