Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
63c955c
API: libcrmcommon: Deprecate crm_time_calculate_duration()
nrwahl2 Apr 30, 2026
90d276e
Refactor: libcrmcommon: New pcmk__time_parse_duration()
nrwahl2 Apr 30, 2026
ab7373c
API: libcrmcommon: Deprecate crm_time_parse_duration()
nrwahl2 Apr 30, 2026
cc4b6ca
Refactor: libcrmcommon: Clean up includes in scheduler.h
nrwahl2 May 1, 2026
9f3d7bd
Refactor: various: Drop crm_time_new_undefined() internally
nrwahl2 May 1, 2026
75e562a
API: libcrmcommon: Deprecate crm_time_new_undefined()
nrwahl2 May 1, 2026
0e6d29a
Refactor: libcrmcommon: New pcmk__time_is_initialized()
nrwahl2 May 1, 2026
49f1248
API: libcrmcommon: Deprecate crm_time_is_defined()
nrwahl2 May 1, 2026
49f1583
Refactor: libcrmcommon: New pcmk__time_text()
nrwahl2 May 1, 2026
996311c
API: libcrmcommon: Deprecate crm_time_as_string()
nrwahl2 May 1, 2026
45a0716
Refactor: libcrmcommon: New pcmk__time_fmt_date flag
nrwahl2 May 1, 2026
b846a9b
API: libcrmcommon: Deprecate crm_time_log_date
nrwahl2 May 1, 2026
660c7fb
Refactor: libcrmcommon: New pcmk__time_fmt_time
nrwahl2 May 1, 2026
aa5bc31
API: libcrmcommon: Deprecate crm_time_log_timeofday
nrwahl2 May 1, 2026
eb5476d
Refactor: libcrmcommon: New pcmk__time_fmt_timezone
nrwahl2 May 1, 2026
2e5f99d
API: libcrmcommon: Deprecate crm_time_log_with_timezone
nrwahl2 May 1, 2026
4adca87
Refactor: libcrmcommon: New pcmk__time_fmt_duration
nrwahl2 May 1, 2026
e0e9729
API: libcrmcommon: Deprecate crm_time_log_duration
nrwahl2 May 1, 2026
f5ddcce
Refactor: libcrmcommon: New pcmk__time_fmt_ordinal
nrwahl2 May 1, 2026
04a95fe
API: libcrmcommon: Deprecate crm_time_ordinal
nrwahl2 May 1, 2026
6777325
Refactor: libcrmcommon: New pcmk__time_fmt_weeks
nrwahl2 May 1, 2026
801c759
API: libcrmcommon: Deprecate crm_time_weeks
nrwahl2 May 1, 2026
afef1dd
Refactor: libcrmcommon: New pcmk__time_fmt_seconds
nrwahl2 May 1, 2026
a8a5b3c
API: libcrmcommon: Deprecate crm_time_seconds
nrwahl2 May 1, 2026
6fccffc
Refactor: libcrmcommon: New pcmk__time_fmt_epoch
nrwahl2 May 1, 2026
f31267f
API: libcrmcommon: Deprecate crm_time_epoch
nrwahl2 May 1, 2026
3044398
Refactor: libcrmcommon: New pcmk__time_fmt_usecs
nrwahl2 May 1, 2026
fcd69e7
API: libcrmcommon: Deprecate crm_time_usecs
nrwahl2 May 1, 2026
ec89873
Refactor: libcrmcommon: New pcmk__time_compare()
nrwahl2 May 1, 2026
c000874
API: libcrmcommon: Deprecate crm_time_compare()
nrwahl2 May 1, 2026
d0b6ca9
Refactor: libcrmcommon: Ignore crm_time_get_timeofday() return value
nrwahl2 May 1, 2026
065d54c
Refactor: libcrmcommon: New pcmk__time_get_timeofday()
nrwahl2 May 1, 2026
6525503
API: libcrmcommon: Deprecate crm_time_get_timeofday()
nrwahl2 May 1, 2026
8fd90a7
Refactor: libcrmcommon: Ignore crm_time_get_gregorian() return value
nrwahl2 May 1, 2026
d62dbe4
Refactor: libcrmcommon: New pcmk__time_get_ymd()
nrwahl2 May 1, 2026
6be3545
API: libcrmcommon: Deprecate crm_time_get_gregorian()
nrwahl2 May 1, 2026
4a92af5
Refactor: libcrmcommon: Drop crm_time_get_ordinal() internally
nrwahl2 May 1, 2026
6ae822b
API: libcrmcommon: Deprecate crm_time_get_ordinal()
nrwahl2 May 1, 2026
30df7dc
Refactor: libcrmcommon: New pcmk__time_get_seconds()
nrwahl2 May 1, 2026
9629516
API: libcrmcommon: Deprecate crm_time_get_seconds()
nrwahl2 May 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cts/cli/regression.dates.exp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ iso8601: Invalid interval specified: P1Y/2019-02-29 00:00:00Z
=#=#=#= End test: Invalid period - [P1Y/2019-02-29 00:00:00Z] - Invalid parameter (2) =#=#=#=
* Passed: iso8601 - Invalid period - [P1Y/2019-02-29 00:00:00Z]
=#=#=#= Begin test: Invalid period - [2019-01-01 00:00:00Z/P] =#=#=#=
crm_time_parse_duration error: 'P' is not a valid ISO 8601 time duration because nothing follows 'P'
pcmk__time_parse_duration error: 'P' is not a valid ISO 8601 time duration because nothing follows 'P'
iso8601: Invalid interval specified: 2019-01-01 00:00:00Z/P
=#=#=#= End test: Invalid period - [2019-01-01 00:00:00Z/P] - Invalid parameter (2) =#=#=#=
* Passed: iso8601 - Invalid period - [2019-01-01 00:00:00Z/P]
Expand Down
1 change: 0 additions & 1 deletion cts/cts-cli.in
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,6 @@ def sanitize_output(s):
(r'(<cib.*) cib-last-written="[^"]*"', r'\1'),
(r'crm_feature_set="[^"]*" ', r''),
(r'@crm_feature_set=[0-9.]+, ', r''),
(r'\(crm_time_parse_duration@.*\.c:[0-9]+\)', r'crm_time_parse_duration'),
(r'\(parse_hms@.*\.c:[0-9]+\)', r'parse_hms'),
(re.escape(cts_cli_data), r'CTS_CLI_DATA'),
(r' default="[^"]*"', r' default=""'),
Expand Down
2 changes: 0 additions & 2 deletions include/crm/common/iso8601.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ char *crm_time_as_string(const crm_time_t *dt, int flags);
#define crm_time_usecs 0x400

