39 #if defined(HAVE_STRUCT_TM_TM_GMTOFF) 40 # define GMTOFF(tm) ((tm)->tm_gmtoff) 43 # define GMTOFF(tm) (-timezone+daylight) 46 #define HOUR_SECONDS (60 * 60) 47 #define DAY_SECONDS (HOUR_SECONDS * 24) 59 static crm_time_t *parse_date(
const char *date_str);
72 utc->years = dt->years;
74 utc->seconds = dt->seconds;
81 utc->months = dt->months;
98 if (date_time == NULL) {
103 dt = parse_date(date_time);
135 return (t != NULL) && (t->years || t->months || t->days || t->seconds
136 || t->offset || t->duration);
170 int YY = (year - 1) % 100;
171 int C = (year - 1) - YY;
173 int jan1 = 1 + (((((C / 100) % 4) * 5) + G) % 7);
175 crm_trace(
"YY=%d, C=%d, G=%d", YY, C, G);
176 crm_trace(
"January 1 %.4d: %d", year, jan1);
201 static int month_days[13] = {
202 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 29
216 if ((month < 1) || (month > 12)) {
222 return month_days[month - 1];
228 gboolean is_leap = FALSE;
233 if (year % 100 == 0 && year % 400 != 0) {
240 get_ordinal_days(uint32_t y, uint32_t m, uint32_t d)
244 for (lpc = 1; lpc < m; lpc++) {
258 (prefix? prefix :
""), (prefix?
": " :
""), date_s);
261 (prefix? prefix :
""), (prefix?
": " :
""), date_s);
267 crm_time_get_sec(
int sec, uint * h, uint * m, uint * s)
269 uint hours, minutes, seconds;
280 minutes = seconds / 60;
281 seconds -= 60 * minutes;
283 crm_trace(
"%d == %.2d:%.2d:%.2d", sec, hours, minutes, seconds);
293 crm_time_get_sec(dt->seconds, h, m, s);
302 crm_time_get_sec(dt->seconds, h, m, &s);
311 long long in_seconds = 0;
317 utc = crm_get_utc_time(dt);
322 for (lpc = 1; lpc < utc->years; lpc++) {
323 long long dmax = year_days(lpc);
335 if (utc->months > 0) {
336 in_seconds +=
DAY_SECONDS * 30 * (
long long) (utc->months);
340 in_seconds +=
DAY_SECONDS * (
long long) (utc->days - 1);
342 in_seconds += utc->seconds;
348 #define EPOCH_SECONDS 62135596800ULL 362 for (months = 1; months <= 12 && days > 0; months++) {
372 }
else if (dt->months) {
383 crm_trace(
"%.4d-%.3d -> %.4d-%.2d-%.2d", dt->years, dt->days, dt->years, months, days);
409 h = dt->days + jan1 - 1;
410 *d = 1 + ((h - 1) % 7);
413 if (dt->days <= (8 - jan1) && jan1 > 4) {
415 year_num = dt->years - 1;
419 year_num = dt->years;
423 if (year_num == dt->years) {
424 int dmax = year_days(year_num);
425 int correction = 4 - *d;
427 if ((dmax - dt->days) < correction) {
428 crm_trace(
"year++, jan1=%d, i=%d vs. %d", jan1, dmax - dt->days, correction);
429 year_num = dt->years + 1;
435 if (year_num == dt->years) {
436 int j = dt->days + (7 - *d) + (jan1 - 1);
445 crm_trace(
"Converted %.4d-%.3d to %.4d-W%.2d-%d", dt->years, dt->days, *y, *w, *d);
452 crm_duration_as_string(
crm_time_t *dt,
char *result)
457 offset += snprintf(result + offset,
DATE_MAX - offset,
"%4d year%s ",
461 offset += snprintf(result + offset,
DATE_MAX - offset,
"%2d month%s ",
465 offset += snprintf(result + offset,
DATE_MAX - offset,
"%2d day%s ",
469 if (((offset == 0) || (dt->seconds != 0))
470 && (dt->seconds > -60) && (dt->seconds < 60)) {
471 offset += snprintf(result + offset,
DATE_MAX - offset,
"%d second%s",
473 }
else if (dt->seconds) {
474 uint h = 0, m = 0, s = 0;
476 offset += snprintf(result + offset,
DATE_MAX - offset,
"%d seconds (",
478 crm_time_get_sec(dt->seconds, &h, &m, &s);
480 offset += snprintf(result + offset,
DATE_MAX - offset,
"%u hour%s%s",
484 offset += snprintf(result + offset,
DATE_MAX - offset,
"%u minute%s%s",
488 offset += snprintf(result + offset,
DATE_MAX - offset,
"%u second%s",
491 offset += snprintf(result + offset,
DATE_MAX - offset,
")");
501 char *result_copy = NULL;
505 if (date_time && date_time->offset
508 utc = crm_get_utc_time(date_time);
515 strcpy(result,
"<undefined time>");
522 crm_duration_as_string(date_time, result);
544 offset += snprintf(result + offset,
DATE_MAX - offset,
545 "%u-W%.2u-%u", y, w, d);
552 offset += snprintf(result + offset,
DATE_MAX - offset,
560 offset += snprintf(result + offset,
DATE_MAX - offset,
561 "%.4u-%.2u-%.2u", y, m, d);
567 uint h = 0, m = 0, s = 0;
570 offset += snprintf(result + offset,
DATE_MAX - offset,
" ");
574 offset += snprintf(result + offset,
DATE_MAX - offset,
575 "%.2u:%.2u:%.2u", h, m, s);
579 crm_time_get_sec(dt->offset, &h, &m, &s);
580 offset += snprintf(result + offset,
DATE_MAX - offset,
582 ((dt->offset < 0)?
'-' :
'+'), h, m);
584 offset += snprintf(result + offset,
DATE_MAX - offset,
"Z");
591 result_copy = strdup(result);
608 crm_time_parse_sec(
const char *time_str,
int *result)
618 rc = sscanf(time_str,
"%d:%d:%d", &hour, &minute, &second);
620 rc = sscanf(time_str,
"%2d%2d%2d", &hour, &minute, &second);
623 crm_err(
"%s is not a valid ISO 8601 time specification", time_str);
628 crm_trace(
"Got valid time: %.2d:%.2d:%.2d", hour, minute, second);
630 if ((hour == 24) && (minute == 0) && (second == 0)) {
632 }
else if (hour >= 24) {
633 crm_err(
"%s is not a valid ISO 8601 time specification " 634 "because %d is not a valid hour", time_str, hour);
639 crm_err(
"%s is not a valid ISO 8601 time specification " 640 "because %d is not a valid minute", time_str, minute);
645 crm_err(
"%s is not a valid ISO 8601 time specification " 646 "because %d is not a valid second", time_str, second);
651 *result = (hour *
HOUR_SECONDS) + (minute * 60) + second;
656 crm_time_parse_offset(
const char *offset_str,
int *offset)
660 if (offset_str == NULL) {
662 #if defined(HAVE_STRUCT_TM_TM_GMTOFF) 663 time_t now = time(NULL);
664 struct tm *now_tm = localtime(&now);
669 if (h_offset < 0 && m_offset < 0) {
670 m_offset = 0 - m_offset;
676 if (offset_str[0] ==
'Z') {
682 if ((offset_str[0] ==
'+') || (offset_str[0] ==
'-')
683 || isdigit((
int)offset_str[0])) {
685 gboolean negate = FALSE;
687 if (offset_str[0] ==
'+') {
689 }
else if (offset_str[0] ==
'-') {
693 if (crm_time_parse_sec(offset_str, offset) == FALSE) {
697 *offset = 0 - *offset;
714 crm_time_parse(
const char *time_str,
crm_time_t *a_time)
717 char *offset_s = NULL;
722 if (crm_time_parse_sec(time_str, &(a_time->seconds)) == FALSE) {
725 offset_s = strstr(time_str,
"Z");
726 if (offset_s == NULL) {
727 offset_s = strstr(time_str,
" ");
729 while (isspace(offset_s[0])) {
736 if (crm_time_parse_offset(offset_s, &(a_time->offset)) == FALSE) {
739 crm_time_get_sec(a_time->offset, &h, &m, &s);
740 crm_trace(
"Got tz: %c%2.d:%.2d", ((a_time->offset < 0)?
'-' :
'+'), h, m);
759 parse_date(
const char *date_str)
761 const char *time_s = NULL;
770 if (pcmk__str_empty(date_str)) {
771 crm_err(
"No ISO 8601 date/time specification given");
775 if ((date_str[0] ==
'T') || (date_str[2] ==
':')) {
778 if (date_str[0] ==
'T') {
779 time_s = date_str + 1;
788 if (!strncasecmp(
"epoch", date_str, 5)
789 && ((date_str[5] ==
'\0') || (date_str[5] ==
'/') || isspace(date_str[5]))) {
797 rc = sscanf(date_str,
"%d-%d-%d", &year, &month, &day);
800 rc = sscanf(date_str,
"%4d%2d%2d", &year, &month, &day);
804 crm_err(
"'%s' is not a valid ISO 8601 date/time specification " 805 "because '%d' is not a valid month", date_str, month);
808 crm_err(
"'%s' is not a valid ISO 8601 date/time specification " 809 "because '%d' is not a valid day of the month",
814 dt->days = get_ordinal_days(year, month, day);
815 crm_trace(
"Parsed Gregorian date '%.4d-%.3d' from date string '%s'",
816 year, dt->days, date_str);
822 rc = sscanf(date_str,
"%d-%d", &year, &day);
824 if (day > year_days(year)) {
825 crm_err(
"'%s' is not a valid ISO 8601 date/time specification " 826 "because '%d' is not a valid day of the year (max %d)",
827 date_str, day, year_days(year));
830 crm_trace(
"Parsed ordinal year %d and days %d from date string '%s'",
831 year, day, date_str);
838 rc = sscanf(date_str,
"%d-W%d-%d", &year, &week, &day);
841 crm_err(
"'%s' is not a valid ISO 8601 date/time specification " 842 "because '%d' is not a valid week of the year (max %d)",
845 }
else if (day < 1 || day > 7) {
846 crm_err(
"'%s' is not a valid ISO 8601 date/time specification " 847 "because '%d' is not a valid day of the week",
863 crm_trace(
"Got year %d (Jan 1 = %d), week %d, and day %d from date string '%s'",
864 year, jan1, week, day, date_str);
880 crm_err(
"'%s' is not a valid ISO 8601 date/time specification", date_str);
885 if (time_s == NULL) {
886 time_s = date_str + strspn(date_str,
"0123456789-W");
887 if ((time_s[0] ==
' ') || (time_s[0] ==
'T')) {
893 if ((time_s != NULL) && (crm_time_parse(time_s, dt) == FALSE)) {
899 crm_err(
"'%s' is not a valid ISO 8601 date/time specification",
916 parse_int(
const char *str,
int field_width,
int upper_bound,
int *result)
920 int intermediate = 0;
921 gboolean fraction = FALSE;
922 gboolean negate = FALSE;
929 if (str[offset] ==
'T') {
933 if (str[offset] ==
'.' || str[offset] ==
',') {
937 }
else if (str[offset] ==
'-') {
940 }
else if (str[offset] ==
'+' || str[offset] ==
':') {
944 for (; (fraction || lpc < field_width) && isdigit((
int)str[offset]); lpc++) {
946 intermediate = (str[offset] -
'0') / (10 ^ lpc);
949 intermediate = str[offset] -
'0';
951 *result += intermediate;
955 *result = (int)(*result * upper_bound);
957 }
else if (upper_bound > 0 && *result > upper_bound) {
958 *result = upper_bound;
961 *result = 0 - *result;
964 crm_trace(
"Found int: %d. Stopped at str[%d]='%c'", *result, lpc, str[lpc]);
984 gboolean is_time = FALSE;
987 if (pcmk__str_empty(period_s)) {
988 crm_err(
"No ISO 8601 time duration given");
991 if (period_s[0] !=
'P') {
992 crm_err(
"'%s' is not a valid ISO 8601 time duration " 993 "because it does not start with a 'P'", period_s);
996 if ((period_s[1] ==
'\0') || isspace(period_s[1])) {
997 crm_err(
"'%s' is not a valid ISO 8601 time duration " 998 "because nothing follows 'P'", period_s);
1003 diff->duration = TRUE;
1005 for (
const char *current = period_s + 1;
1006 current[0] && (current[0] !=
'/') && !isspace(current[0]);
1011 if (current[0] ==
'T') {
1021 rc = parse_int(current, 10, 0, &an_int);
1023 crm_err(
"'%s' is not a valid ISO 8601 time duration " 1024 "because no integer at '%s'", period_s, current);
1030 switch (current[0]) {
1032 diff->years = an_int;
1037 diff->seconds += an_int * 60;
1039 diff->months = an_int;
1043 diff->days += an_int * 7;
1046 diff->days += an_int;
1052 diff->seconds += an_int;
1055 crm_err(
"'%s' is not a valid ISO 8601 time duration " 1056 "because no units after %d", period_s, an_int);
1059 crm_err(
"'%s' is not a valid ISO 8601 time duration " 1060 "because '%c' is not a valid time unit",
1061 period_s, current[0]);
1067 crm_err(
"'%s' is not a valid ISO 8601 time duration " 1068 "because no amounts and units given", period_s);
1092 const char *original = period_str;
1095 if (pcmk__str_empty(period_str)) {
1096 crm_err(
"No ISO 8601 time period given");
1104 if (period_str[0] ==
'P') {
1106 if (period->
diff == NULL) {
1110 period->
start = parse_date(period_str);
1111 if (period->
start == NULL) {
1116 period_str = strstr(original,
"/");
1119 if (period_str[0] ==
'P') {
1120 if (period->
diff != NULL) {
1121 crm_err(
"'%s' is not a valid ISO 8601 time period " 1122 "because it has two durations",
1127 if (period->
diff == NULL) {
1131 period->
end = parse_date(period_str);
1132 if (period->
end == NULL) {
1137 }
else if (period->
diff != NULL) {
1143 crm_err(
"'%s' is not a valid ISO 8601 time period " 1144 "because it has no duration or ending time",
1149 if (period->
start == NULL) {
1152 }
else if (period->
end == NULL) {
1157 crm_err(
"'%s' is not a valid ISO 8601 time period " 1158 "because the start is invalid", period_str);
1162 crm_err(
"'%s' is not a valid ISO 8601 time period " 1163 "because the end is invalid", period_str);
1198 target->years = source->years;
1199 target->days = source->days;
1200 target->months = source->months;
1201 target->seconds = source->seconds;
1202 target->offset = source->offset;
1222 target->duration = FALSE;
1224 if (source->tm_year > 0) {
1226 target->years = 1900 + source->tm_year;
1229 if (source->tm_yday >= 0) {
1231 target->days = 1 + source->tm_yday;
1234 if (source->tm_hour >= 0) {
1237 if (source->tm_min >= 0) {
1238 target->seconds += 60 * source->tm_min;
1240 if (source->tm_sec >= 0) {
1241 target->seconds += source->tm_sec;
1247 crm_trace(
"Offset (s): %ld, offset (hh:mm): %.2d:%.2d",
GMTOFF(source), h_offset, m_offset);
1250 target->offset += 60 * m_offset;
1256 ha_set_tm_time(
target, localtime(source));
1274 if ((dt == NULL) || (value == NULL)) {
1281 utc = crm_get_utc_time(value);
1287 answer->years += utc->years;
1302 if ((dt == NULL) || (value == NULL)) {
1307 utc = crm_get_utc_time(value);
1312 answer = crm_get_utc_time(dt);
1313 if (answer == NULL) {
1317 answer->duration = TRUE;
1319 answer->years -= utc->years;
1320 if(utc->months != 0) {
1336 if ((dt == NULL) || (value == NULL)) {
1341 utc = crm_get_utc_time(value);
1347 answer->years -= utc->years;
1348 if(utc->months != 0) {
1368 && (dt->days > 0) && (dt->days <= year_days(dt->years))
1369 && (dt->seconds >= 0) && (dt->seconds <
DAY_SECONDS);
1372 #define do_cmp_field(l, r, field) \ 1374 if(l->field > r->field) { \ 1375 crm_trace("%s: %d > %d", \ 1376 #field, l->field, r->field); \ 1378 } else if(l->field < r->field) { \ 1379 crm_trace("%s: %d < %d", \ 1380 #field, l->field, r->field); \ 1392 if ((t1 == NULL) && (t2 == NULL)) {
1394 }
else if (t1 == NULL) {
1396 }
else if (t2 == NULL) {
1420 crm_trace(
"Adding %d seconds to %d (max=%d)",
1422 a_time->seconds += extra;
1427 if (a_time->seconds < 0) {
1438 int lower_bound = 1;
1441 crm_trace(
"Adding %d days to %.4d-%.3d", extra, a_time->years, a_time->days);
1443 a_time->days += extra;
1444 while (a_time->days > ydays) {
1446 a_time->days -= ydays;
1450 if(a_time->duration) {
1454 while (a_time->days < lower_bound) {
1464 uint32_t y, m, d, dmax;
1467 crm_trace(
"Adding %d months to %.4d-%.2d-%.2d", extra, y, m, d);
1470 for (lpc = extra; lpc > 0; lpc--) {
1478 for (lpc = -extra; lpc > 0; lpc--) {
1493 crm_trace(
"Calculated %.4d-%.2d-%.2d", y, m, d);
1496 a_time->days = get_ordinal_days(y, m, d);
1499 crm_trace(
"Got %.4d-%.2d-%.2d", y, m, d);
1523 a_time->years += extra;
1530 .tm_year = source->years - 1900,
1531 .tm_mday = source->days,
1532 .tm_sec = source->seconds % 60,
1533 .tm_min = ( source->seconds / 60 ) % 60,
1538 .tm_gmtoff = source->offset
1564 .months = dt->months,
1566 .seconds = dt->seconds,
1567 .offset = dt->offset,
1568 .duration = dt->duration
1580 .years = hr_dt->
years,
1582 .days = hr_dt->
days,
1607 struct timeval tv_now;
1610 if (gettimeofday(&tv_now, NULL) == 0) {
1616 dt = parse_date(date_time);
1633 int max = 128, scanned_pos = 0, printed_pos = 0, fmt_pos = 0,
1634 date_len = 0, nano_digits = 0;
1635 char nano_s[10], date_s[max+1], nanofmt_s[5] =
"%", *tmp_fmt_s;
1643 ha_get_tm_time(&tm, &dt);
1644 sprintf(nano_s,
"%06d000", hr_dt->
useconds);
1646 while ((format[scanned_pos]) !=
'\0') {
1647 mark_s = strchr(&format[scanned_pos],
'%');
1651 fmt_pos = mark_s - format;
1652 while ((format[fmt_pos+fmt_len] !=
'\0') &&
1653 (format[fmt_pos+fmt_len] >=
'0') &&
1654 (format[fmt_pos+fmt_len] <=
'9')) {
1657 scanned_pos = fmt_pos + fmt_len + 1;
1658 if (format[fmt_pos+fmt_len] ==
'N') {
1659 nano_digits = atoi(&format[fmt_pos+1]);
1660 nano_digits = (nano_digits > 6)?6:nano_digits;
1661 nano_digits = (nano_digits < 0)?0:nano_digits;
1662 sprintf(&nanofmt_s[1],
".%ds", nano_digits);
1664 if (format[scanned_pos] !=
'\0') {
1667 fmt_pos = scanned_pos;
1670 scanned_pos = strlen(format);
1671 fmt_pos = scanned_pos;
1673 tmp_fmt_s =
strndup(&format[printed_pos], fmt_pos - printed_pos);
1674 #ifdef GCC_FORMAT_NONLITERAL_CHECKING_ENABLED 1675 #pragma GCC diagnostic push 1676 #pragma GCC diagnostic ignored "-Wformat-nonliteral" 1678 date_len += strftime(&date_s[date_len], max-date_len, tmp_fmt_s, &tm);
1679 #ifdef GCC_FORMAT_NONLITERAL_CHECKING_ENABLED 1680 #pragma GCC diagnostic pop 1682 printed_pos = scanned_pos;
1685 #ifdef GCC_FORMAT_NONLITERAL_CHECKING_ENABLED 1686 #pragma GCC diagnostic push 1687 #pragma GCC diagnostic ignored "-Wformat-nonliteral" 1689 date_len += snprintf(&date_s[date_len], max-date_len,
1691 #ifdef GCC_FORMAT_NONLITERAL_CHECKING_ENABLED 1692 #pragma GCC diagnostic pop 1698 return (date_len == 0)?NULL:strdup(date_s);
1716 char *since_epoch = NULL;
1719 time_t a_time = time(NULL);
1721 if (a_time == (time_t) -1) {
1724 since_epoch = ctime(&a_time);
1727 since_epoch = ctime(when);
1730 if (since_epoch == NULL) {
1751 #define MS_IN_S (1000) 1752 #define MS_IN_M (MS_IN_S * 60) 1753 #define MS_IN_H (MS_IN_M * 60) 1754 #define MS_IN_D (MS_IN_H * 24) 1755 #define MAXSTR sizeof("..d..h..m..s...ms") 1756 static char str[
MAXSTR] = {
'\0', };
1760 offset += snprintf(str + offset,
MAXSTR - offset,
"%ud",
1765 offset += snprintf(str + offset,
MAXSTR - offset,
"%uh",
1770 offset += snprintf(str + offset,
MAXSTR - offset,
"%um",
1777 offset += snprintf(str + offset,
MAXSTR - offset,
"%u",
1780 if (interval_ms > 0) {
1781 offset += snprintf(str + offset,
MAXSTR - offset,
".%03u",
1784 (void) snprintf(str + offset,
MAXSTR - offset,
"s");
1786 }
else if (interval_ms > 0) {
1787 (void) snprintf(str + offset,
MAXSTR - offset,
"%ums", interval_ms);
1789 }
else if (str[0] ==
'\0') {
#define CRM_CHECK(expr, failure_action)
crm_time_t * crm_time_new_undefined()
Allocate memory for an uninitialized time object.
crm_time_t * pcmk_copy_time(crm_time_t *source)
bool crm_time_leapyear(int year)
crm_time_t * crm_time_subtract(crm_time_t *dt, crm_time_t *value)
void pcmk__time_hr_free(pcmk__time_hr_t *hr_dt)
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
void crm_time_add_minutes(crm_time_t *a_time, int extra)
const char * pcmk__readable_interval(guint interval_ms)
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.
pcmk__time_hr_t * pcmk__time_timeval_hr_convert(pcmk__time_hr_t *target, struct timeval *tv)
#define crm_time_log_duration
char * strndup(const char *str, size_t len)
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)
pcmk__time_hr_t * pcmk__time_hr_new(const char *date_time)
struct pcmk__time_us pcmk__time_hr_t
crm_time_period_t * crm_time_parse_period(const char *period_str)
Parse a time period from an ISO 8601 interval specification.
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)
Add a given number of seconds to a date/time or duration.
bool crm_time_check(crm_time_t *dt)
Check whether a time object represents a sensible date/time.
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...)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
int crm_time_get_isoweek(crm_time_t *dt, uint *y, uint *w, uint *d)
crm_time_t * crm_time_parse_duration(const char *period_s)
Parse a time duration from an ISO 8601 duration specification.
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)
Return number of days in given month of given year.
#define crm_time_log_with_timezone
int crm_time_get_timezone(crm_time_t *dt, uint *h, uint *m)
char * pcmk__time_format_hr(const char *format, pcmk__time_hr_t *hr_dt)
void crm_time_add_years(crm_time_t *a_time, int extra)
bool crm_time_is_defined(const crm_time_t *t)
Check whether a time object has been initialized yet.
#define HAVE_STRUCT_TM_TM_GMTOFF
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)
const char * pcmk__epoch2str(time_t *when)
#define pcmk__plural_s(i)
void pcmk__time_set_hr_dt(crm_time_t *target, pcmk__time_hr_t *hr_dt)
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 * pcmk__trim(char *str)
char * crm_time_as_string(crm_time_t *date_time, int flags)
void crm_time_free_period(crm_time_period_t *period)
Free a dynamically allocated time period object.
#define crm_time_log_date
pcmk__time_hr_t * pcmk__time_hr_convert(pcmk__time_hr_t *target, crm_time_t *dt)
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)