94
115
*----------------------------------------------------------------------
117
* TimeUtil_MakeTime --
119
* Converts a TimeUtil_Date to a time_t.
127
*----------------------------------------------------------------------
131
TimeUtil_MakeTime(const TimeUtil_Date *d) // IN
137
memset(&t, 0, sizeof t);
140
t.tm_mon = d->month - 1;
141
t.tm_year = d->year - 1900;
143
t.tm_sec = d->second;
144
t.tm_min = d->minute;
146
t.tm_isdst = -1; /* Unknown. */
153
*----------------------------------------------------------------------
155
* TimeUtil_StringToDate --
157
* Initialize the date object with value from the string argument,
158
* while the time will be left unmodified.
159
* The string 'date' needs to be in the format of 'YYYYMMDD' or
160
* 'YYYY/MM/DD' or 'YYYY-MM-DD'.
161
* Unsuccesful initialization will leave the 'd' argument unmodified.
169
*----------------------------------------------------------------------
173
TimeUtil_StringToDate(TimeUtil_Date *d, // IN/OUT
174
char const *date) // IN
177
* Reduce the string to a known and handled format: YYYYMMDD.
178
* Then, passed to internal function TimeUtilLoadDate.
180
if (strlen(date) == 8) {
182
return TimeUtilLoadDate(d, date);
183
} else if (strlen(date) == 10) {
185
char temp[16] = { 0 };
187
if (!(((date[4] != '/') || (date[7] != '/')) ||
188
((date[4] != '-') || (date[7] != '-')))) {
192
Str_Strcpy(temp, date, sizeof(temp));
199
return TimeUtilLoadDate(d, temp);
207
*----------------------------------------------------------------------
209
* TimeUtil_DeltaDays --
211
* Calculate the number of days between the two date arguments.
212
* This function ignores the time. It will be as if the time
213
* is midnight (00:00:00).
217
* - 0 (if 'left' and 'right' are of the same date (ignoring the time).
218
* - negative, if 'left' is of a later date than 'right'
219
* - positive, if 'right' is of a later date than 'left'
224
*----------------------------------------------------------------------
228
TimeUtil_DeltaDays(TimeUtil_Date const *left, // IN
229
TimeUtil_Date const *right) // IN
236
Bool inverted = FALSE;
240
ASSERT(TimeUtilIsValidDate(left->year, left->month, left->day));
241
ASSERT(TimeUtilIsValidDate(right->year, right->month, right->day));
243
TimeUtilInit(&temp1);
244
TimeUtilInit(&temp2);
247
temp1.year = left->year;
248
temp1.month = left->month;
249
temp1.day = left->day;
250
temp2.year = right->year;
251
temp2.month = right->month;
252
temp2.day = right->day;
254
if (!TimeUtil_DateLowerThan(&temp1, &temp2) &&
255
!TimeUtil_DateLowerThan(&temp2, &temp1)) {
257
} else if (TimeUtil_DateLowerThan(&temp1, &temp2)) {
259
} else if (TimeUtil_DateLowerThan(&temp2, &temp1)) {
267
TimeUtil_DaysAdd(&temp1, 1);
268
while (TimeUtil_DateLowerThan(&temp1, &temp2)) {
270
TimeUtil_DaysAdd(&temp1, 1);
282
*----------------------------------------------------------------------
284
* TimeUtil_DaysSubtract --
286
* Subtracts 'nr' days from 'd'.
288
* Simple algorithm - which can be improved as necessary:
289
* - get rough days estimation, also guarantee that the estimation is
290
* lower than the actual result.
291
* - 'add' a day-by-day to arrive at actual result.
292
* 'd' will be unchanged if the function failed.
295
* This function can be combined with DaysAdd(), where it
296
* accepts integer (positive for addition, negative for subtraction).
297
* But, that cannot be done without changing the DaysAdd function
299
* When this utility get rewritten, this can be updated.
307
*----------------------------------------------------------------------
311
TimeUtil_DaysSubtract(TimeUtil_Date *d, // IN/OUT
312
unsigned int nr) // IN
319
TimeUtil_Date estRes;
324
unsigned int dayCount = nr;
329
TimeUtilInit(&estRes);
332
* Use lower bound for the following conversion:
333
* 365 (instead of 366) days in a year
334
* 30 (instead of 31) days in a month.
336
* To account for February having fewer than 30 days, we will
337
* intentionally subtract an additional 2 days for each year
338
* and an additional 3 days.
340
dayCount = dayCount + 3 + 2 * (dayCount / 365);
342
subYear = dayCount / 365;
343
dayCount = dayCount % 365;
344
subMonth = dayCount / 30;
345
subDay = dayCount % 30;
347
estDay = d->day - subDay;
348
while (estDay <= 0) {
349
estDay = estDay + 30;
352
estMonth = d->month - subMonth;
353
while (estMonth <= 0) {
354
estMonth = estMonth + 12;
357
estYear = d->year - subYear;
363
* making sure on the valid range, without checking
364
* for leap year, etc.
366
if ((estDay > 28) && (estMonth == 2)) {
370
estRes.year = estYear;
371
estRes.month = estMonth;
375
* we also copy the time from the original argument in making
376
* sure that it does not play role in the comparison.
378
estRes.hour = d->hour;
379
estRes.minute = d->minute;
380
estRes.second = d->second;
383
* At this point, we should have an estimated result which
384
* guaranteed to be lower than the actual result. Otherwise,
385
* infinite loop will happen.
387
ASSERT(TimeUtil_DateLowerThan(&estRes, d));
390
* Perform the actual precise adjustment
391
* Done by moving up (moving forward) the estimated a day at a time
392
* until they are the correct one (i.e. estDate + arg #day = arg date)
395
TimeUtil_DaysAdd(&temp, nr);
396
while (TimeUtil_DateLowerThan(&temp, d)) {
397
TimeUtil_DaysAdd(&temp, 1);
398
TimeUtil_DaysAdd(&estRes, 1);
401
d->year = estRes.year;
402
d->month = estRes.month;
410
*----------------------------------------------------------------------
96
412
* TimeUtil_DaysAdd --
98
414
* Add 'nr' days to a date.
1063
***********************************************************************
1067
***********************************************************************
1071
*----------------------------------------------------------------------
1075
* Initialize everything to zero
1083
*----------------------------------------------------------------------
1087
TimeUtilInit(TimeUtil_Date *d)
1103
*----------------------------------------------------------------------
1105
* TimeUtilIsValidDate --
1107
* Check whether the args represent a valid date.
1115
*----------------------------------------------------------------------
1119
TimeUtilIsValidDate(unsigned int year, // IN
1120
unsigned int month, // IN
1121
unsigned int day) // IN
1123
static unsigned int monthdays[13] = DAYS_IN_MONTH;
1126
* Initialize the table
1128
if (TimeUtilIsLeapYear(year)) {
1135
(month >= 1) && (month <= 12) &&
1136
(day >= 1) && (day <= monthdays[month])) {
1145
*----------------------------------------------------------------------
1147
* TimeUtilIsLeapYear --
1149
* Check whether the argument represents a leap year.
1157
*----------------------------------------------------------------------
1161
TimeUtilIsLeapYear(unsigned int year) // IN
1163
if ((year % 4) == 0 &&
1164
((year % 100) != 0 ||
1165
(year % 400) == 0)) {
1174
*----------------------------------------------------------------------
1176
* TimeUtilLoadDate --
1178
* Initialize the date object with value from the string argument,
1179
* while the time will be left unmodified.
1180
* The string 'date' needs to be in the format of 'YYYYMMDD'.
1181
* Unsuccesful initialization will leave the 'd' argument unmodified.
1189
*----------------------------------------------------------------------
1193
TimeUtilLoadDate(TimeUtil_Date *d, // IN/OUT
1194
const char *date) // IN
1196
char temp[16] = { 0 };
1207
if (strlen(date) != 8) {
1210
for (i = 0; i < strlen(date); i++) {
1211
if (isdigit((int) date[i]) == 0) {
1221
year = strtol(temp, &end, 10);
1229
month = strtol(temp, &end, 10);
1237
day = strtol(temp, &end, 10);
1242
if (!TimeUtilIsValidDate((unsigned int) year, (unsigned int) month, (unsigned int) day)) {
1246
d->year = (unsigned int) year;
1247
d->month = (unsigned int) month;
1248
d->day = (unsigned int) day;
754
1255
*----------------------------------------------------------------------
756
1257
* TimeUtilFindIndexByUTCOffset --