Allow building on platforms without `struct tm.tm_gmtoff`, `timezone`, `daylight`
I'm not happy about this because the results are non-intuitive, but that
looks like something which originates in libyang's attempts to use local
TZ everywhere instead of normalizing to UTC time.
But hey, this only matters on a platform which cannot "easily" represent
timezones in `struct tm`, or for which we cannot determine the TZ/DST
status without going the extra mile of writing non-POSIX stuff. So as
long as we mark the returned value with "I cannot really vouch for the
TZ", this *might* even be standard-compliant.
diff --git a/CMakeModules/UseCompat.cmake b/CMakeModules/UseCompat.cmake
index 7d7a338..a3be828 100644
--- a/CMakeModules/UseCompat.cmake
+++ b/CMakeModules/UseCompat.cmake
@@ -47,6 +47,10 @@
check_include_file("stdatomic.h" HAVE_STDATOMIC)
+ include(CheckStructHasMember)
+ check_struct_has_member("struct tm" tm_gmtoff time.h HAVE_TM_GMTOFF)
+ check_symbol_exists(timezone time.h HAVE_TIME_H_TIMEZONE)
+
unset(CMAKE_REQUIRED_DEFINITIONS)
unset(CMAKE_REQUIRED_LIBRARIES)
diff --git a/compat/compat.h.in b/compat/compat.h.in
index 9383f2d..8ff7c89 100644
--- a/compat/compat.h.in
+++ b/compat/compat.h.in
@@ -58,6 +58,8 @@
#cmakedefine HAVE_STRCHRNUL
#cmakedefine HAVE_GET_CURRENT_DIR_NAME
#cmakedefine HAVE_PTHREAD_MUTEX_TIMEDLOCK
+#cmakedefine HAVE_TM_GMTOFF
+#cmakedefine HAVE_TIME_H_TIMEZONE
#ifndef bswap64
#define bswap64(val) \
diff --git a/src/plugins_types/date_and_time.c b/src/plugins_types/date_and_time.c
index 62e304c..627869b 100644
--- a/src/plugins_types/date_and_time.c
+++ b/src/plugins_types/date_and_time.c
@@ -115,6 +115,7 @@
ret = ly_time_str2time(value, &val->time, &val->fractions_s);
LY_CHECK_GOTO(ret, cleanup);
+#ifdef HAVE_TIME_H_TIMEZONE
if (!strncmp(((char *)value + value_len) - 6, "-00:00", 6)) {
/* unknown timezone, move the timestamp to UTC */
tzset();
@@ -136,6 +137,10 @@
}
}
}
+#else
+ (void)tm;
+ val->unknown_tz = 1;
+#endif
if (format == LY_VALUE_CANON) {
/* store canonical value */
diff --git a/src/tree_data_helpers.c b/src/tree_data_helpers.c
index 714b1fd..94b5fd1 100644
--- a/src/tree_data_helpers.c
+++ b/src/tree_data_helpers.c
@@ -934,6 +934,7 @@
return LY_ESYS;
}
+#ifdef HAVE_TM_GMTOFF
/* get timezone offset */
if (tm.tm_gmtoff == 0) {
/* time is Zulu (UTC) */
@@ -945,6 +946,11 @@
zonediff_m = tm.tm_gmtoff / 60 % 60;
}
sprintf(zoneshift, "%+03d:%02d", zonediff_h, zonediff_m);
+#else
+ (void)zonediff_h;
+ (void)zonediff_m;
+ sprintf(zoneshift, "-00:00");
+#endif
/* print */
if (asprintf(str, "%04d-%02d-%02dT%02d:%02d:%02d%s%s%s",
diff --git a/tests/utests/types/yang_types.c b/tests/utests/types/yang_types.c
index 2ed427c..567df72 100644
--- a/tests/utests/types/yang_types.c
+++ b/tests/utests/types/yang_types.c
@@ -18,6 +18,7 @@
#include <stdlib.h>
+#include "compat.h"
#include "libyang.h"
#define MODULE_CREATE_YIN(MOD_NAME, NODES) \
@@ -90,6 +91,7 @@
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
/* date-and-time */
+#if defined (HAVE_TM_GMTOFF) && defined (HAVE_TIME_H_TIMEZONE)
TEST_SUCCESS_XML("a", "l", "2005-05-25T23:15:15.88888Z", STRING, "2005-05-25T21:15:15.88888-02:00");
TEST_SUCCESS_XML("a", "l", "2005-05-31T23:15:15-08:59", STRING, "2005-06-01T06:14:15-02:00");
TEST_SUCCESS_XML("a", "l", "2005-05-31T23:15:15-23:00", STRING, "2005-06-01T20:15:15-02:00");
@@ -104,6 +106,12 @@
/* unknown timezone */
TEST_SUCCESS_XML("a", "l", "2017-02-01T00:00:00-00:00", STRING, "2017-02-01T00:00:00-00:00");
TEST_SUCCESS_XML("a", "l", "2021-02-29T00:00:00-00:00", STRING, "2021-03-01T00:00:00-00:00");
+#else
+ /* Tests run with a TZ offset of +02:00.
+ * Strictly speaking, this result is "not wrong" because we're indeed saying "unspecified TZ". */
+ TEST_SUCCESS_XML("a", "l", "2005-05-25T23:15:15.88888Z", STRING, "2005-05-25T21:15:15.88888-00:00");
+ TEST_SUCCESS_XML("a", "l", "2005-05-25T23:15:15.88888+04:30", STRING, "2005-05-25T16:45:15.88888-00:00");
+#endif
TEST_ERROR_XML("a", "l", "2005-05-31T23:15:15.-08:00");
CHECK_LOG_CTX("Unsatisfied pattern - \"2005-05-31T23:15:15.-08:00\" does not conform to "