43 #if defined(HAVE_STRUCT_TM_TM_GMTOFF) 44 # define GMTOFF(tm) ((tm)->tm_gmtoff) 47 # define GMTOFF(tm) (-timezone+daylight) 50 #define HOUR_SECONDS (60 * 60) 51 #define DAY_SECONDS (HOUR_SECONDS * 24) 65 #define valid_sec_usec(sec, usec) \ 66 ((QB_ABS(usec) < QB_TIME_US_IN_SEC) \ 67 && (((sec) == 0) || ((usec) == 0) || (((sec) < 0) == ((usec) < 0)))) 79 static crm_time_t *parse_date(
const char *date_str);
92 utc->years = dt->years;
94 utc->seconds = dt->seconds;
101 utc->months = dt->months;
115 if (date_time == NULL) {
118 return parse_date(date_time);
145 return (t != NULL) && (t->years || t->months || t->days || t->seconds
146 || t->offset || t->duration);
180 int YY = (year - 1) % 100;
181 int C = (year - 1) - YY;
183 int jan1 = 1 + (((((C / 100) % 4) * 5) + G) % 7);
185 crm_trace(
"YY=%d, C=%d, G=%d", YY, C, G);
186 crm_trace(
"January 1 %.4d: %d", year, jan1);
211 static int month_days[13] = {
212 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 29
226 if ((month < 1) || (month > 12) || (year < 1)) {
232 return month_days[month - 1];
238 gboolean is_leap = FALSE;
243 if (year % 100 == 0 && year % 400 != 0) {
261 get_ordinal_days(uint32_t y, uint32_t m, uint32_t d)
265 CRM_CHECK((y > 0) && (y <= INT_MAX) && (m >= 1) && (m <= 12)
266 && (d >= 1) && (d <= 31),
return 0);
269 for (
int lpc = 1; lpc < m; lpc++) {
277 int line,
const char *prefix,
const crm_time_t *date_time,
284 (prefix? prefix :
""), (prefix?
": " :
""), date_s);
287 (prefix? prefix :
""), (prefix?
": " :
""), date_s);
293 crm_time_get_sec(
int sec, uint32_t *h, uint32_t *m, uint32_t *s)
295 uint32_t hours, minutes, seconds;
297 seconds = QB_ABS(sec);
302 minutes = seconds / 60;
303 seconds -= 60 * minutes;
305 crm_trace(
"%d == %.2" PRIu32
":%.2" PRIu32
":%.2" PRIu32,
306 sec, hours, minutes, seconds);
317 crm_time_get_sec(dt->seconds, h, m, s);
326 crm_time_get_sec(dt->seconds, h, m, &s);
335 long long in_seconds = 0;
341 utc = crm_get_utc_time(dt);
346 for (lpc = 1; lpc < utc->years; lpc++) {
347 long long dmax = year_days(lpc);
359 if (utc->months > 0) {
360 in_seconds +=
DAY_SECONDS * 30 * (
long long) (utc->months);
364 in_seconds +=
DAY_SECONDS * (
long long) (utc->days - 1);
366 in_seconds += utc->seconds;
372 #define EPOCH_SECONDS 62135596800ULL 387 for (months = 1; months <= 12 && days > 0; months++) {
397 }
else if (dt->months) {
408 crm_trace(
"%.4d-%.3d -> %.4d-%.2d-%.2d", dt->years, dt->days, dt->years, months, days);
435 h = dt->days + jan1 - 1;
436 *d = 1 + ((h - 1) % 7);
439 if (dt->days <= (8 - jan1) && jan1 > 4) {
441 year_num = dt->years - 1;
445 year_num = dt->years;
449 if (year_num == dt->years) {
450 int dmax = year_days(year_num);
451 int correction = 4 - *d;
453 if ((dmax - dt->days) < correction) {
454 crm_trace(
"year++, jan1=%d, i=%d vs. %d", jan1, dmax - dt->days, correction);
455 year_num = dt->years + 1;
461 if (year_num == dt->years) {
462 int j = dt->days + (7 - *d) + (jan1 - 1);
471 crm_trace(
"Converted %.4d-%.3d to %.4" PRIu32
"-W%.2" PRIu32
"-%" PRIu32,
472 dt->years, dt->days, *y, *w, *d);
489 sec_usec_as_string(
long long sec,
int usec,
char *buf,
size_t *offset)
491 *offset += snprintf(buf + *offset,
DATE_MAX - *offset,
"%s%lld.%06d",
492 ((sec == 0) && (usec < 0))?
"-" :
"",
506 crm_duration_as_string(
const crm_time_t *dt,
int usec,
bool show_usec,
514 offset += snprintf(
result + offset,
DATE_MAX - offset,
"%4d year%s ",
518 offset += snprintf(
result + offset,
DATE_MAX - offset,
"%2d month%s ",
522 offset += snprintf(
result + offset,
DATE_MAX - offset,
"%2d day%s ",
527 if ((offset == 0) || (dt->seconds != 0) || (show_usec && (usec != 0))) {
529 sec_usec_as_string(dt->seconds, usec,
result, &offset);
534 offset += snprintf(
result + offset,
DATE_MAX - offset,
" second%s",
539 if (QB_ABS(dt->seconds) >= 60) {
543 uint32_t u = QB_ABS(usec);
544 bool print_sec_component =
false;
546 crm_time_get_sec(dt->seconds, &h, &m, &s);
547 print_sec_component = ((s != 0) || (show_usec && (u != 0)));
554 ((m != 0) || print_sec_component)?
" " :
"");
560 print_sec_component?
" " :
"");
563 if (print_sec_component) {
565 sec_usec_as_string(s, u,
result, &offset);
570 offset += snprintf(
result + offset,
DATE_MAX - offset,
" second%s",
597 strcpy(
result,
"<undefined time>");
614 long long seconds = 0;
623 sec_usec_as_string(seconds, usec,
result, &offset);
633 utc = crm_get_utc_time(dt);
647 "%" PRIu32
"-W%.2" PRIu32
"-%" PRIu32,
657 "%" PRIu32
"-%.3" PRIu32, y, d);
667 "%.4" PRIu32
"-%.2" PRIu32
"-%.2" PRIu32,
674 uint32_t h = 0, m = 0, s = 0;
682 "%.2" PRIu32
":%.2" PRIu32
":%.2" PRIu32,
687 ".%06" PRIu32, QB_ABS(usec));
692 && (dt->offset != 0)) {
693 crm_time_get_sec(dt->offset, &h, &m, &s);
695 " %c%.2" PRIu32
":%.2" PRIu32,
696 ((dt->offset < 0)?
'-' :
'+'), h, m);
734 crm_time_parse_sec(
const char *time_str,
int *
result)
744 rc = sscanf(time_str,
"%" SCNu32
":%" SCNu32
":%" SCNu32,
745 &hour, &minute, &second);
747 rc = sscanf(time_str,
"%2" SCNu32
"%2" SCNu32
"%2" SCNu32,
748 &hour, &minute, &second);
751 crm_err(
"%s is not a valid ISO 8601 time specification", time_str);
756 crm_trace(
"Got valid time: %.2" PRIu32
":%.2" PRIu32
":%.2" PRIu32,
757 hour, minute, second);
759 if ((hour == 24) && (minute == 0) && (second == 0)) {
761 }
else if (hour >= 24) {
762 crm_err(
"%s is not a valid ISO 8601 time specification " 763 "because %" PRIu32
" is not a valid hour", time_str, hour);
768 crm_err(
"%s is not a valid ISO 8601 time specification " 769 "because %" PRIu32
" is not a valid minute", time_str, minute);
774 crm_err(
"%s is not a valid ISO 8601 time specification " 775 "because %" PRIu32
" is not a valid second", time_str, second);
785 crm_time_parse_offset(
const char *offset_str,
int *offset)
789 if (offset_str == NULL) {
791 #if defined(HAVE_STRUCT_TM_TM_GMTOFF) 792 time_t now = time(NULL);
793 struct tm *now_tm = localtime(&now);
798 if (h_offset < 0 && m_offset < 0) {
799 m_offset = 0 - m_offset;
805 if (offset_str[0] ==
'Z') {
811 if ((offset_str[0] ==
'+') || (offset_str[0] ==
'-')
812 || isdigit((
int)offset_str[0])) {
814 gboolean negate = FALSE;
816 if (offset_str[0] ==
'+') {
818 }
else if (offset_str[0] ==
'-') {
822 if (crm_time_parse_sec(offset_str, offset) == FALSE) {
826 *offset = 0 - *offset;
843 crm_time_parse(
const char *time_str,
crm_time_t *a_time)
846 char *offset_s = NULL;
851 if (crm_time_parse_sec(time_str, &(a_time->seconds)) == FALSE) {
854 offset_s = strstr(time_str,
"Z");
855 if (offset_s == NULL) {
856 offset_s = strstr(time_str,
" ");
858 while (isspace(offset_s[0])) {
865 if (crm_time_parse_offset(offset_s, &(a_time->offset)) == FALSE) {
868 crm_time_get_sec(a_time->offset, &h, &m, &s);
869 crm_trace(
"Got tz: %c%2." PRIu32
":%.2" PRIu32,
870 (a_time->offset < 0)?
'-' :
'+', h, m);
890 parse_date(
const char *date_str)
892 const char *time_s = NULL;
902 if (pcmk__str_empty(date_str)) {
903 crm_err(
"No ISO 8601 date/time specification given");
907 if ((date_str[0] ==
'T')
908 || ((strlen(date_str) > 2) && (date_str[2] ==
':'))) {
911 if (date_str[0] ==
'T') {
912 time_s = date_str + 1;
922 && ((date_str[5] ==
'\0')
923 || (date_str[5] ==
'/')
924 || isspace(date_str[5]))) {
932 rc = sscanf(date_str,
"%" SCNu32
"-%" SCNu32
"-%" SCNu32
"",
933 &year, &month, &day);
936 rc = sscanf(date_str,
"%4" SCNu32
"%2" SCNu32
"%2" SCNu32
"",
937 &year, &month, &day);
940 if ((month < 1U) || (month > 12U)) {
941 crm_err(
"'%s' is not a valid ISO 8601 date/time specification " 942 "because '%" PRIu32
"' is not a valid month",
945 }
else if ((year < 1U) || (year > INT_MAX)) {
946 crm_err(
"'%s' is not a valid ISO 8601 date/time specification " 947 "because '%" PRIu32
"' is not a valid year",
950 }
else if ((day < 1) || (day > INT_MAX)
952 crm_err(
"'%s' is not a valid ISO 8601 date/time specification " 953 "because '%" PRIu32
"' is not a valid day of the month",
958 dt->days = get_ordinal_days(year, month, day);
959 crm_trace(
"Parsed Gregorian date '%.4" PRIu32
"-%.3d' " 960 "from date string '%s'", year, dt->days, date_str);
966 rc = sscanf(date_str,
"%" SCNu32
"-%" SCNu32, &year, &day);
968 if ((year < 1U) || (year > INT_MAX)) {
969 crm_err(
"'%s' is not a valid ISO 8601 date/time specification " 970 "because '%" PRIu32
"' is not a valid year",
973 }
else if ((day < 1U) || (day > INT_MAX) || (day > year_days(year))) {
974 crm_err(
"'%s' is not a valid ISO 8601 date/time specification " 975 "because '%" PRIu32
"' is not a valid day of year %" 977 date_str, day, year, year_days(year));
980 crm_trace(
"Parsed ordinal year %d and days %d from date string '%s'",
981 year, day, date_str);
988 rc = sscanf(date_str,
"%" SCNu32
"-W%" SCNu32
"-%" SCNu32,
992 crm_err(
"'%s' is not a valid ISO 8601 date/time specification " 993 "because '%" PRIu32
"' is not a valid week of year %" 997 }
else if ((day < 1U) || (day > 7U)) {
998 crm_err(
"'%s' is not a valid ISO 8601 date/time specification " 999 "because '%" PRIu32
"' is not a valid day of the week",
1016 crm_trace(
"Parsed year %" PRIu32
" (Jan 1 = %d), week %" PRIu32
1017 ", and day %" PRIu32
" from date string '%s'",
1018 year, jan1, week, day, date_str);
1034 crm_err(
"'%s' is not a valid ISO 8601 date/time specification", date_str);
1039 if (time_s == NULL) {
1040 time_s = date_str + strspn(date_str,
"0123456789-W");
1041 if ((time_s[0] ==
' ') || (time_s[0] ==
'T')) {
1047 if ((time_s != NULL) && (crm_time_parse(time_s, dt) == FALSE)) {
1053 crm_err(
"'%s' is not a valid ISO 8601 date/time specification",
1067 parse_int(
const char *str,
int *
result)
1070 int offset = (str[0] ==
'T')? 1 : 0;
1071 bool negate =
false;
1076 switch (str[offset]) {
1095 for (lpc = 0; (lpc < 10) && isdigit(str[offset]); lpc++) {
1096 const int digit = str[offset++] -
'0';
1098 if ((*
result * 10LL + digit) > INT_MAX) {
1106 return (lpc > 0)? offset : 0;
1123 gboolean is_time = FALSE;
1126 if (pcmk__str_empty(period_s)) {
1127 crm_err(
"No ISO 8601 time duration given");
1130 if (period_s[0] !=
'P') {
1131 crm_err(
"'%s' is not a valid ISO 8601 time duration " 1132 "because it does not start with a 'P'", period_s);
1135 if ((period_s[1] ==
'\0') || isspace(period_s[1])) {
1136 crm_err(
"'%s' is not a valid ISO 8601 time duration " 1137 "because nothing follows 'P'", period_s);
1143 for (
const char *current = period_s + 1;
1144 current[0] && (current[0] !=
'/') && !isspace(current[0]);
1150 if (current[0] ==
'T') {
1160 rc = parse_int(current, &an_int);
1162 crm_err(
"'%s' is not a valid ISO 8601 time duration " 1163 "because no valid integer at '%s'", period_s, current);
1169 switch (current[0]) {
1171 diff->years = an_int;
1176 diff->months = an_int;
1178 result = diff->seconds + an_int * 60LL;
1180 crm_err(
"'%s' is not a valid ISO 8601 time duration " 1181 "because integer at '%s' is too %s",
1182 period_s, current - rc,
1183 ((
result > 0)?
"large" :
"small"));
1186 diff->seconds = (int)
result;
1193 result = diff->days + an_int * 7LL;
1195 crm_err(
"'%s' is not a valid ISO 8601 time duration " 1196 "because integer at '%s' is too %s",
1197 period_s, current - rc,
1198 ((
result > 0)?
"large" :
"small"));
1201 diff->days = (int)
result;
1206 result = diff->days + (
long long) an_int;
1208 crm_err(
"'%s' is not a valid ISO 8601 time duration " 1209 "because integer at '%s' is too %s",
1210 period_s, current - rc,
1211 ((
result > 0)?
"large" :
"small"));
1214 diff->days = (int)
result;
1221 crm_err(
"'%s' is not a valid ISO 8601 time duration " 1222 "because integer at '%s' is too %s",
1223 period_s, current - rc,
1224 ((
result > 0)?
"large" :
"small"));
1227 diff->seconds = (int)
result;
1232 result = diff->seconds + (
long long) an_int;
1234 crm_err(
"'%s' is not a valid ISO 8601 time duration " 1235 "because integer at '%s' is too %s",
1236 period_s, current - rc,
1237 ((
result > 0)?
"large" :
"small"));
1240 diff->seconds = (int)
result;
1245 crm_err(
"'%s' is not a valid ISO 8601 time duration " 1246 "because no units after %d", period_s, an_int);
1250 crm_err(
"'%s' is not a valid ISO 8601 time duration " 1251 "because '%c' is not a valid time unit",
1252 period_s, current[0]);
1258 crm_err(
"'%s' is not a valid ISO 8601 time duration " 1259 "because no amounts and units given", period_s);
1263 diff->duration = TRUE;
1285 const char *original = period_str;
1288 if (pcmk__str_empty(period_str)) {
1289 crm_err(
"No ISO 8601 time period given");
1296 if (period_str[0] ==
'P') {
1298 if (period->
diff == NULL) {
1302 period->
start = parse_date(period_str);
1303 if (period->
start == NULL) {
1308 period_str = strstr(original,
"/");
1311 if (period_str[0] ==
'P') {
1312 if (period->
diff != NULL) {
1313 crm_err(
"'%s' is not a valid ISO 8601 time period " 1314 "because it has two durations",
1319 if (period->
diff == NULL) {
1323 period->
end = parse_date(period_str);
1324 if (period->
end == NULL) {
1329 }
else if (period->
diff != NULL) {
1335 crm_err(
"'%s' is not a valid ISO 8601 time period " 1336 "because it has no duration or ending time",
1341 if (period->
start == NULL) {
1344 }
else if (period->
end == NULL) {
1349 crm_err(
"'%s' is not a valid ISO 8601 time period " 1350 "because the start is invalid", period_str);
1354 crm_err(
"'%s' is not a valid ISO 8601 time period " 1355 "because the end is invalid", period_str);
1390 target->years = source->years;
1391 target->days = source->days;
1392 target->months = source->months;
1393 target->seconds = source->seconds;
1394 target->offset = source->offset;
1414 target->duration = FALSE;
1416 if (source->tm_year > 0) {
1422 if (source->tm_yday >= 0) {
1424 target->days = 1 + source->tm_yday;
1427 if (source->tm_hour >= 0) {
1430 if (source->tm_min >= 0) {
1431 target->seconds += 60 * source->tm_min;
1433 if (source->tm_sec >= 0) {
1434 target->seconds += source->tm_sec;
1440 crm_trace(
"Time offset is %lds (%.2d:%.2d)",
1441 GMTOFF(source), h_offset, m_offset);
1444 target->offset += 60 * m_offset;
1450 ha_set_tm_time(
target, localtime(source));
1463 if ((
target != NULL) && (source != NULL)
1502 if ((dt == NULL) || (value == NULL)) {
1509 utc = crm_get_utc_time(value);
1536 switch (component) {
1576 switch (component) {
1622 if ((t == NULL) || (attr == NULL) || (add == NULL)) {
1635 if ((value < INT_MIN) || (value > INT_MAX)) {
1640 add(t, (
int) value);
1651 if ((dt == NULL) || (value == NULL)) {
1656 utc = crm_get_utc_time(value);
1661 answer = crm_get_utc_time(dt);
1662 if (answer == NULL) {
1666 answer->duration = TRUE;
1669 if(utc->months != 0) {
1685 if ((dt == NULL) || (value == NULL)) {
1690 utc = crm_get_utc_time(value);
1697 if(utc->months != 0) {
1718 && (dt->days > 0) && (dt->days <= year_days(dt->years))
1719 && (dt->seconds >= 0) && (dt->seconds <
DAY_SECONDS);
1722 #define do_cmp_field(l, r, field) \ 1724 if(l->field > r->field) { \ 1725 crm_trace("%s: %d > %d", \ 1726 #field, l->field, r->field); \ 1728 } else if(l->field < r->field) { \ 1729 crm_trace("%s: %d < %d", \ 1730 #field, l->field, r->field); \ 1742 if ((t1 == NULL) && (t2 == NULL)) {
1744 }
else if (t1 == NULL) {
1746 }
else if (t2 == NULL) {
1772 crm_trace(
"Adding %d seconds (including %d whole day%s) to %d",
1782 }
else if (a_time->seconds < 0) {
1790 #define ydays(t) (crm_time_leapyear((t)->years)? 366 : 365) 1803 crm_trace(
"Adding %d days to %.4d-%.3d", extra, a_time->years, a_time->days);
1806 while ((a_time->days + (
long long) extra) >
ydays(a_time)) {
1807 if ((a_time->years + 1LL) > INT_MAX) {
1808 a_time->days =
ydays(a_time);
1811 extra -=
ydays(a_time);
1814 }
else if (extra < 0) {
1815 const int min_days = a_time->duration? 0 : 1;
1817 while ((a_time->days + (
long long) extra) < min_days) {
1818 if ((a_time->years - 1) < 1) {
1823 extra +=
ydays(a_time);
1826 a_time->days += extra;
1833 uint32_t y, m, d, dmax;
1836 crm_trace(
"Adding %d months to %.4" PRIu32
"-%.2" PRIu32
"-%.2" PRIu32,
1840 for (lpc = extra; lpc > 0; lpc--) {
1848 for (lpc = -extra; lpc > 0; lpc--) {
1863 crm_trace(
"Calculated %.4" PRIu32
"-%.2" PRIu32
"-%.2" PRIu32, y, m, d);
1866 a_time->days = get_ordinal_days(y, m, d);
1869 crm_trace(
"Got %.4" PRIu32
"-%.2" PRIu32
"-%.2" PRIu32, y, m, d);
1895 if ((extra > 0) && ((a_time->years + (
long long) extra) > INT_MAX)) {
1896 a_time->years = INT_MAX;
1897 }
else if ((extra < 0) && ((a_time->years + (
long long) extra) < 1)) {
1900 a_time->years += extra;
1908 .tm_year = source->years - 1900,
1909 .tm_mday = source->days,
1910 .tm_sec = source->seconds % 60,
1911 .tm_min = ( source->seconds / 60 ) % 60,
1916 .tm_gmtoff = source->offset
1937 if (hr_dt == NULL) {
1943 .months = dt->months,
1945 .seconds = dt->seconds,
1946 .offset = dt->offset,
1947 .duration = dt->duration
1959 .years = hr_dt->
years,
1961 .days = hr_dt->
days,
1983 qb_util_timespec_from_epoch_get(&tv);
1984 if (epoch != NULL) {
1990 hr->
useconds = tv.tv_nsec / QB_TIME_NS_IN_USEC;
2000 if (date_time == NULL) {
2005 dt = parse_date(date_time);
2031 int scanned_pos = 0;
2032 int printed_pos = 0;
2033 size_t date_len = 0;
2035 char nano_s[10] = {
'\0', };
2036 char date_s[128] = {
'\0', };
2038 struct tm tm = { 0, };
2041 if (format == NULL) {
2045 ha_get_tm_time(&tm, &dt);
2046 sprintf(nano_s,
"%06d000", hr_dt->
useconds);
2048 while (format[scanned_pos] !=
'\0') {
2050 int nano_digits = 0;
2051 char *tmp_fmt_s = NULL;
2055 const char *mark_s = strchr(&format[scanned_pos],
'%');
2057 if (mark_s == NULL) {
2059 scanned_pos = strlen(format);
2060 fmt_pos = scanned_pos;
2063 fmt_pos = mark_s - format;
2066 scanned_pos = fmt_pos + 1;
2067 while (isdigit(format[scanned_pos])) {
2071 switch (format[scanned_pos]) {
2073 fmt_pos = scanned_pos;
2080 nano_digits = atoi(&format[fmt_pos + 1]);
2081 nano_digits = QB_MAX(nano_digits, 0);
2082 nano_digits = QB_MIN(nano_digits, 6);
2086 if (format[++scanned_pos] !=
'\0') {
2089 fmt_pos = scanned_pos;
2094 if (date_len >=
sizeof(date_s)) {
2098 tmp_fmt_s = strndup(&format[printed_pos], fmt_pos - printed_pos);
2099 #ifdef HAVE_FORMAT_NONLITERAL 2100 #pragma GCC diagnostic push 2101 #pragma GCC diagnostic ignored "-Wformat-nonliteral" 2103 nbytes = strftime(&date_s[date_len],
sizeof(date_s) - date_len,
2105 #ifdef HAVE_FORMAT_NONLITERAL 2106 #pragma GCC diagnostic pop 2113 printed_pos = scanned_pos;
2114 if (nano_digits != 0) {
2117 if (date_len >=
sizeof(date_s)) {
2120 nc = snprintf(&date_s[date_len],
sizeof(date_s) - date_len,
2121 "%.*s", nano_digits, nano_s);
2123 if ((nc < 0) || (nc == (
sizeof(date_s) - date_len))) {
2149 time_t epoch_time = (source == NULL)? time(NULL) : *source;
2181 struct timespec tmp_ts;
2186 qb_util_timespec_from_epoch_get(&tmp_ts);
2190 time_as_string_common(&dt, ts->tv_nsec / QB_TIME_NS_IN_USEC,
flags,
result);
2208 #define MS_IN_S (1000) 2209 #define MS_IN_M (MS_IN_S * 60) 2210 #define MS_IN_H (MS_IN_M * 60) 2211 #define MS_IN_D (MS_IN_H * 24) 2212 #define MAXSTR sizeof("..d..h..m..s...ms") 2218 offset += snprintf(str + offset,
MAXSTR - offset,
"%ud",
2223 offset += snprintf(str + offset,
MAXSTR - offset,
"%uh",
2228 offset += snprintf(str + offset,
MAXSTR - offset,
"%um",
2235 offset += snprintf(str + offset,
MAXSTR - offset,
"%u",
2238 if (interval_ms > 0) {
2239 offset += snprintf(str + offset,
MAXSTR - offset,
".%03u",
2242 (void) snprintf(str + offset,
MAXSTR - offset,
"s");
2244 }
else if (interval_ms > 0) {
2245 (void) snprintf(str + offset,
MAXSTR - offset,
"%ums", interval_ms);
2247 }
else if (str[0] ==
'\0') {
int crm_time_get_gregorian(const crm_time_t *dt, uint32_t *y, uint32_t *m, uint32_t *d)
#define CRM_CHECK(expr, failure_action)
void crm_time_set_timet(crm_time_t *target, const time_t *source)
bool crm_time_leapyear(int year)
int pcmk__add_time_from_xml(crm_time_t *t, enum pcmk__time_component component, const xmlNode *xml)
void crm_time_log_alias(int log_level, const char *file, const char *function, int line, const char *prefix, const crm_time_t *date_time, int flags)
void pcmk__time_hr_free(pcmk__time_hr_t *hr_dt)
#define crm_time_log_timeofday
crm_time_t * crm_time_new(const char *date_time)
void pcmk__set_time_if_earlier(crm_time_t *target, const crm_time_t *source)
struct crm_time_s crm_time_t
bool crm_time_check(const crm_time_t *dt)
Check whether a time object represents a sensible date/time.
void crm_time_add_minutes(crm_time_t *a_time, int extra)
crm_time_t * crm_time_calculate_duration(const crm_time_t *dt, const crm_time_t *value)
const char * pcmk__readable_interval(guint interval_ms)
void crm_time_add_weeks(crm_time_t *a_time, int extra)
int crm_time_get_timezone(const crm_time_t *dt, uint32_t *h, uint32_t *m)
char * pcmk__epoch2str(const time_t *source, uint32_t flags)
long long crm_time_get_seconds_since_epoch(const crm_time_t *dt)
void crm_time_set(crm_time_t *target, const crm_time_t *source)
int crm_time_compare(const crm_time_t *a, const crm_time_t *b)
void crm_time_free(crm_time_t *dt)
#define do_cmp_field(l, r, field)
crm_time_t * pcmk__copy_timet(time_t source)
#define valid_sec_usec(sec, usec)
char * pcmk__timespec2str(const struct timespec *ts, uint32_t flags)
#define do_crm_log_alias(level, file, function, line, fmt, args...)
Log a message as if it came from a different code location.
crm_time_t * crm_time_add(const crm_time_t *dt, const crm_time_t *value)
#define crm_time_log_duration
pcmk__time_hr_t * pcmk__time_hr_now(time_t *epoch)
long long crm_time_get_seconds(const crm_time_t *dt)
pcmk__time_hr_t * pcmk__time_hr_new(const char *date_time)
int pcmk__scan_ll(const char *text, long long *result, long long default_value)
struct pcmk__time_us pcmk__time_hr_t
void pcmk__time_set_hr_dt(crm_time_t *target, const pcmk__time_hr_t *hr_dt)
crm_time_period_t * crm_time_parse_period(const char *period_str)
Parse a time period from an ISO 8601 interval specification.
void crm_time_add_seconds(crm_time_t *a_time, int extra)
Add a given number of seconds to a date/time or duration.
crm_time_t * pcmk_copy_time(const crm_time_t *source)
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
void crm_time_add_days(crm_time_t *a_time, int extra)
Add days to a date/time.
#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_ordinal(const crm_time_t *dt, uint32_t *y, uint32_t *d)
crm_time_t * crm_time_parse_duration(const char *period_s)
Parse a time duration from an ISO 8601 duration specification.
int crm_time_get_timeofday(const crm_time_t *dt, uint32_t *h, uint32_t *m, uint32_t *s)
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
const char * pcmk__time_component_attr(enum pcmk__time_component component)
crm_time_t * crm_time_new_undefined(void)
Allocate memory for an uninitialized time object.
#define pcmk__str_copy(str)
char * crm_time_as_string(const crm_time_t *dt, int flags)
Get a string representation of a crm_time_t object.
char * pcmk__time_format_hr(const char *format, const pcmk__time_hr_t *hr_dt)
crm_time_t * crm_time_subtract(const crm_time_t *dt, const crm_time_t *value)
int crm_time_get_isoweek(const crm_time_t *dt, uint32_t *y, uint32_t *w, uint32_t *d)
#define pcmk__assert(expr)
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
pcmk__action_result_t result
#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)
#define pcmk__plural_s(i)
pcmk__time_hr_t * pcmk__time_hr_convert(pcmk__time_hr_t *target, const crm_time_t *dt)
void(* component_fn_t)(crm_time_t *, int)
char * pcmk__trim(char *str)
#define PCMK__VALUE_EPOCH
#define pcmk__assert_alloc(nmemb, size)
void crm_time_free_period(crm_time_period_t *period)
Free a dynamically allocated time period object.
#define crm_time_log_date