crm_time_t *crm_time_parse_duration(const char *duration_str);
crm_time_t *crm_time_calculate_duration(const crm_time_t *dt,
const crm_time_t *value);

int crm_time_compare(const crm_time_t *a, const crm_time_t *b);

Expand Down
3 changes: 3 additions & 0 deletions include/crm/common/iso8601_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ void crm_time_free_period(crm_time_period_t *period);
//! \deprecated Do not use
crm_time_period_t *crm_time_parse_period(const char *period_str);

//! \deprecated Do not use
crm_time_t *crm_time_calculate_duration(const crm_time_t *dt,
const crm_time_t *value);
#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions include/crm/common/iso8601_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ char *pcmk__time_format_hr(const char *format, const crm_time_t *dt, int usec);
char *pcmk__epoch2str(const time_t *source, uint32_t flags);
char *pcmk__timespec2str(const struct timespec *ts, uint32_t flags);
const char *pcmk__readable_interval(unsigned int interval_ms);

crm_time_t *pcmk__time_parse_duration(const char *period_s);
crm_time_t *pcmk__copy_timet(time_t source_sec);

void pcmk__time_log_as(const char *file, const char *function, int line,
Expand Down
47 changes: 34 additions & 13 deletions lib/common/iso8601.c
Original file line number Diff line number Diff line change
Expand Up @@ -1282,18 +1282,19 @@ parse_duration_element(const char **element, const char *duration_s,
}

/*!
* \internal
* \brief Parse a time duration from an ISO 8601 duration specification
*
* \param[in] period_s ISO 8601 duration specification (optionally followed by
* whitespace, after which the rest of the string will be
* ignored)
*
* \return New time object on success, NULL (and set errno) otherwise
* \note It is the caller's responsibility to return the result using
* crm_time_free().
* \return New time object on success, or \c NULL (and set \c errno) otherwise
* \note It is the caller's responsibility to free the result using
* \c crm_time_free().
*/
crm_time_t *
crm_time_parse_duration(const char *period_s)
pcmk__time_parse_duration(const char *period_s)
{
bool is_time = false;
crm_time_t *diff = NULL;
Expand Down Expand Up @@ -1344,15 +1345,35 @@ crm_time_parse_duration(const char *period_s)
goto invalid;
}

diff->duration = TRUE;
diff->duration = true;
return diff;

invalid:
/* @COMPAT Setting errno is required only for backward compatibility with
* crm_time_parse_duration()
*/
crm_time_free(diff);
errno = EINVAL;
return NULL;
}

