833d708b8dfcce300cd1e34d314515de8ca713ae
[kopensolaris-gnu/glibc.git] / time / localtime.c
1 /* localtime -- convert `time_t' to `struct tm' in local time zone
2 Copyright (C) 1991, 92, 93, 95, 96 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
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.
9
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.
14
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
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA.  */
19
20 #include <errno.h>
21 #include <time.h>
22 #include <libc-lock.h>
23
24 /* The C Standard says that localtime and gmtime return the same pointer.  */
25 struct tm _tmbuf;
26
27 /* Return the `struct tm' representation of *TIMER in the local timezone.  */
28 struct tm *
29 localtime (timer)
30      const time_t *timer;
31 {
32   return __localtime_r (timer, &_tmbuf);
33 }
34
35 struct tm *
36 __localtime_r (timer, tp)
37      const time_t *timer;
38      struct tm *tp;
39 {
40   /* This lock is defined in tzset.c and locks all the data defined there
41      and in tzfile.c; the internal functions do no locking themselves.
42      This lock is only taken here and in `tzset'.  */
43   __libc_lock_define (extern, __tzset_lock)
44   extern int __use_tzfile;
45   extern int __tz_compute __P ((time_t timer, struct tm *tp));
46   extern int __tzfile_compute __P ((time_t timer,
47                                     long int *leap_correct, int *leap_hit));
48   long int leap_correction;
49   int leap_extra_secs;
50
51   if (timer == NULL)
52     {
53       __set_errno (EINVAL);
54       return NULL;
55     }
56
57   __libc_lock_lock (__tzset_lock);
58
59   /* Make sure the database is initialized.  */
60   __tzset ();
61
62   if (__use_tzfile)
63     {
64       if (! __tzfile_compute (*timer, &leap_correction, &leap_extra_secs))
65         tp = NULL;
66     }
67   else
68     {
69       tp = __gmtime_r (timer, tp);
70       if (tp && ! __tz_compute (*timer, tp))
71         tp = NULL;
72       leap_correction = 0L;
73       leap_extra_secs = 0;
74     }
75
76   if (tp)
77     {
78       __offtime (timer, __timezone - leap_correction, tp);
79       tp->tm_sec += leap_extra_secs;
80       tp->tm_isdst = __daylight;
81       tp->tm_gmtoff = __timezone;
82       tp->tm_zone = __tzname[__daylight];
83     }
84
85   __libc_lock_unlock (__tzset_lock);
86
87   return tp;
88 }
89 weak_alias (__localtime_r, localtime_r)