2
* Copyright (C) 2005 Andrew Beekhof <andrew@beekhof.net>
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
* http://en.wikipedia.org/wiki/ISO_8601 as at 2005-08-01
24
#include <crm_internal.h>
28
#include <crm/common/iso8601.h>
30
#define do_add_field(atime, field, extra, limit, overflow) \
32
crm_trace("Adding %d to %d (limit=%d)", \
33
extra, atime->field, limit); \
34
atime->field += extra; \
36
while(limit < atime->field) { \
37
crm_trace("Overflowing: %d", atime->field); \
38
atime->field -= limit; \
42
atime->field = atime->field; \
43
crm_trace("Result: %d", atime->field); \
46
#define do_add_days_field(atime, field, extra, overflow) \
48
int __limit = days_per_month(atime->months, atime->years); \
49
crm_trace("Adding %d to %d (limit=%d)", \
50
extra, atime->field, __limit); \
51
atime->field += extra; \
53
while(__limit < atime->field) { \
54
crm_trace("Overflowing: %d", atime->field); \
56
__limit = days_per_month(atime->months, atime->years); \
57
atime->field -= __limit; \
60
atime->field = atime->field; \
61
crm_trace("Result: %d", atime->field); \
64
#define do_add_time_field(atime, field, extra, limit, overflow) \
66
crm_trace("Adding %d to %d (limit=%d)", \
67
extra, atime->field, limit); \
68
atime->field += extra; \
70
while(limit <= atime->field) { \
71
crm_trace("Overflowing: %d", atime->field); \
72
atime->field -= limit; \
76
atime->field = atime->field; \
77
crm_trace("Result: %d", atime->field); \
80
#define do_sub_field(atime, field, extra, limit, overflow) \
82
crm_trace("Subtracting %d from %d (limit=%d)", \
83
extra, atime->field, limit); \
84
atime->field -= extra; \
85
while(atime->field < 1) { \
86
crm_trace("Underflowing: %d", atime->field); \
87
atime->field += limit; \
90
crm_trace("Result: %d", atime->field); \
93
#define do_sub_days_field(atime, field, extra, overflow) \
95
int __limit = days_per_month(atime->months, atime->years); \
96
crm_trace("Subtracting %d from %d (__limit=%d)", \
97
extra, atime->field, __limit); \
98
atime->field -= extra; \
99
while(atime->field < 1) { \
100
crm_trace("Underflowing: %d", atime->field); \
101
overflow(atime, 1); \
102
__limit = days_per_month(atime->months, atime->years); \
103
atime->field += __limit; \
105
crm_trace("Result: %d", atime->field); \
107
#define do_sub_time_field(atime, field, extra, limit, overflow) \
109
crm_trace("Subtracting %d from %d (limit=%d)", \
110
extra, atime->field, limit); \
111
atime->field -= extra; \
112
while(atime->field < 0) { \
113
crm_trace("Underflowing: %d", atime->field); \
114
atime->field += limit; \
115
overflow(atime, 1); \
117
crm_trace("Result: %d", atime->field); \
121
add_seconds(ha_time_t * a_time, int extra)
124
sub_seconds(a_time, -extra);
126
do_add_time_field(a_time, seconds, extra, 60, add_minutes);
131
add_minutes(ha_time_t * a_time, int extra)
134
sub_minutes(a_time, -extra);
136
do_add_time_field(a_time, minutes, extra, 60, add_hours);
141
add_hours(ha_time_t * a_time, int extra)
144
sub_hours(a_time, -extra);
146
do_add_time_field(a_time, hours, extra, 24, add_days);
151
add_days(ha_time_t * a_time, int extra)
153
if (a_time->has->days == FALSE) {
154
crm_trace("has->days == FALSE");
158
sub_days(a_time, -extra);
160
do_add_days_field(a_time, days, extra, add_months);
163
convert_from_gregorian(a_time);
167
add_weekdays(ha_time_t * a_time, int extra)
169
if (a_time->has->weekdays == FALSE) {
170
crm_trace("has->weekdays == FALSE");
174
sub_weekdays(a_time, -extra);
176
do_add_field(a_time, weekdays, extra, 7, add_weeks);
179
convert_from_weekdays(a_time);
183
add_yeardays(ha_time_t * a_time, int extra)
185
if (a_time->has->yeardays == FALSE) {
186
crm_trace("has->yeardays == FALSE");
190
sub_yeardays(a_time, -extra);
192
/* coverity[result_independent_of_operands] Not interesting */
193
do_add_field(a_time, yeardays, extra,
194
(is_leap_year(a_time->years) ? 366 : 365), add_ordinalyears);
197
convert_from_ordinal(a_time);
201
add_weeks(ha_time_t * a_time, int extra)
203
if (a_time->has->weeks == FALSE) {
204
crm_trace("has->weeks == FALSE");
208
sub_weeks(a_time, -extra);
210
do_add_field(a_time, weeks, extra, weeks_in_year(a_time->years), add_weekyears);
213
convert_from_weekdays(a_time);
217
add_months(ha_time_t * a_time, int extra)
221
if (a_time->has->months == FALSE) {
222
crm_trace("has->months == FALSE");
226
sub_months(a_time, -extra);
228
do_add_field(a_time, months, extra, 12, add_years);
231
max = days_per_month(a_time->months, a_time->years);
232
if (a_time->days > max) {
235
convert_from_gregorian(a_time);
239
add_years(ha_time_t * a_time, int extra)
241
if (a_time->has->years == FALSE) {
242
crm_trace("has->years == FALSE");
245
a_time->years += extra;
246
convert_from_gregorian(a_time);
250
add_ordinalyears(ha_time_t * a_time, int extra)
252
if (a_time->has->years == FALSE) {
253
crm_trace("has->years == FALSE");
256
a_time->years += extra;
257
convert_from_ordinal(a_time);
261
add_weekyears(ha_time_t * a_time, int extra)
263
if (a_time->has->weekyears == FALSE) {
264
crm_trace("has->weekyears == FALSE");
267
a_time->weekyears += extra;
268
convert_from_weekdays(a_time);
272
sub_seconds(ha_time_t * a_time, int extra)
275
add_seconds(a_time, -extra);
277
do_sub_time_field(a_time, seconds, extra, 60, sub_minutes);
282
sub_minutes(ha_time_t * a_time, int extra)
285
add_minutes(a_time, -extra);
287
do_sub_time_field(a_time, minutes, extra, 60, sub_hours);
292
sub_hours(ha_time_t * a_time, int extra)
295
add_hours(a_time, -extra);
297
do_sub_time_field(a_time, hours, extra, 24, sub_days);
302
sub_days(ha_time_t * a_time, int extra)
304
if (a_time->has->days == FALSE) {
305
crm_trace("has->days == FALSE");
309
crm_trace("Subtracting %d days from %.4d-%.2d-%.2d",
310
extra, a_time->years, a_time->months, a_time->days);
313
add_days(a_time, -extra);
315
do_sub_days_field(a_time, days, extra, sub_months);
318
convert_from_gregorian(a_time);
322
sub_weekdays(ha_time_t * a_time, int extra)
324
if (a_time->has->weekdays == FALSE) {
325
crm_trace("has->weekdays == FALSE");
329
crm_trace("Subtracting %d days from %.4d-%.2d-%.2d",
330
extra, a_time->years, a_time->months, a_time->days);
333
add_weekdays(a_time, -extra);
335
do_sub_field(a_time, weekdays, extra, 7, sub_weeks);
338
convert_from_weekdays(a_time);
342
sub_yeardays(ha_time_t * a_time, int extra)
344
if (a_time->has->yeardays == FALSE) {
345
crm_trace("has->yeardays == FALSE");
349
crm_trace("Subtracting %d days from %.4d-%.3d", extra, a_time->years, a_time->yeardays);
352
add_yeardays(a_time, -extra);
354
do_sub_field(a_time, yeardays, extra,
355
is_leap_year(a_time->years) ? 366 : 365, sub_ordinalyears);
358
convert_from_ordinal(a_time);
362
sub_weeks(ha_time_t * a_time, int extra)
364
if (a_time->has->weeks == FALSE) {
365
crm_trace("has->weeks == FALSE");
369
add_weeks(a_time, -extra);
371
do_sub_field(a_time, weeks, extra, weeks_in_year(a_time->years), sub_weekyears);
374
convert_from_weekdays(a_time);
378
sub_months(ha_time_t * a_time, int extra)
380
if (a_time->has->months == FALSE) {
381
crm_trace("has->months == FALSE");
385
add_months(a_time, -extra);
387
do_sub_field(a_time, months, extra, 12, sub_years);
389
convert_from_gregorian(a_time);
393
sub_years(ha_time_t * a_time, int extra)
395
if (a_time->has->years == FALSE) {
396
crm_trace("has->years == FALSE");
399
a_time->years -= extra;
400
convert_from_gregorian(a_time);
404
sub_weekyears(ha_time_t * a_time, int extra)
406
if (a_time->has->weekyears == FALSE) {
407
crm_trace("has->weekyears == FALSE");
410
a_time->weekyears -= extra;
412
convert_from_weekdays(a_time);
416
sub_ordinalyears(ha_time_t * a_time, int extra)
418
if (a_time->has->years == FALSE) {
419
crm_trace("has->years == FALSE");
422
a_time->years -= extra;
424
convert_from_ordinal(a_time);