Subversion Repositories Kolibri OS

Rev

Rev 4921 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/*
2
 * localtime_r.c
6099 serge 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 
7
 * - Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov 
8
 * - Implement localtime_r() with gmtime_r() and the conditional code moved
9
 *   from _mktm_r() - 05/09/14, Freddie Chopin 
4349 Serge 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
 
18
struct tm *
19
_DEFUN (localtime_r, (tim_p, res),
4921 Serge 20
	_CONST time_t *__restrict tim_p _AND
21
	struct tm *__restrict res)
4349 Serge 22
{
6099 serge 23
  long offset;
24
  int hours, mins, secs;
25
  int year;
26
  __tzinfo_type *_CONST tz = __gettzinfo ();
27
  _CONST int *ip;
28
 
29
  res = gmtime_r (tim_p, res);
30
 
31
  year = res->tm_year + YEAR_BASE;
32
  ip = __month_lengths[isleap(year)];
33
 
34
  TZ_LOCK;
35
  _tzset_unlocked ();
36
  if (_daylight)
37
    {
38
      if (year == tz->__tzyear || __tzcalc_limits (year))
39
	res->tm_isdst = (tz->__tznorth
40
	  ? (*tim_p >= tz->__tzrule[0].change
41
	  && *tim_p < tz->__tzrule[1].change)
42
	  : (*tim_p >= tz->__tzrule[0].change
43
	  || *tim_p < tz->__tzrule[1].change));
44
      else
45
	res->tm_isdst = -1;
46
    }
47
  else
48
    res->tm_isdst = 0;
49
 
50
  offset = (res->tm_isdst == 1
51
    ? tz->__tzrule[1].offset
52
    : tz->__tzrule[0].offset);
53
 
54
  hours = (int) (offset / SECSPERHOUR);
55
  offset = offset % SECSPERHOUR;
56
 
57
  mins = (int) (offset / SECSPERMIN);
58
  secs = (int) (offset % SECSPERMIN);
59
 
60
  res->tm_sec -= secs;
61
  res->tm_min -= mins;
62
  res->tm_hour -= hours;
63
 
64
  if (res->tm_sec >= SECSPERMIN)
65
    {
66
      res->tm_min += 1;
67
      res->tm_sec -= SECSPERMIN;
68
    }
69
  else if (res->tm_sec < 0)
70
    {
71
      res->tm_min -= 1;
72
      res->tm_sec += SECSPERMIN;
73
    }
74
  if (res->tm_min >= MINSPERHOUR)
75
    {
76
      res->tm_hour += 1;
77
      res->tm_min -= MINSPERHOUR;
78
    }
79
  else if (res->tm_min < 0)
80
    {
81
      res->tm_hour -= 1;
82
      res->tm_min += MINSPERHOUR;
83
    }
84
  if (res->tm_hour >= HOURSPERDAY)
85
    {
86
      ++res->tm_yday;
87
      ++res->tm_wday;
88
      if (res->tm_wday > 6)
89
	res->tm_wday = 0;
90
      ++res->tm_mday;
91
      res->tm_hour -= HOURSPERDAY;
92
      if (res->tm_mday > ip[res->tm_mon])
93
	{
94
	  res->tm_mday -= ip[res->tm_mon];
95
	  res->tm_mon += 1;
96
	  if (res->tm_mon == 12)
97
	    {
98
	      res->tm_mon = 0;
99
	      res->tm_year += 1;
100
	      res->tm_yday = 0;
101
	    }
102
	}
103
    }
104
  else if (res->tm_hour < 0)
105
    {
106
      res->tm_yday -= 1;
107
      res->tm_wday -= 1;
108
      if (res->tm_wday < 0)
109
	res->tm_wday = 6;
110
      res->tm_mday -= 1;
111
      res->tm_hour += 24;
112
      if (res->tm_mday == 0)
113
	{
114
	  res->tm_mon -= 1;
115
	  if (res->tm_mon < 0)
116
	    {
117
	      res->tm_mon = 11;
118
	      res->tm_year -= 1;
119
	      res->tm_yday = 364 + isleap(res->tm_year + YEAR_BASE);
120
	    }
121
	  res->tm_mday = ip[res->tm_mon];
122
	}
123
    }
124
  TZ_UNLOCK;
125
 
126
  return (res);
4349 Serge 127
}