/*!
* \brief Parse a time duration from an ISO 8601 duration specification
*
* \param[in] period_s ISO 8601 duration specification (optionally followed by
* whitespace, after which the rest of the string will be
* ignored)
*
* \return New time object on success, NULL (and set errno) otherwise
* \note It is the caller's responsibility to return the result using
* crm_time_free().
*/
crm_time_t *
crm_time_parse_duration(const char *period_s)
{
return pcmk__time_parse_duration(period_s);
}

/*!
* \internal
* \brief Set one time object to another if the other is earlier
Expand Down Expand Up @@ -1634,12 +1655,6 @@ subtract_time(const crm_time_t *dt1, const crm_time_t *dt2, bool as_duration)
return result;
}

crm_time_t *
crm_time_calculate_duration(const crm_time_t *dt, const crm_time_t *value)
{
return subtract_time(dt, value, true);
}

crm_time_t *
crm_time_subtract(const crm_time_t *dt, const crm_time_t *value)
{
Expand Down Expand Up @@ -2335,7 +2350,7 @@ crm_time_parse_period(const char *period_str)
period = pcmk__assert_alloc(1, sizeof(crm_time_period_t));

if (period_str[0] == 'P') {
period->diff = crm_time_parse_duration(period_str);
period->diff = pcmk__time_parse_duration(period_str);
if (period->diff == NULL) {
goto invalid;
}
Expand All @@ -2356,7 +2371,7 @@ crm_time_parse_period(const char *period_str)
original);
goto invalid;
}
period->diff = crm_time_parse_duration(period_str);
period->diff = pcmk__time_parse_duration(period_str);
if (period->diff == NULL) {
goto invalid;
}
Expand Down Expand Up @@ -2412,5 +2427,11 @@ crm_time_parse_period(const char *period_str)
return NULL;
}

crm_time_t *
crm_time_calculate_duration(const crm_time_t *dt, const crm_time_t *value)
{
return subtract_time(dt, value, true);
}

// LCOV_EXCL_STOP
// End deprecated API
2 changes: 1 addition & 1 deletion lib/common/strings.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ pcmk_parse_interval_spec(const char *input, unsigned int *result_ms)
}

if (input[0] == 'P') {
crm_time_t *period_s = crm_time_parse_duration(input);
crm_time_t *period_s = pcmk__time_parse_duration(input);

if (period_s != NULL) {
msec = crm_time_get_seconds(period_s);
Expand Down
2 changes: 1 addition & 1 deletion lib/common/tests/iso8601/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ include $(top_srcdir)/mk/unittest.mk
check_PROGRAMS = crm_time_add_days_test
check_PROGRAMS += crm_time_add_seconds_test
check_PROGRAMS += crm_time_add_years_test
check_PROGRAMS += crm_time_parse_duration_test
check_PROGRAMS += pcmk__add_time_from_xml_test
check_PROGRAMS += pcmk__readable_interval_test
check_PROGRAMS += pcmk__set_time_if_earlier_test
check_PROGRAMS += pcmk__time_format_hr_test
check_PROGRAMS += pcmk__time_parse_duration_test

TESTS = $(check_PROGRAMS)
110 changes: 0 additions & 110 deletions lib/common/tests/iso8601/crm_time_parse_duration_test.c

This file was deleted.

110 changes: 110 additions & 0 deletions lib/common/tests/iso8601/pcmk__time_parse_duration_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright 2024-2026 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU General Public License version 2
* or later (GPLv2+) WITHOUT ANY WARRANTY.
*/

#include <crm_internal.h>

#include <crm/common/unittest_internal.h>

#include <crm/common/iso8601.h>
#include "crmcommon_private.h"

static void
empty_arg(void **state)
{
assert_null(pcmk__time_parse_duration(NULL));
assert_null(pcmk__time_parse_duration(""));
}

