OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
DateTime.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2//
3// Copyright 2026 Caleb Buahin
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
47
48#ifndef OPENSWMM_ENGINE_DATETIME_HPP
49#define OPENSWMM_ENGINE_DATETIME_HPP
50
51#include <cmath>
52
53namespace openswmm {
54namespace datetime {
55
56// ============================================================================
57// Constants — matching legacy datetime.c exactly
58// ============================================================================
59
60static constexpr int DateDelta = 693594;
61static constexpr double SecsPerDay = 86400.0;
62static constexpr double OneSecond = 1.1574074e-5;
63
64// ============================================================================
65// Date/time type — same as legacy DateTime (double)
66// ============================================================================
67
68using DateTime = double;
69
70// ============================================================================
71// Core functions — numerically identical to legacy datetime.c
72// ============================================================================
73
83inline void divMod(int n, int d, int* result, int* remainder) {
84 if (d == 0) {
85 *result = 0;
86 *remainder = 0;
87 } else {
88 *result = n / d;
89 *remainder = n - d * (*result);
90 }
91}
92
98inline bool isLeapYear(int year) {
99 return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0));
100}
101
110inline DateTime encodeDate(int year, int month, int day) {
111 static constexpr int DaysPerMonth[2][12] = {{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
112 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
113 int i = isLeapYear(year) ? 1 : 0;
114 if (year >= 1 && year <= 9999 && month >= 1 && month <= 12 && day >= 1 &&
115 day <= DaysPerMonth[i][month - 1]) {
116 for (int j = 0; j < month - 1; ++j)
117 day += DaysPerMonth[i][j];
118 int y = year - 1;
119 return y * 365 + y / 4 - y / 100 + y / 400 + day - DateDelta;
120 }
121 return -DateDelta;
122}
123
134inline DateTime encodeTime(int hour, int minute, int second) {
135 if (hour >= 0 && minute >= 0 && second >= 0) {
136 int s = hour * 3600 + minute * 60 + second;
137 return static_cast<double>(s) / SecsPerDay;
138 }
139 return 0.0;
140}
141
152inline void decodeDate(DateTime date, int& year, int& month, int& day) {
153 static constexpr int DaysPerMonth[2][12] = {{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
154 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
155 constexpr int D1 = 365, D4 = 1461, D100 = 36524, D400 = 146097;
156
157 int t = static_cast<int>(std::floor(date)) + DateDelta;
158 if (t <= 0) {
159 year = 0;
160 month = 1;
161 day = 1;
162 return;
163 }
164
165 t--;
166 int y = 1, i, d;
167 while (t >= D400) {
168 t -= D400;
169 y += 400;
170 }
171 divMod(t, D100, &i, &d);
172 if (i == 4) {
173 i--;
174 d += D100;
175 }
176 y += i * 100;
177 divMod(d, D4, &i, &d);
178 y += i * 4;
179 divMod(d, D1, &i, &d);
180 if (i == 4) {
181 i--;
182 d += D1;
183 }
184 y += i;
185
186 int k = isLeapYear(y) ? 1 : 0;
187 int m = 1;
188 for (;;) {
189 i = DaysPerMonth[k][m - 1];
190 if (d < i)
191 break;
192 d -= i;
193 m++;
194 }
195 year = y;
196 month = m;
197 day = d + 1;
198}
199
210inline void decodeTime(DateTime time, int& h, int& m, int& s) {
211 double fracDay = (time - std::floor(time)) * SecsPerDay;
212 int secs = static_cast<int>(std::floor(fracDay + 0.5));
213 if (secs >= 86400)
214 secs = 86399;
215 divMod(secs, 60, &m, &s); // mins, secs
216 int mins = m;
217 divMod(mins, 60, &h, &m); // hours, mins
218 if (h > 23)
219 h = 0;
220}
221
233inline DateTime addSeconds(DateTime date, double seconds) {
234 double d = std::floor(date);
235 int h, m, s;
236 decodeTime(date, h, m, s);
237 return d + (3600.0 * h + 60.0 * m + s + seconds) / SecsPerDay;
238}
239
249inline long timeDiff(DateTime date1, DateTime date2) {
250 double d1 = std::floor(date1);
251 double d2 = std::floor(date2);
252 int h, m, s;
253 decodeTime(date1, h, m, s);
254 long s1 = 3600L * h + 60L * m + s;
255 decodeTime(date2, h, m, s);
256 long s2 = 3600L * h + 60L * m + s;
257 long secs = static_cast<long>(std::floor((d1 - d2) * SecsPerDay + 0.5));
258 secs += (s1 - s2);
259 return secs;
260}
261
269inline int monthOfYear(DateTime date) {
270 int y, m, d;
271 decodeDate(date, y, m, d);
272 return m;
273}
274
282inline int dayOfYear(DateTime date) {
283 int y, m, d;
284 decodeDate(date, y, m, d);
285 DateTime startOfYear = encodeDate(y, 1, 1);
286 return static_cast<int>(std::floor(date - startOfYear)) + 1;
287}
288
289} // namespace datetime
290} // namespace openswmm
291
292#endif // OPENSWMM_ENGINE_DATETIME_HPP
Definition DateTime.hpp:54
void decodeDate(DateTime date, int &year, int &month, int &day)
Decode the whole-day part of a SWMM DateTime.
Definition DateTime.hpp:152
DateTime encodeTime(int hour, int minute, int second)
Convert nonnegative time components to an elapsed-day fraction.
Definition DateTime.hpp:134
DateTime addSeconds(DateTime date, double seconds)
Add an offset after rounding the input time to whole seconds.
Definition DateTime.hpp:233
double DateTime
Definition DateTime.hpp:68
int monthOfYear(DateTime date)
Extract the month from a SWMM DateTime.
Definition DateTime.hpp:269
bool isLeapYear(int year)
Test the proleptic Gregorian leap-year rule.
Definition DateTime.hpp:98
void divMod(int n, int d, int *result, int *remainder)
Divide integers with the legacy zero-divisor convention.
Definition DateTime.hpp:83
DateTime encodeDate(int year, int month, int day)
Encode a Gregorian calendar date as midnight in SWMM days.
Definition DateTime.hpp:110
long timeDiff(DateTime date1, DateTime date2)
Subtract two SWMM DateTimes using whole-second decoded times.
Definition DateTime.hpp:249
void decodeTime(DateTime time, int &h, int &m, int &s)
Decode a SWMM day fraction to the nearest whole second.
Definition DateTime.hpp:210
int dayOfYear(DateTime date)
Extract the ordinal day from a SWMM DateTime.
Definition DateTime.hpp:282
Definition ExchangeLaw.hpp:60
double * y
Definition odesolve.c:37