update from main archive 970124
[glibc.git] / time / localtime.c
blobab8fc1ac45294c437516a31436fe6fd4e711806d
1 /* Convert `time_t' to `struct tm' in local time zone.
2 Copyright (C) 1991, 92, 93, 95, 96, 97 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 #include <errno.h>
21 #include <time.h>
22 #include <libc-lock.h>
24 /* The C Standard says that localtime and gmtime return the same pointer. */
25 struct tm _tmbuf;
27 /* Prototype for the internal function to get information based on TZ. */
28 extern void __tzset_internal __P ((int always));
29 extern int __tz_compute __P ((time_t timer, struct tm *tp));
30 extern int __tzfile_compute __P ((time_t timer,
31 long int *leap_correct, int *leap_hit));
33 extern int __use_tzfile;
35 /* This lock is defined in tzset.c and locks all the data defined there
36 and in tzfile.c; the internal functions do no locking themselves.
37 This lock is only taken here and in `tzset'. */
38 __libc_lock_define (extern, __tzset_lock)
41 /* Return the `struct tm' representation of *TIMER in the local timezone. */
42 static struct tm *
43 localtime_internal (const time_t *timer, struct tm *tp)
45 long int leap_correction;
46 int leap_extra_secs;
48 if (timer == NULL)
50 __set_errno (EINVAL);
51 return NULL;
54 if (__use_tzfile)
56 if (! __tzfile_compute (*timer, &leap_correction, &leap_extra_secs))
57 tp = NULL;
59 else
61 tp = __gmtime_r (timer, tp);
62 if (tp && ! __tz_compute (*timer, tp))
63 tp = NULL;
64 leap_correction = 0L;
65 leap_extra_secs = 0;
68 if (tp)
70 __offtime (timer, __timezone - leap_correction, tp);
71 tp->tm_sec += leap_extra_secs;
72 tp->tm_isdst = __daylight;
73 tp->tm_gmtoff = __timezone;
74 tp->tm_zone = __tzname[__daylight];
77 return tp;
81 /* POSIX.1 8.3.7.2 says that localtime_r is not required to set
82 tzname. This is a good idea since this allows at least a bit more
83 parallelism. */
85 struct tm *
86 localtime (timer)
87 const time_t *timer;
89 struct tm *result;
91 __libc_lock_lock (__tzset_lock);
93 /* Update internal database according to current TZ setting. */
94 __tzset_internal (1);
96 result = localtime_internal (timer, &_tmbuf);
98 __libc_lock_unlock (__tzset_lock);
100 return result;
104 struct tm *
105 __localtime_r (timer, tp)
106 const time_t *timer;
107 struct tm *tp;
109 struct tm *result;
111 __libc_lock_lock (__tzset_lock);
113 /* Make sure the database is initialized. */
114 __tzset_internal (0);
116 result = localtime_internal (timer, tp);
118 __libc_lock_unlock (__tzset_lock);
120 return result;
122 weak_alias (__localtime_r, localtime_r)