µOS++ IIIe Reference  v6.3.15
“Perfekt ist nicht gut genug”
The third edition of µOS++, a POSIX inspired open source system, written in C++.
timegm.c
Go to the documentation of this file.
1 /*
2  * This file is part of the µOS++ distribution.
3  * (https://github.com/micro-os-plus)
4  * Copyright (c) 2018 Liviu Ionescu.
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense, and/or
11  * sell copies of the Software, and to permit persons to whom
12  * the Software is furnished to do so, subject to the following
13  * conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  */
27 
28 #include <time.h>
29 #include <stdlib.h>
30 
31 // ----------------------------------------------------------------------------
32 
40 #pragma GCC diagnostic push
41 #if defined(__clang__)
42 #pragma clang diagnostic ignored "-Wreserved-id-macro"
43 #endif
44 
45 #define _SEC_IN_MINUTE 60L
46 #define _SEC_IN_HOUR 3600L
47 #define _SEC_IN_DAY 86400L
48 
49 static const int DAYS_IN_MONTH[12] =
50  { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
51 
52 #define _DAYS_IN_MONTH(x) ((x == 1) ? days_in_feb : DAYS_IN_MONTH[x])
53 
54 static const int _DAYS_BEFORE_MONTH[12] =
55  { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
56 
57 #define _ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || (((y)+1900) % 400) == 0))
58 #define _DAYS_IN_YEAR(year) (_ISLEAP(year) ? 366 : 365)
59 
60 #pragma GCC diagnostic pop
61 
62 static void
63 validate_structure (struct tm *tim_p);
64 
65 time_t
66 timegm (struct tm* tim_p);
67 
68 // ----------------------------------------------------------------------------
69 
70 time_t
71 timegm (struct tm* tim_p)
72 {
73  time_t tim = 0;
74  long days = 0;
75  int year;
76 
77  /* validate structure */
78  validate_structure (tim_p);
79 
80  /* compute hours, minutes, seconds */
81  tim += tim_p->tm_sec + (tim_p->tm_min * _SEC_IN_MINUTE)
82  + (tim_p->tm_hour * _SEC_IN_HOUR);
83 
84  /* compute days in year */
85  days += tim_p->tm_mday - 1;
86  days += _DAYS_BEFORE_MONTH[tim_p->tm_mon];
87  if (tim_p->tm_mon > 1 && _DAYS_IN_YEAR (tim_p->tm_year) == 366)
88  days++;
89 
90  /* compute day of the year */
91  tim_p->tm_yday = (int)days;
92 
93  if (tim_p->tm_year > 10000 || tim_p->tm_year < -10000)
94  return (time_t) -1;
95 
96  /* compute days in other years */
97  if ((year = tim_p->tm_year) > 70)
98  {
99  for (year = 70; year < tim_p->tm_year; year++)
100  days += _DAYS_IN_YEAR(year);
101  }
102  else if (year < 70)
103  {
104  for (year = 69; year > tim_p->tm_year; year--)
105  days -= _DAYS_IN_YEAR(year);
106  days -= _DAYS_IN_YEAR(year);
107  }
108 
109  /* compute total seconds */
110  tim += (days * _SEC_IN_DAY);
111 
112  /* compute day of the week */
113  if ((tim_p->tm_wday = (int)((days + 4) % 7)) < 0)
114  tim_p->tm_wday += 7;
115 
116  return tim;
117 }
118 
119 /*
120  * This is an unfortunate code duplication, but the newlib functions
121  * are also static and cannot be used here.
122  */
123 static void
124 validate_structure (struct tm *tim_p)
125 {
126  div_t res;
127  int days_in_feb = 28;
128 
129  /* calculate time & date to account for out of range values */
130  if (tim_p->tm_sec < 0 || tim_p->tm_sec > 59)
131  {
132  res = div (tim_p->tm_sec, 60);
133  tim_p->tm_min += res.quot;
134  if ((tim_p->tm_sec = res.rem) < 0)
135  {
136  tim_p->tm_sec += 60;
137  --tim_p->tm_min;
138  }
139  }
140 
141  if (tim_p->tm_min < 0 || tim_p->tm_min > 59)
142  {
143  res = div (tim_p->tm_min, 60);
144  tim_p->tm_hour += res.quot;
145  if ((tim_p->tm_min = res.rem) < 0)
146  {
147  tim_p->tm_min += 60;
148  --tim_p->tm_hour;
149  }
150  }
151 
152  if (tim_p->tm_hour < 0 || tim_p->tm_hour > 23)
153  {
154  res = div (tim_p->tm_hour, 24);
155  tim_p->tm_mday += res.quot;
156  if ((tim_p->tm_hour = res.rem) < 0)
157  {
158  tim_p->tm_hour += 24;
159  --tim_p->tm_mday;
160  }
161  }
162 
163  if (tim_p->tm_mon < 0 || tim_p->tm_mon > 11)
164  {
165  res = div (tim_p->tm_mon, 12);
166  tim_p->tm_year += res.quot;
167  if ((tim_p->tm_mon = res.rem) < 0)
168  {
169  tim_p->tm_mon += 12;
170  --tim_p->tm_year;
171  }
172  }
173 
174  if (_DAYS_IN_YEAR (tim_p->tm_year) == 366)
175  days_in_feb = 29;
176 
177  if (tim_p->tm_mday <= 0)
178  {
179  while (tim_p->tm_mday <= 0)
180  {
181  if (--tim_p->tm_mon == -1)
182  {
183  tim_p->tm_year--;
184  tim_p->tm_mon = 11;
185  days_in_feb = ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ? 29 : 28);
186  }
187  tim_p->tm_mday += _DAYS_IN_MONTH(tim_p->tm_mon);
188  }
189  }
190  else
191  {
192  while (tim_p->tm_mday > _DAYS_IN_MONTH(tim_p->tm_mon))
193  {
194  tim_p->tm_mday -= _DAYS_IN_MONTH(tim_p->tm_mon);
195  if (++tim_p->tm_mon == 12)
196  {
197  tim_p->tm_year++;
198  tim_p->tm_mon = 0;
199  days_in_feb = ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ? 29 : 28);
200  }
201  }
202  }
203 }
204 
205 // ----------------------------------------------------------------------------
#define _SEC_IN_DAY
Definition: timegm.c:47
#define _DAYS_IN_MONTH(x)
Definition: timegm.c:52
static const int _DAYS_BEFORE_MONTH[12]
Definition: timegm.c:54
static const int DAYS_IN_MONTH[12]
Definition: timegm.c:49
time_t timegm(struct tm *tim_p)
Definition: timegm.c:71
#define _SEC_IN_HOUR
Definition: timegm.c:46
static void validate_structure(struct tm *tim_p)
Definition: timegm.c:124
#define _SEC_IN_MINUTE
Definition: timegm.c:45
#define _DAYS_IN_YEAR(year)
Definition: timegm.c:58