[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gpsd-dev] [PATCH] Add Windows versions of time related functions.
From: |
Rob Norris |
Subject: |
[gpsd-dev] [PATCH] Add Windows versions of time related functions. |
Date: |
Fri, 18 Mar 2016 23:53:40 +0000 |
strptime() is not part of the Windows C runtime,
thus add a minimal implementation that converts iso8601 strings only
(rather than a full version of strptime() from e.g. FreeBSD that handles all
formats).
gmtime_r() is gmtime_s() on Windows with the parameter order reversed.
TESTED:
Forced the alternative strptime() implementation under Linux and scons
build-all check passes.
[Note that iso8601_to_unix is called from at least 'test_json'.]
gpsutils.c builds for Windows via cross compilation.
---
SConstruct | 2 +-
gpsutils.c | 27 ++++++++++++++++++++++++---
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/SConstruct b/SConstruct
index 3eb7045..7bc2a34 100644
--- a/SConstruct
+++ b/SConstruct
@@ -705,7 +705,7 @@ else:
# check function after libraries, because some function require libraries
# for example clock_gettime() require librt on Linux glibc < 2.17
- for f in ("daemon", "strlcpy", "strlcat", "clock_gettime"):
+ for f in ("daemon", "strlcpy", "strlcat", "clock_gettime", "strptime",
"gmtime_r" ):
if config.CheckFunc(f):
confdefs.append("#define HAVE_%s 1\n" % f.upper())
else:
diff --git a/gpsutils.c b/gpsutils.c
index 3add68b..7d78388 100644
--- a/gpsutils.c
+++ b/gpsutils.c
@@ -336,15 +336,31 @@ timestamp_t iso8601_to_unix(char *isotime)
#ifndef __clang_analyzer__
#ifndef USE_QT
char *dp = NULL;
- double usec;
+ double usec = 0;
struct tm tm;
memset(&tm,0,sizeof(tm));
+#ifdef HAVE_STRPTIME
dp = strptime(isotime, "%Y-%m-%dT%H:%M:%S", &tm);
+#else
+ /* Fallback for systems without strptime (i.e. Windows)
+ This is simplistic conversion for iso8601 strings only,
+ rather than embedding a full copy of strptime() that handles all
formats */
+ unsigned int year, mon, mday, hour, min;
+ double sec;
+ if (sscanf(isotime, "%u-%u-%uT%u:%u:%lf", &year, &mon, &mday, &hour, &min,
&sec) == 6) {
+ tm.tm_year = year - 1900; // Adjust to tm year
+ tm.tm_mon = mon - 1; // Month indexing starts from zero
+ tm.tm_mday = mday;
+ tm.tm_hour = hour;
+ tm.tm_min = min;
+ tm.tm_sec = (unsigned int)sec; // Truncate to get integer value
+ (void)mktime(&tm); // Normalizes tm so that tm_yday is set
+ usec = sec - (unsigned int)sec; // Get the fractional part (if any)
+ }
+#endif
if (dp != NULL && *dp == '.')
usec = strtod(dp, NULL);
- else
- usec = 0;
/*
* It would be nice if we could say mktime(&tm) - timezone + usec instead,
* but timezone is not available at all on some BSDs. Besides, when working
@@ -380,7 +396,12 @@ char *unix_to_iso8601(timestamp_t fixtime, /*@ out @*/
fractional = modf(fixtime, &integral);
intfixtime = (time_t) integral;
+#ifdef HAVE_GMTIME_R
(void)gmtime_r(&intfixtime, &when);
+#else
+ /* Fallback to try with gmtime_s - primarily for Windows */
+ (void)gmtime_s(&when, &intfixtime);
+#endif
(void)strftime(timestr, sizeof(timestr), "%Y-%m-%dT%H:%M:%S", &when);
/*
--
2.7.0
- [gpsd-dev] [PATCH] Add Windows versions of time related functions.,
Rob Norris <=