source: trunk/libs/newlib/src/newlib/libc/time/lcltime_r.c @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 2.9 KB
Line 
1/*
2 * localtime_r.c
3 * Original Author: Adapted from tzcode maintained by Arthur David Olson.
4 * Modifications:
5 * - Changed to mktm_r and added __tzcalc_limits - 04/10/02, Jeff Johnston
6 * - Fixed bug in mday computations - 08/12/04, Alex Mogilnikov <alx@intellectronika.ru>
7 * - Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov <alx@intellectronika.ru>
8 * - Implement localtime_r() with gmtime_r() and the conditional code moved
9 *   from _mktm_r() - 05/09/14, Freddie Chopin <freddie_chopin@op.pl>
10 *
11 * Converts the calendar time pointed to by tim_p into a broken-down time
12 * expressed as local time. Returns a pointer to a structure containing the
13 * broken-down time.
14 */
15
16#include "local.h"
17
18struct tm *
19localtime_r (const time_t *__restrict tim_p,
20        struct tm *__restrict res)
21{
22  long offset;
23  int hours, mins, secs;
24  int year;
25  __tzinfo_type *const tz = __gettzinfo ();
26  const int *ip;
27
28  res = gmtime_r (tim_p, res);
29
30  year = res->tm_year + YEAR_BASE;
31  ip = __month_lengths[isleap(year)];
32
33  TZ_LOCK;
34  _tzset_unlocked ();
35  if (_daylight)
36    {
37      if (year == tz->__tzyear || __tzcalc_limits (year))
38        res->tm_isdst = (tz->__tznorth
39          ? (*tim_p >= tz->__tzrule[0].change
40          && *tim_p < tz->__tzrule[1].change)
41          : (*tim_p >= tz->__tzrule[0].change
42          || *tim_p < tz->__tzrule[1].change));
43      else
44        res->tm_isdst = -1;
45    }
46  else
47    res->tm_isdst = 0;
48
49  offset = (res->tm_isdst == 1
50    ? tz->__tzrule[1].offset
51    : tz->__tzrule[0].offset);
52
53  hours = (int) (offset / SECSPERHOUR);
54  offset = offset % SECSPERHOUR;
55
56  mins = (int) (offset / SECSPERMIN);
57  secs = (int) (offset % SECSPERMIN);
58
59  res->tm_sec -= secs;
60  res->tm_min -= mins;
61  res->tm_hour -= hours;
62
63  if (res->tm_sec >= SECSPERMIN)
64    {
65      res->tm_min += 1;
66      res->tm_sec -= SECSPERMIN;
67    }
68  else if (res->tm_sec < 0)
69    {
70      res->tm_min -= 1;
71      res->tm_sec += SECSPERMIN;
72    }
73  if (res->tm_min >= MINSPERHOUR)
74    {
75      res->tm_hour += 1;
76      res->tm_min -= MINSPERHOUR;
77    }
78  else if (res->tm_min < 0)
79    {
80      res->tm_hour -= 1;
81      res->tm_min += MINSPERHOUR;
82    }
83  if (res->tm_hour >= HOURSPERDAY)
84    {
85      ++res->tm_yday;
86      ++res->tm_wday;
87      if (res->tm_wday > 6)
88        res->tm_wday = 0;
89      ++res->tm_mday;
90      res->tm_hour -= HOURSPERDAY;
91      if (res->tm_mday > ip[res->tm_mon])
92        {
93          res->tm_mday -= ip[res->tm_mon];
94          res->tm_mon += 1;
95          if (res->tm_mon == 12)
96            {
97              res->tm_mon = 0;
98              res->tm_year += 1;
99              res->tm_yday = 0;
100            }
101        }
102    }
103  else if (res->tm_hour < 0)
104    {
105      res->tm_yday -= 1;
106      res->tm_wday -= 1;
107      if (res->tm_wday < 0)
108        res->tm_wday = 6;
109      res->tm_mday -= 1;
110      res->tm_hour += 24;
111      if (res->tm_mday == 0)
112        {
113          res->tm_mon -= 1;
114          if (res->tm_mon < 0)
115            {
116              res->tm_mon = 11;
117              res->tm_year -= 1;
118              res->tm_yday = 364 + isleap(res->tm_year + YEAR_BASE);
119            }
120          res->tm_mday = ip[res->tm_mon];
121        }
122    }
123  TZ_UNLOCK;
124
125  return (res);
126}
Note: See TracBrowser for help on using the repository browser.