µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
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
49static 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
54static 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
62static void
63validate_structure (struct tm *tim_p);
64
65time_t
66timegm (struct tm* tim_p);
67
68// ----------------------------------------------------------------------------
69
70time_t
71timegm (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 */
123static void
124validate_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// ----------------------------------------------------------------------------
static void validate_structure(struct tm *tim_p)
Definition timegm.c:124
static const int DAYS_IN_MONTH[12]
Definition timegm.c:49
#define _DAYS_IN_YEAR(year)
Definition timegm.c:58
static const int _DAYS_BEFORE_MONTH[12]
Definition timegm.c:54
#define _SEC_IN_DAY
Definition timegm.c:47
#define _SEC_IN_MINUTE
Definition timegm.c:45
#define _DAYS_IN_MONTH(x)
Definition timegm.c:52
time_t timegm(struct tm *tim_p)
Definition timegm.c:71
#define _SEC_IN_HOUR
Definition timegm.c:46