mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 00:47:10 +09:00
Merge pull request #26772 from yuwata/time-util-adjust-formattable-timestamp-max
time-util: adjust formattable timestamp max
This commit is contained in:
@@ -662,6 +662,9 @@ static int parse_timestamp_impl(
|
||||
* +5min
|
||||
* -5days
|
||||
* @2147483647 (seconds since epoch)
|
||||
*
|
||||
* Note, on DST change, 00:00:00 may not exist and in that case the time part may be shifted.
|
||||
* E.g. "Sun 2023-03-13 America/Havana" is parsed as "Sun 2023-03-13 01:00:00 CDT".
|
||||
*/
|
||||
|
||||
assert(t);
|
||||
|
||||
@@ -205,13 +205,17 @@ static inline usec_t usec_sub_signed(usec_t timestamp, int64_t delta) {
|
||||
return usec_sub_unsigned(timestamp, (usec_t) delta);
|
||||
}
|
||||
|
||||
/* The last second we can format is 31. Dec 9999, 1s before midnight, because otherwise we'd enter 5 digit
|
||||
* year territory. However, since we want to stay away from this in all timezones we take one day off. */
|
||||
#define USEC_TIMESTAMP_FORMATTABLE_MAX_64BIT ((usec_t) 253402214399000000) /* Thu 9999-12-30 23:59:59 UTC */
|
||||
/* With a 32bit time_t we can't go beyond 2038...
|
||||
* We parse timestamp with RFC-822/ISO 8601 (e.g. +06, or -03:00) as UTC, hence the upper bound must be off
|
||||
* by USEC_PER_DAY. See parse_timestamp() for more details. */
|
||||
#define USEC_TIMESTAMP_FORMATTABLE_MAX_32BIT (((usec_t) INT32_MAX) * USEC_PER_SEC - USEC_PER_DAY)
|
||||
#if SIZEOF_TIME_T == 8
|
||||
/* The last second we can format is 31. Dec 9999, 1s before midnight, because otherwise we'd enter 5 digit
|
||||
* year territory. However, since we want to stay away from this in all timezones we take one day off. */
|
||||
# define USEC_TIMESTAMP_FORMATTABLE_MAX ((usec_t) 253402214399000000)
|
||||
# define USEC_TIMESTAMP_FORMATTABLE_MAX USEC_TIMESTAMP_FORMATTABLE_MAX_64BIT
|
||||
#elif SIZEOF_TIME_T == 4
|
||||
/* With a 32bit time_t we can't go beyond 2038... */
|
||||
# define USEC_TIMESTAMP_FORMATTABLE_MAX ((usec_t) 2147483647000000)
|
||||
# define USEC_TIMESTAMP_FORMATTABLE_MAX USEC_TIMESTAMP_FORMATTABLE_MAX_32BIT
|
||||
#else
|
||||
# error "Yuck, time_t is neither 4 nor 8 bytes wide?"
|
||||
#endif
|
||||
|
||||
@@ -101,8 +101,8 @@ int main(int argc, char *argv[]) {
|
||||
test_should_fail("9999-12-31 00:00:00 UTC");
|
||||
test_should_fail("10000-01-01 00:00:00 UTC");
|
||||
#elif SIZEOF_TIME_T == 4
|
||||
test_should_pass("2038-01-19 03:14:07 UTC");
|
||||
test_should_fail("2038-01-19 03:14:08 UTC");
|
||||
test_should_pass("2038-01-18 03:14:07 UTC");
|
||||
test_should_fail("2038-01-18 03:14:08 UTC");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -407,6 +407,10 @@ static void test_format_timestamp_impl(usec_t x) {
|
||||
|
||||
static void test_format_timestamp_loop(void) {
|
||||
test_format_timestamp_impl(USEC_PER_SEC);
|
||||
test_format_timestamp_impl(USEC_TIMESTAMP_FORMATTABLE_MAX_32BIT-1);
|
||||
test_format_timestamp_impl(USEC_TIMESTAMP_FORMATTABLE_MAX_32BIT);
|
||||
test_format_timestamp_impl(USEC_TIMESTAMP_FORMATTABLE_MAX-1);
|
||||
test_format_timestamp_impl(USEC_TIMESTAMP_FORMATTABLE_MAX);
|
||||
|
||||
for (unsigned i = 0; i < TRIAL; i++) {
|
||||
usec_t x;
|
||||
@@ -617,8 +621,8 @@ TEST(format_timestamp_range) {
|
||||
test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, TIMESTAMP_US_UTC, "--- XXXX-XX-XX XX:XX:XX.XXXXXX UTC");
|
||||
test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, TIMESTAMP_DATE, "--- XXXX-XX-XX");
|
||||
#elif SIZEOF_TIME_T == 4
|
||||
test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX, TIMESTAMP_UTC, "Tue 2038-01-19 03:14:07 UTC");
|
||||
test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX, TIMESTAMP_DATE, "Tue 2038-01-19");
|
||||
test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX, TIMESTAMP_UTC, "Mon 2038-01-18 03:14:07 UTC");
|
||||
test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX, TIMESTAMP_DATE, "Mon 2038-01-18");
|
||||
test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, TIMESTAMP_UTC, "--- XXXX-XX-XX XX:XX:XX UTC");
|
||||
test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, TIMESTAMP_US_UTC, "--- XXXX-XX-XX XX:XX:XX.XXXXXX UTC");
|
||||
test_format_timestamp_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, TIMESTAMP_DATE, "--- XXXX-XX-XX");
|
||||
@@ -632,12 +636,30 @@ static void test_parse_timestamp_one(const char *str, usec_t max_diff, usec_t ex
|
||||
int r;
|
||||
|
||||
r = parse_timestamp(str, &usec);
|
||||
log_debug("/* %s(%s): max_diff="USEC_FMT", expected="USEC_FMT", result="USEC_FMT"*/", __func__, str, max_diff, expected, usec);
|
||||
log_debug("/* %s(%s): max_diff="USEC_FMT", expected="USEC_FMT", result="USEC_FMT" */", __func__, str, max_diff, expected, usec);
|
||||
assert_se(r >= 0);
|
||||
assert_se(usec >= expected);
|
||||
assert_se(usec_sub_unsigned(usec, expected) <= max_diff);
|
||||
}
|
||||
|
||||
static bool time_is_zero(usec_t usec) {
|
||||
const char *s;
|
||||
|
||||
s = FORMAT_TIMESTAMP(usec);
|
||||
return strstr(s, " 00:00:00 ");
|
||||
}
|
||||
|
||||
static bool timezone_equal(usec_t today, usec_t target) {
|
||||
const char *s, *t, *sz, *tz;
|
||||
|
||||
s = FORMAT_TIMESTAMP(today);
|
||||
t = FORMAT_TIMESTAMP(target);
|
||||
assert_se(sz = strrchr(s, ' '));
|
||||
assert_se(tz = strrchr(t, ' '));
|
||||
log_debug("%s("USEC_FMT", "USEC_FMT") -> %s, %s", __func__, today, target, s, t);
|
||||
return streq(sz, tz);
|
||||
}
|
||||
|
||||
static void test_parse_timestamp_impl(const char *tz) {
|
||||
usec_t today, now_usec;
|
||||
|
||||
@@ -819,12 +841,17 @@ static void test_parse_timestamp_impl(const char *tz) {
|
||||
|
||||
/* without date */
|
||||
assert_se(parse_timestamp("today", &today) == 0);
|
||||
test_parse_timestamp_one("00:01", 0, today + USEC_PER_MINUTE);
|
||||
test_parse_timestamp_one("00:00:01", 0, today + USEC_PER_SEC);
|
||||
test_parse_timestamp_one("00:00:01.001", 0, today + USEC_PER_SEC + 1000);
|
||||
test_parse_timestamp_one("00:00:01.0010", 0, today + USEC_PER_SEC + 1000);
|
||||
test_parse_timestamp_one("tomorrow", 0, today + USEC_PER_DAY);
|
||||
test_parse_timestamp_one("yesterday", 0, today - USEC_PER_DAY);
|
||||
if (time_is_zero(today)) {
|
||||
test_parse_timestamp_one("00:01", 0, today + USEC_PER_MINUTE);
|
||||
test_parse_timestamp_one("00:00:01", 0, today + USEC_PER_SEC);
|
||||
test_parse_timestamp_one("00:00:01.001", 0, today + USEC_PER_SEC + 1000);
|
||||
test_parse_timestamp_one("00:00:01.0010", 0, today + USEC_PER_SEC + 1000);
|
||||
|
||||
if (timezone_equal(today, today + USEC_PER_DAY) && time_is_zero(today + USEC_PER_DAY))
|
||||
test_parse_timestamp_one("tomorrow", 0, today + USEC_PER_DAY);
|
||||
if (timezone_equal(today, today - USEC_PER_DAY) && time_is_zero(today - USEC_PER_DAY))
|
||||
test_parse_timestamp_one("yesterday", 0, today - USEC_PER_DAY);
|
||||
}
|
||||
|
||||
/* relative */
|
||||
assert_se(parse_timestamp("now", &now_usec) == 0);
|
||||
|
||||
Reference in New Issue
Block a user