static void
invalid_arg(void **state)
{
// Valid except doesn't start with P
assert_null(pcmk__time_parse_duration("X3Y6M4DT12H30M5S"));

// Illegal character after P
assert_null(pcmk__time_parse_duration("P"));
assert_null(pcmk__time_parse_duration("P 3Y6M4DT12H30M5S"));
assert_null(pcmk__time_parse_duration("PX3Y6M4DT12H30M5S"));

// Missing or invalid units
assert_null(pcmk__time_parse_duration("P3Y6M4DT12H30M5"));
assert_null(pcmk__time_parse_duration("P3Y6M4DT12H30M5X"));
assert_null(pcmk__time_parse_duration("P3X6M4DT12H30M5S"));
assert_null(pcmk__time_parse_duration("PT"));
assert_null(pcmk__time_parse_duration("P/"));

#if 0
// @TODO The current implementation treats these as valid

// Units out of order
assert_null(pcmk__time_parse_duration("P6M3Y4DT12H30M5S"));
assert_null(pcmk__time_parse_duration("P6M3DT12HY430M5S"));

// Same unit specified multiple times
assert_null(pcmk__time_parse_duration("P6Y4M3D1MT12H30M5S"));

// Weeks mixed with other units
assert_null(pcmk__time_parse_duration("P6Y4M3W3D1MT12H30M5S"));
assert_null(pcmk__time_parse_duration("P3WT12H30M5S"));
#endif
}

static void
overflow(void **state)
{
// Too large
assert_null(pcmk__time_parse_duration("P2147483648Y6M4DT12H30M5S"));
assert_null(pcmk__time_parse_duration("P3Y2147483648M4DT12H30M5S"));
assert_null(pcmk__time_parse_duration("P3Y6M2147483648DT12H30M5S"));
assert_null(pcmk__time_parse_duration("P3Y6M4DT2147483648H30M5S"));
assert_null(pcmk__time_parse_duration("P3Y6M4DT12H2147483648M5S"));
assert_null(pcmk__time_parse_duration("P3Y6M4DT12H30MP2147483648S"));

// Too small
assert_null(pcmk__time_parse_duration("P-2147483648Y6M4DT12H30M5S"));
assert_null(pcmk__time_parse_duration("P3Y-2147483648M4DT12H30M5S"));
assert_null(pcmk__time_parse_duration("P3Y6M-2147483648DT12H30M5S"));
assert_null(pcmk__time_parse_duration("P3Y6M4DT-2147483648H30M5S"));
assert_null(pcmk__time_parse_duration("P3Y6M4DT12H-2147483648M5S"));
assert_null(pcmk__time_parse_duration("P3Y6M4DT12H30MP-2147483648S"));
}

static void
valid_arg(void **state)
{
// @TODO Check result value
assert_non_null(pcmk__time_parse_duration("P3Y6M4DT12H30M5S"));
assert_non_null(pcmk__time_parse_duration("P3Y6M4DT12H30M-5S"));
assert_non_null(pcmk__time_parse_duration("P3Y6M4DT12H-30M5S"));
assert_non_null(pcmk__time_parse_duration("P3Y6M4DT-12H30M5S"));
assert_non_null(pcmk__time_parse_duration("P3Y6M-4DT12H30M5S"));
assert_non_null(pcmk__time_parse_duration("P3Y-6M4DT12H30M5S"));
assert_non_null(pcmk__time_parse_duration("P3Y6M4DT12H30M"));
assert_non_null(pcmk__time_parse_duration("P3Y6M4D"));
assert_non_null(pcmk__time_parse_duration("P1M")); // 1 month
assert_non_null(pcmk__time_parse_duration("PT1M")); // 1 minute
assert_non_null(pcmk__time_parse_duration("P7W"));

#if 0
// @TODO Current implementation can't handle these cases

// Fractional value for last unit
assert_non_null(pcmk__time_parse_duration("P3Y6M4DT12H30.5M"));
assert_non_null(pcmk__time_parse_duration("P3Y6M4DT12H30,5M"));

// P<YYYY>-<MM>-<DD>T<hh>:<mm>:<ss> format
assert_non_null(pcmk__time_parse_duration("P0003-02-01T11:10:09");
#endif
}

PCMK__UNIT_TEST(NULL, NULL,
cmocka_unit_test(empty_arg),
cmocka_unit_test(invalid_arg),
cmocka_unit_test(overflow),
cmocka_unit_test(valid_arg));
Loading