µ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-2023 Liviu Ionescu. All rights reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software
7 * for any purpose is hereby granted, under the terms of the MIT license.
8 *
9 * If a copy of the license was not distributed with this file, it can
10 * be obtained from https://opensource.org/licenses/mit/.
11 */
12
13#include <time.h>
14#include <stdlib.h>
15
16// ----------------------------------------------------------------------------
17
25#pragma GCC diagnostic push
26#if defined(__clang__)
27#pragma clang diagnostic ignored "-Wreserved-id-macro"
28#endif
29
30#define _SEC_IN_MINUTE 60L
31#define _SEC_IN_HOUR 3600L
32#define _SEC_IN_DAY 86400L
33
34static const int DAYS_IN_MONTH[12] =
35 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
36
37#define _DAYS_IN_MONTH(x) ((x == 1) ? days_in_feb : DAYS_IN_MONTH[x])
38
39#pragma GCC diagnostic push
40#if defined(__clang__)
41#pragma clang diagnostic ignored "-Wreserved-identifier"
42#endif
43static const int _DAYS_BEFORE_MONTH[12] =
44 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
45#pragma GCC diagnostic pop
46
47#define _ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || (((y)+1900) % 400) == 0))
48#define _DAYS_IN_YEAR(year) (_ISLEAP(year) ? 366 : 365)
49
50#pragma GCC diagnostic pop
51
52static void
53validate_structure (struct tm *tim_p);
54
55time_t
56timegm (struct tm* tim_p);
57
58// ----------------------------------------------------------------------------
59
60time_t
61timegm (struct tm* tim_p)
62{
63 time_t tim = 0;
64 long days = 0;
65 int year;
66
67 /* validate structure */
68 validate_structure (tim_p);
69
70 /* compute hours, minutes, seconds */
71 tim += tim_p->tm_sec + (tim_p->tm_min * _SEC_IN_MINUTE)
72 + (tim_p->tm_hour * _SEC_IN_HOUR);
73
74 /* compute days in year */
75 days += tim_p->tm_mday - 1;
76 days += _DAYS_BEFORE_MONTH[tim_p->tm_mon];
77 if (tim_p->tm_mon > 1 && _DAYS_IN_YEAR (tim_p->tm_year) == 366)
78 days++;
79
80 /* compute day of the year */
81 tim_p->tm_yday = (int)days;
82
83 if (tim_p->tm_year > 10000 || tim_p->tm_year < -10000)
84 return (time_t) -1;
85
86 /* compute days in other years */
87 if ((year = tim_p->tm_year) > 70)
88 {
89 for (year = 70; year < tim_p->tm_year; year++)
90 days += _DAYS_IN_YEAR(year);
91 }
92 else if (year < 70)
93 {
94 for (year = 69; year > tim_p->tm_year; year--)
95 days -= _DAYS_IN_YEAR(year);
96 days -= _DAYS_IN_YEAR(year);
97 }
98
99 /* compute total seconds */
100 tim += (days * _SEC_IN_DAY);
101
102 /* compute day of the week */
103 if ((tim_p->tm_wday = (int)((days + 4) % 7)) < 0)
104 tim_p->tm_wday += 7;
105
106 return tim;
107}
108
109/*
110 * This is an unfortunate code duplication, but the newlib functions
111 * are also static and cannot be used here.
112 */
113static void
114validate_structure (struct tm *tim_p)
115{
116 div_t res;
117 int days_in_feb = 28;
118
119#pragma GCC diagnostic push
120#if defined(__clang__)
121#elif defined(__GNUC__)
122// For div()
123#pragma GCC diagnostic ignored "-Waggregate-return"
124#endif
125 /* calculate time & date to account for out of range values */
126 if (tim_p->tm_sec < 0 || tim_p->tm_sec > 59)
127 {
128 res = div (tim_p->tm_sec, 60);
129 tim_p->tm_min += res.quot;
130 if ((tim_p->tm_sec = res.rem) < 0)
131 {
132 tim_p->tm_sec += 60;
133 --tim_p->tm_min;
134 }
135 }
136
137 if (tim_p->tm_min < 0 || tim_p->tm_min > 59)
138 {
139 res = div (tim_p->tm_min, 60);
140 tim_p->tm_hour += res.quot;
141 if ((tim_p->tm_min = res.rem) < 0)
142 {
143 tim_p->tm_min += 60;
144 --tim_p->tm_hour;
145 }
146 }
147
148 if (tim_p->tm_hour < 0 || tim_p->tm_hour > 23)
149 {
150 res = div (tim_p->tm_hour, 24);
151 tim_p->tm_mday += res.quot;
152 if ((tim_p->tm_hour = res.rem) < 0)
153 {
154 tim_p->tm_hour += 24;
155 --tim_p->tm_mday;
156 }
157 }
158
159 if (tim_p->tm_mon < 0 || tim_p->tm_mon > 11)
160 {
161 res = div (tim_p->tm_mon, 12);
162 tim_p->tm_year += res.quot;
163 if ((tim_p->tm_mon = res.rem) < 0)
164 {
165 tim_p->tm_mon += 12;
166 --tim_p->tm_year;
167 }
168 }
169#pragma GCC diagnostic pop
170
171 if (_DAYS_IN_YEAR (tim_p->tm_year) == 366)
172 days_in_feb = 29;
173
174 if (tim_p->tm_mday <= 0)
175 {
176 while (tim_p->tm_mday <= 0)
177 {
178 if (--tim_p->tm_mon == -1)
179 {
180 tim_p->tm_year--;
181 tim_p->tm_mon = 11;
182 days_in_feb = ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ? 29 : 28);
183 }
184 tim_p->tm_mday += _DAYS_IN_MONTH(tim_p->tm_mon);
185 }
186 }
187 else
188 {
189 while (tim_p->tm_mday > _DAYS_IN_MONTH(tim_p->tm_mon))
190 {
191 tim_p->tm_mday -= _DAYS_IN_MONTH(tim_p->tm_mon);
192 if (++tim_p->tm_mon == 12)
193 {
194 tim_p->tm_year++;
195 tim_p->tm_mon = 0;
196 days_in_feb = ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ? 29 : 28);
197 }
198 }
199 }
200}
201
202// ----------------------------------------------------------------------------
static void validate_structure(struct tm *tim_p)
Definition timegm.c:114
static const int DAYS_IN_MONTH[12]
Definition timegm.c:34
#define _DAYS_IN_YEAR(year)
Definition timegm.c:48
static const int _DAYS_BEFORE_MONTH[12]
Definition timegm.c:43
#define _SEC_IN_DAY
Definition timegm.c:32
#define _SEC_IN_MINUTE
Definition timegm.c:30
#define _DAYS_IN_MONTH(x)
Definition timegm.c:37
time_t timegm(struct tm *tim_p)
Definition timegm.c:61
#define _SEC_IN_HOUR
Definition timegm.c:31