52 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
53 # define GMTOFF(tm) ((tm)->tm_gmtoff)
56 # define GMTOFF(tm) (-timezone+daylight)
78 utc->years = dt->years;
80 utc->seconds = dt->seconds;
87 utc->months = dt->months;
104 if (date_time == NULL) {
145 int YY = (year - 1) % 100;
146 int C = (year - 1) - YY;
148 int jan1 = 1 + (((((C / 100) % 4) * 5) + G) % 7);
150 crm_trace(
"YY=%d, C=%d, G=%d", YY, C, G);
151 crm_trace(
"January 1 %.4d: %d", year, jan1);
175 int month_days[14] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 29 };
183 return month_days[month];
189 gboolean is_leap = FALSE;
194 if (year % 100 == 0 && year % 400 != 0) {
205 for (lpc = 1; lpc < m; lpc++) {
217 if (log_level < LOG_CRIT) {
219 prefix ? prefix :
"", prefix ?
": " :
"", date_s ? date_s :
"__invalid_date__");
222 prefix ? prefix :
"", prefix ?
": " :
"",
223 date_s ? date_s :
"__invalid_date__");
229 crm_time_get_sec(
int sec, uint * h, uint * m, uint * s)
231 uint hours, minutes, seconds;
239 hours = seconds / (60 * 60);
240 seconds -= 60 * 60 * hours;
242 minutes = seconds / (60);
243 seconds -= 60 * minutes;
245 crm_trace(
"%d == %.2d:%.2d:%.2d", sec, hours, minutes, seconds);
257 return crm_time_get_sec(dt->seconds, h, m, s);
265 return crm_time_get_sec(dt->seconds, h, m, &s);
273 long long in_seconds = 0;
275 utc = crm_get_utc_time(dt);
277 for (lpc = 1; lpc < utc->years; lpc++) {
278 int dmax = year_days(lpc);
280 in_seconds += 60 * 60 * 24 * dmax;
290 if (utc->months > 0) {
291 in_seconds += 60 * 60 * 24 * 30 * utc->months;
295 in_seconds += 60 * 60 * 24 * (utc->days - 1);
297 in_seconds += utc->seconds;
303 #define EPOCH_SECONDS 62135596800ULL
317 for (months = 1; months <= 12 && days > 0; months++) {
327 }
else if (dt->months) {
338 crm_trace(
"%.4d-%.3d -> %.4d-%.2d-%.2d", dt->years, dt->days, dt->years, months, days);
364 h = dt->days + jan1 - 1;
365 *d = 1 + ((h - 1) % 7);
368 if (dt->days <= (8 - jan1) && jan1 > 4) {
370 year_num = dt->years - 1;
374 year_num = dt->years;
378 if (year_num == dt->years) {
379 int dmax = year_days(year_num);
380 int correction = 4 - *d;
382 if ((dmax - dt->days) < correction) {
383 crm_trace(
"year++, jan1=%d, i=%d vs. %d", jan1, dmax - dt->days, correction);
384 year_num = dt->years + 1;
390 if (year_num == dt->years) {
391 int j = dt->days + (7 - *d) + (jan1 - 1);
400 crm_trace(
"Converted %.4d-%.3d to %.4d-W%.2d-%d", dt->years, dt->days, *y, *w, *d);
409 char *offset_s = NULL;
410 char *result_s = NULL;
414 if (date_time == NULL) {
419 utc = crm_get_utc_time(date_time);
427 uint h = 0, m = 0, s = 0;
428 int offset = 0, max = 128;
430 date_s = calloc(1, max+1);
431 crm_time_get_sec(dt->seconds, &h, &m, &s);
433 if (date_s == NULL) {
438 offset += snprintf(date_s+offset, max-offset,
"%4d year%s ", dt->years, dt->years>1?
"s":
"");
441 offset += snprintf(date_s+offset, max-offset,
"%2d month%s ", dt->months, dt->months>1?
"s":
"");
444 offset += snprintf(date_s+offset, max-offset,
"%2d day%s ", dt->days, dt->days>1?
"s":
"");
447 offset += snprintf(date_s+offset, max-offset,
"%d seconds ( ", dt->seconds);
449 offset += snprintf(date_s+offset, max-offset,
"%d hour%s ", h, h>1?
"s":
"");
452 offset += snprintf(date_s+offset, max-offset,
"%d minute%s ", m, m>1?
"s":
"");
455 offset += snprintf(date_s+offset, max-offset,
"%d second%s ", s, s>1?
"s":
"");
457 offset += snprintf(date_s+offset, max-offset,
")");
463 date_s = calloc(1, 32);
464 if (date_s == NULL) {
470 snprintf(date_s, 31,
"%lld", s);
476 snprintf(date_s, 31,
"%lld", s);
484 snprintf(date_s, 31,
"%d-W%.2d-%d", y, w, d);
492 snprintf(date_s, 31,
"%d-%.3d", y, d);
500 snprintf(date_s, 31,
"%.4d-%.2d-%.2d", y, m, d);
508 time_s = calloc(1, 32);
509 if (time_s == NULL) {
514 snprintf(time_s, 31,
"%.2d:%.2d:%.2d", h, m, s);
517 if (dt->offset != 0) {
518 crm_time_get_sec(dt->offset, &h, &m, &s);
521 offset_s = calloc(1, 32);
522 if ((flags & crm_time_log_with_timezone) == 0 || dt->offset == 0) {
523 crm_trace(
"flags %6x %6x", flags, crm_time_log_with_timezone);
524 snprintf(offset_s, 31,
"Z");
527 snprintf(offset_s, 31,
" %c%.2d:%.2d", dt->offset < 0 ?
'-' :
'+', h, m);
532 result_s = calloc(1, 100);
534 snprintf(result_s, 100,
"%s%s%s%s",
535 date_s ? date_s :
"", (date_s != NULL && time_s != NULL) ?
" " :
"",
536 time_s ? time_s :
"", offset_s ? offset_s :
"");
548 crm_time_parse_sec(
const char *time_str)
555 rc = sscanf(time_str,
"%d:%d:%d", &hour, &minute, &second);
557 rc = sscanf(time_str,
"%2d%2d%2d", &hour, &minute, &second);
560 if (rc > 0 && rc < 4) {
561 crm_trace(
"Got valid time: %.2d:%.2d:%.2d", hour, minute, second);
563 crm_err(
"Invalid hour: %d", hour);
564 }
else if (minute >= 60) {
565 crm_err(
"Invalid minute: %d", minute);
566 }
else if (second >= 60) {
567 crm_err(
"Invalid second: %d", second);
569 second += (minute * 60);
570 second += (hour * 60 * 60);
573 crm_err(
"Bad time: %s (%d)", time_str, rc);
579 crm_time_parse_offset(
const char *offset_str)
584 if (offset_str == NULL) {
585 #if defined(HAVE_STRUCT_TM_TM_GMTOFF)
586 time_t now = time(NULL);
587 struct tm *now_tm = localtime(&now);
589 int h_offset =
GMTOFF(now_tm) / (3600);
590 int m_offset = (
GMTOFF(now_tm) - (3600 * h_offset)) / (60);
592 if (h_offset < 0 && m_offset < 0) {
593 m_offset = 0 - m_offset;
595 offset += (60 * 60 * h_offset);
596 offset += (60 * m_offset);
598 }
else if (offset_str[0] ==
'Z') {
600 }
else if (offset_str[0] ==
'+' || offset_str[0] ==
'-' || isdigit((
int)offset_str[0])) {
601 gboolean negate = FALSE;
603 if (offset_str[0] ==
'-') {
607 offset = crm_time_parse_sec(offset_str);
616 crm_time_parse(
const char *time_str,
crm_time_t * a_time)
619 char *offset_s = NULL;
623 if (a_time == NULL) {
628 dt->seconds = crm_time_parse_sec(time_str);
630 offset_s = strstr(time_str,
"Z");
631 if (offset_s == NULL) {
632 offset_s = strstr(time_str,
" ");
637 while (isspace(offset_s[0])) {
641 dt->offset = crm_time_parse_offset(offset_s);
642 crm_time_get_sec(dt->offset, &h, &m, &s);
643 crm_trace(
"Got tz: %c%2.d:%.2d", dt->offset < 0 ?
'-' :
'+', h, m);
659 CRM_CHECK(date_str != NULL,
return NULL);
660 CRM_CHECK(strlen(date_str) > 0,
return NULL);
662 if (date_str[0] ==
'T' || date_str[2] ==
':') {
665 dt = crm_time_parse(date_str, dt);
680 rc = sscanf(date_str,
"%d-%d-%d", &year, &month, &day);
683 rc = sscanf(date_str,
"%4d%2d%2d", &year, &month, &day);
687 crm_err(
"Invalid month: %d", month);
688 }
else if (day > 31) {
689 crm_err(
"Invalid day: %d", day);
692 dt->days = get_ordinal_days(year, month, day);
693 crm_trace(
"Got gergorian date: %.4d-%.3d", year, dt->days);
699 rc = sscanf(date_str,
"%d-%d", &year, &day);
702 if (day > year_days(year)) {
703 crm_err(
"Invalid day: %d (max=%d)", day, year_days(year));
712 rc = sscanf(date_str,
"%d-W%d-%d", &year, &week, &day);
717 }
else if (day < 1 || day > 7) {
718 crm_err(
"Invalid day: %d", day);
750 crm_err(
"Couldn't parse %s", date_str);
753 time_s = strstr(date_str,
" ");
754 if (time_s == NULL) {
755 time_s = strstr(date_str,
"T");
760 crm_time_parse(time_s, dt);
771 parse_int(
const char *str,
int field_width,
int uppper_bound,
int *result)
775 int intermediate = 0;
776 gboolean fraction = FALSE;
777 gboolean negate = FALSE;
784 if (strlen(str) <= 0) {
788 if (str[offset] ==
'T') {
792 if (str[offset] ==
'.' || str[offset] ==
',') {
796 }
else if (str[offset] ==
'-') {
799 }
else if (str[offset] ==
'+' || str[offset] ==
':') {
803 for (; (fraction || lpc < field_width) && isdigit((
int)str[offset]); lpc++) {
805 intermediate = (str[offset] -
'0') / (10 ^ lpc);
808 intermediate = str[offset] -
'0';
810 *result += intermediate;
814 *result = (int)(*result * uppper_bound);
816 }
else if (uppper_bound > 0 && *result > uppper_bound) {
817 *result = uppper_bound;
820 *result = 0 - *result;
823 crm_trace(
"Found int: %d. Stopped at str[%d]='%c'", *result, lpc, str[lpc]);
832 gboolean is_time = FALSE;
835 CRM_CHECK(interval_str != NULL,
goto bail);
836 CRM_CHECK(strlen(interval_str) > 0,
goto bail);
837 CRM_CHECK(interval_str[0] ==
'P',
goto bail);
842 while (isspace((
int)interval_str[0]) == FALSE) {
846 if (interval_str[0] ==
'T') {
851 rc = parse_int(interval_str, 10, 0, &an_int);
857 ch = interval_str[0];
860 crm_trace(
"Testing %c=%d, rc=%d", ch, an_int, rc);
867 diff->years = an_int;
872 diff->seconds += an_int * 60;
874 diff->months = an_int;
878 diff->days += an_int * 7;
881 diff->days += an_int;
884 diff->seconds += an_int * 60 * 60;
887 diff->seconds += an_int;
904 gboolean invalid = FALSE;
905 const char *original = period_str;
908 CRM_CHECK(period_str != NULL,
return NULL);
909 CRM_CHECK(strlen(period_str) > 0,
return NULL);
914 if (period_str[0] ==
'P') {
920 period_str = strstr(original,
"/");
922 CRM_CHECK(period_str[0] ==
'/', invalid = TRUE;
926 if (period_str[0] ==
'P') {
932 }
else if (period->
diff != NULL) {
938 CRM_CHECK(period_str != NULL,
goto bail);
942 if (period->
start == NULL && period->
end == NULL) {
943 crm_err(
"Invalid time period: %s", original);
946 }
else if (period->
start == NULL && period->
diff == NULL) {
947 crm_err(
"Invalid time period: %s", original);
950 }
else if (period->
end == NULL && period->
diff == NULL) {
951 crm_err(
"Invalid time period: %s", original);
963 if (period->
end == NULL && period->
diff == NULL) {
966 if (period->
start == NULL) {
969 }
else if (period->
end == NULL) {
982 crm_trace(
"target=%p, source=%p", target, source);
984 CRM_CHECK(target != NULL && source != NULL,
return);
986 target->years = source->years;
987 target->days = source->days;
988 target->months = source->months;
989 target->seconds = source->seconds;
990 target->offset = source->offset;
999 ha_set_tm_time(
crm_time_t * target,
struct tm *source)
1008 target->seconds = 0;
1010 target->duration = FALSE;
1012 if (source->tm_year > 0) {
1014 target->years = 1900 + source->tm_year;
1017 if (source->tm_yday >= 0) {
1019 target->days = 1 + source->tm_yday;
1022 if (source->tm_hour >= 0) {
1023 target->seconds += 60 * 60 * source->tm_hour;
1025 if (source->tm_min >= 0) {
1026 target->seconds += 60 * source->tm_min;
1028 if (source->tm_sec >= 0) {
1029 target->seconds += source->tm_sec;
1033 h_offset =
GMTOFF(source) / (3600);
1034 m_offset = (
GMTOFF(source) - (3600 * h_offset)) / (60);
1035 crm_trace(
"Offset (s): %ld, offset (hh:mm): %.2d:%.2d",
GMTOFF(source), h_offset, m_offset);
1037 target->offset += 60 * 60 * h_offset;
1038 target->offset += 60 * m_offset;
1044 ha_set_tm_time(target, localtime(source));
1053 CRM_CHECK(dt != NULL && value != NULL,
return NULL);
1058 utc = crm_get_utc_time(value);
1060 answer->years += utc->years;
1075 CRM_CHECK(dt != NULL && value != NULL,
return NULL);
1077 utc = crm_get_utc_time(value);
1078 answer = crm_get_utc_time(dt);
1079 answer->duration = TRUE;
1081 answer->years -= utc->years;
1082 if(utc->months != 0) {
1098 CRM_CHECK(dt != NULL && value != NULL,
return NULL);
1102 utc = crm_get_utc_time(value);
1104 answer->years -= utc->years;
1105 if(utc->months != 0) {
1121 ydays = year_days(dt->years);
1125 CRM_CHECK(dt->days <= ydays,
return FALSE);
1127 CRM_CHECK(dt->seconds >= 0,
return FALSE);
1128 CRM_CHECK(dt->seconds < 24 * 60 * 60,
return FALSE);
1133 #define do_cmp_field(l, r, field) \
1135 if(l->field > r->field) { \
1136 crm_trace("%s: %d > %d", \
1137 #field, l->field, r->field); \
1139 } else if(l->field < r->field) { \
1140 crm_trace("%s: %d < %d", \
1141 #field, l->field, r->field); \
1153 if (a == NULL && b == NULL) {
1155 }
else if (a == NULL) {
1157 }
else if (b == NULL) {
1161 t1 = crm_get_utc_time(a);
1162 t2 = crm_get_utc_time(b);
1177 int seconds = 24 * 60 * 60;
1179 crm_trace(
"Adding %d seconds to %d (max=%d)", extra, a_time->seconds, seconds);
1181 a_time->seconds += extra;
1182 while (a_time->seconds >= seconds) {
1183 a_time->seconds -= seconds;
1187 while (a_time->seconds < 0) {
1188 a_time->seconds += seconds;
1197 int lower_bound = 1;
1200 crm_trace(
"Adding %d days to %.4d-%.3d", extra, a_time->years, a_time->days);
1202 a_time->days += extra;
1203 while (a_time->days > ydays) {
1205 a_time->days -= ydays;
1209 if(a_time->duration) {
1213 while (a_time->days < lower_bound) {
1226 crm_trace(
"Adding %d months to %.4d-%.2d-%.2d", extra, y, m, d);
1229 for (lpc = extra; lpc > 0; lpc--) {
1237 for (lpc = -extra; lpc > 0; lpc--) {
1252 crm_trace(
"Calculated %.4d-%.2d-%.2d", y, m, d);
1255 a_time->days = get_ordinal_days(y, m, d);
1258 crm_trace(
"Got %.4d-%.2d-%.2d", y, m, d);
1282 a_time->years += extra;
#define CRM_CHECK(expr, failure_action)
crm_time_t * parse_date(const char *date_str)
bool crm_time_leapyear(int year)
crm_time_t * crm_time_parse_duration(const char *interval_str)
crm_time_t * crm_time_subtract(crm_time_t *dt, crm_time_t *value)
void crm_time_set_timet(crm_time_t *target, time_t *source)
crm_time_t * crm_time_add(crm_time_t *dt, crm_time_t *value)
#define crm_time_log_timeofday
crm_time_t * crm_time_new(const char *date_time)
int crm_time_compare(crm_time_t *a, crm_time_t *b)
struct crm_time_s crm_time_t
gboolean check_for_ordinal(const char *str)
void crm_time_add_minutes(crm_time_t *a_time, int extra)
void crm_time_add_weeks(crm_time_t *a_time, int extra)
void crm_time_free(crm_time_t *dt)
#define do_cmp_field(l, r, field)
#define do_crm_log_alias(level, file, function, line, fmt, args...)
Log a message as if it came from a different code location.
#define crm_time_log_duration
void crm_time_log_alias(int log_level, const char *file, const char *function, int line, const char *prefix, crm_time_t *date_time, int flags)
crm_time_period_t * crm_time_parse_period(const char *period_str)
int crm_time_get_gregorian(crm_time_t *dt, uint *y, uint *m, uint *d)
void crm_time_add_seconds(crm_time_t *a_time, int extra)
bool crm_time_check(crm_time_t *dt)
long long crm_time_get_seconds(crm_time_t *dt)
void crm_time_add_days(crm_time_t *a_time, int extra)
#define crm_trace(fmt, args...)
int crm_time_get_isoweek(crm_time_t *dt, uint *y, uint *w, uint *d)
void crm_time_add_hours(crm_time_t *a_time, int extra)
#define crm_time_log(level, prefix, dt, flags)
int crm_time_days_in_month(int month, int year)
#define crm_time_log_with_timezone
int crm_time_get_timezone(crm_time_t *dt, uint *h, uint *m)
void crm_time_add_years(crm_time_t *a_time, int extra)
long long crm_time_get_seconds_since_epoch(crm_time_t *dt)
#define crm_err(fmt, args...)
void crm_time_add_months(crm_time_t *a_time, int extra)
int crm_time_weeks_in_year(int year)
int crm_time_january1_weekday(int year)
crm_time_t * crm_time_calculate_duration(crm_time_t *dt, crm_time_t *value)
int crm_time_get_ordinal(crm_time_t *dt, uint *y, uint *d)
char * crm_time_as_string(crm_time_t *date_time, int flags)
#define safe_str_eq(a, b)
#define crm_time_log_date
int crm_time_get_timeofday(crm_time_t *dt, uint *h, uint *m, uint *s)
void crm_time_set(crm_time_t *target, crm_time_t *source)