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