From 964fb28e774d5165811434ef7dccbff2ff02ff68 Mon Sep 17 00:00:00 2001 From: shifter Date: Fri, 24 Jan 2025 10:48:10 +0100 Subject: [PATCH] filterx: Fix strptime to remove unwanted gmtoff in datetime conversion The strptime function relies on the wallclocktime_strptime utility to parse time, leveraging its extensive heuristics. Additionally, we use the wallclocktime to unixtime conversion from the wallclocktime module, as the internal time representation in filterx datetime is unixtime. However, this conversion introduces an unintended side effect: the GMT offset (gmtoff) value is retained even after converting to UTC. This results in a double application of the time offset when the unixtime handler functions process the timestamp later. To address this issue, the simplest solution was to manually reset the GMT offset (gmtoff) to zero after the conversion. This approach is questionable, as it discards timezone information at the moment of creating the datetime object in certain cases. A potential improvement could involve creating a custom wallclocktime-to-unixtime converter to avoid such side effects. Signed-off-by: shifter --- lib/filterx/object-datetime.c | 2 ++ lib/filterx/tests/test_object_datetime.c | 6 +++--- tests/light/functional_tests/filterx/test_filterx.py | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/filterx/object-datetime.c b/lib/filterx/object-datetime.c index 8770c5aa8..48571e4bd 100644 --- a/lib/filterx/object-datetime.c +++ b/lib/filterx/object-datetime.c @@ -185,6 +185,7 @@ filterx_typecast_datetime_isodate(FilterXExpr *s, FilterXObject *args[], gsize a } convert_wall_clock_time_to_unix_time(&wct, &ut); + ut.ut_gmtoff = 0; return filterx_datetime_new(&ut); } @@ -288,6 +289,7 @@ _strptime_eval(FilterXExpr *s) if (end) { convert_wall_clock_time_to_unix_time(&wct, &ut); + ut.ut_gmtoff = 0; result = filterx_datetime_new(&ut); } else diff --git a/lib/filterx/tests/test_object_datetime.c b/lib/filterx/tests/test_object_datetime.c index 2469b6380..9ada66b76 100644 --- a/lib/filterx/tests/test_object_datetime.c +++ b/lib/filterx/tests/test_object_datetime.c @@ -196,9 +196,9 @@ Test(filterx_datetime, test_filterx_datetime_repr) GString *repr = scratch_buffers_alloc(); g_string_assign(repr, "foo"); cr_assert(filterx_object_repr(obj, repr)); - cr_assert_str_eq("2024-03-18T12:34:13.000+09:00", repr->str); + cr_assert_str_eq("2024-03-18T03:34:13.000+00:00", repr->str); cr_assert(filterx_object_repr_append(obj, repr)); - cr_assert_str_eq("2024-03-18T12:34:13.000+09:002024-03-18T12:34:13.000+09:00", repr->str); + cr_assert_str_eq("2024-03-18T03:34:13.000+00:002024-03-18T03:34:13.000+00:00", repr->str); filterx_simple_function_free_args(args, G_N_ELEMENTS(args)); filterx_object_unref(obj); @@ -310,7 +310,7 @@ Test(filterx_datetime, test_filterx_datetime_strptime_matching_nth_timefmt) GString *repr = scratch_buffers_alloc(); cr_assert(filterx_object_repr(obj, repr)); - cr_assert_str_eq(repr->str, "2024-04-08T10:11:12.000+01:00"); + cr_assert_str_eq(repr->str, "2024-04-08T09:11:12.000+00:00"); filterx_object_unref(obj); filterx_expr_unref(func_expr); diff --git a/tests/light/functional_tests/filterx/test_filterx.py b/tests/light/functional_tests/filterx/test_filterx.py index c3bbfa8d4..28873c867 100644 --- a/tests/light/functional_tests/filterx/test_filterx.py +++ b/tests/light/functional_tests/filterx/test_filterx.py @@ -138,7 +138,7 @@ def test_otel_logrecord_datetime_setter_getter(config, syslog_ng): assert file_true.get_stats()["processed"] == 1 assert "processed" not in file_false.get_stats() - assert file_true.read_log() == "1701353998.123000+00:00\n" + assert file_true.read_log() == "1701346798.123000+00:00\n" def test_otel_logrecord_body_string_setter_getter(config, syslog_ng): @@ -210,7 +210,7 @@ def test_otel_logrecord_body_datetime_setter_getter(config, syslog_ng): # does not distinguish int_value and datetime. assert file_true.get_stats()["processed"] == 1 assert "processed" not in file_false.get_stats() - assert file_true.read_log() == "1701353998123000\n" + assert file_true.read_log() == "1701346798123000\n" def test_otel_logrecord_body_bytes_setter_getter(config, syslog_ng):