From 4ebbaef8404e925f59962ed15eca6d8b65ea8375 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Thu, 16 May 2019 14:59:07 +0200 Subject: [PATCH 1/5] add minmea_getdate() The GPS date is internally converted to a struct tm anyway. Add a function to make use of this for external users too. --- minmea.c | 30 +++++++++++++++++++----------- minmea.h | 5 +++++ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/minmea.c b/minmea.c index 32f7881..26e8ae3 100644 --- a/minmea.c +++ b/minmea.c @@ -612,25 +612,33 @@ bool minmea_parse_zda(struct minmea_sentence_zda *frame, const char *sentence) return true; } -int minmea_gettime(struct timespec *ts, const struct minmea_date *date, const struct minmea_time *time_) +int minmea_getdate(struct tm *out, const struct minmea_date *date, const struct minmea_time *time_) { if (date->year == -1 || time_->hours == -1) return -1; - struct tm tm; - memset(&tm, 0, sizeof(tm)); + memset(out, 0, sizeof(struct tm)); if (date->year < 80) { - tm.tm_year = 2000 + date->year - 1900; // 2000-2079 + out->tm_year = 2000 + date->year - 1900; // 2000-2079 } else if (date->year >= 1900) { - tm.tm_year = date->year - 1900; // 4 digit year, use directly + out->tm_year = date->year - 1900; // 4 digit year, use directly } else { - tm.tm_year = date->year; // 1980-1999 + out->tm_year = date->year; // 1980-1999 } - tm.tm_mon = date->month - 1; - tm.tm_mday = date->day; - tm.tm_hour = time_->hours; - tm.tm_min = time_->minutes; - tm.tm_sec = time_->seconds; + out->tm_mon = date->month - 1; + out->tm_mday = date->day; + out->tm_hour = time_->hours; + out->tm_min = time_->minutes; + out->tm_sec = time_->seconds; + + return 0; +} + +int minmea_gettime(struct timespec *ts, const struct minmea_date *date, const struct minmea_time *time_) +{ + struct tm tm; + if (minmea_getdate(&tm, date, time_)) + return -1; time_t timestamp = timegm(&tm); /* See README.md if your system lacks timegm(). */ if (timestamp != (time_t)-1) { diff --git a/minmea.h b/minmea.h index 181d8c7..9084a37 100644 --- a/minmea.h +++ b/minmea.h @@ -208,6 +208,11 @@ bool minmea_parse_gsv(struct minmea_sentence_gsv *frame, const char *sentence); bool minmea_parse_vtg(struct minmea_sentence_vtg *frame, const char *sentence); bool minmea_parse_zda(struct minmea_sentence_zda *frame, const char *sentence); +/** + * Convert GPS UTC date/time representation to a UNIX calendar time. + */ +int minmea_getdate(struct tm *out, const struct minmea_date *date, const struct minmea_time *time_); + /** * Convert GPS UTC date/time representation to a UNIX timestamp. */ From f2bd34c82a9873f1f783212c6c2e9bfea9029fb7 Mon Sep 17 00:00:00 2001 From: Kosma Moczek Date: Fri, 3 Jun 2022 00:53:40 +0200 Subject: [PATCH 2/5] minmea_getdate: use pointer dereferencing for memset (safer) --- minmea.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minmea.c b/minmea.c index 26e8ae3..4a3dbbd 100644 --- a/minmea.c +++ b/minmea.c @@ -617,7 +617,7 @@ int minmea_getdate(struct tm *out, const struct minmea_date *date, const struct if (date->year == -1 || time_->hours == -1) return -1; - memset(out, 0, sizeof(struct tm)); + memset(out, 0, sizeof(*out)); if (date->year < 80) { out->tm_year = 2000 + date->year - 1900; // 2000-2079 } else if (date->year >= 1900) { From 8e243e53102e7aad8da9c5c971fd2e10d5113397 Mon Sep 17 00:00:00 2001 From: Kosma Moczek Date: Fri, 3 Jun 2022 00:54:00 +0200 Subject: [PATCH 3/5] minmea_getdate: consistent argument naming --- minmea.c | 20 ++++++++++---------- minmea.h | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/minmea.c b/minmea.c index 4a3dbbd..d6c50db 100644 --- a/minmea.c +++ b/minmea.c @@ -612,24 +612,24 @@ bool minmea_parse_zda(struct minmea_sentence_zda *frame, const char *sentence) return true; } -int minmea_getdate(struct tm *out, const struct minmea_date *date, const struct minmea_time *time_) +int minmea_getdate(struct tm *tm, const struct minmea_date *date, const struct minmea_time *time_) { if (date->year == -1 || time_->hours == -1) return -1; - memset(out, 0, sizeof(*out)); + memset(tm, 0, sizeof(*tm)); if (date->year < 80) { - out->tm_year = 2000 + date->year - 1900; // 2000-2079 + tm->tm_year = 2000 + date->year - 1900; // 2000-2079 } else if (date->year >= 1900) { - out->tm_year = date->year - 1900; // 4 digit year, use directly + tm->tm_year = date->year - 1900; // 4 digit year, use directly } else { - out->tm_year = date->year; // 1980-1999 + tm->tm_year = date->year; // 1980-1999 } - out->tm_mon = date->month - 1; - out->tm_mday = date->day; - out->tm_hour = time_->hours; - out->tm_min = time_->minutes; - out->tm_sec = time_->seconds; + tm->tm_mon = date->month - 1; + tm->tm_mday = date->day; + tm->tm_hour = time_->hours; + tm->tm_min = time_->minutes; + tm->tm_sec = time_->seconds; return 0; } diff --git a/minmea.h b/minmea.h index 9084a37..1e01bad 100644 --- a/minmea.h +++ b/minmea.h @@ -211,7 +211,7 @@ bool minmea_parse_zda(struct minmea_sentence_zda *frame, const char *sentence); /** * Convert GPS UTC date/time representation to a UNIX calendar time. */ -int minmea_getdate(struct tm *out, const struct minmea_date *date, const struct minmea_time *time_); +int minmea_getdate(struct tm *tm, const struct minmea_date *date, const struct minmea_time *time_); /** * Convert GPS UTC date/time representation to a UNIX timestamp. From 77d5410c68e8c59645543b72ddad7fc29f1e03b4 Mon Sep 17 00:00:00 2001 From: Kosma Moczek Date: Fri, 3 Jun 2022 01:01:53 +0200 Subject: [PATCH 4/5] rename minmea_getdate -> minmea_getdatetime --- minmea.c | 4 ++-- minmea.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/minmea.c b/minmea.c index d6c50db..f18d8ae 100644 --- a/minmea.c +++ b/minmea.c @@ -612,7 +612,7 @@ bool minmea_parse_zda(struct minmea_sentence_zda *frame, const char *sentence) return true; } -int minmea_getdate(struct tm *tm, const struct minmea_date *date, const struct minmea_time *time_) +int minmea_getdatetime(struct tm *tm, const struct minmea_date *date, const struct minmea_time *time_) { if (date->year == -1 || time_->hours == -1) return -1; @@ -637,7 +637,7 @@ int minmea_getdate(struct tm *tm, const struct minmea_date *date, const struct m int minmea_gettime(struct timespec *ts, const struct minmea_date *date, const struct minmea_time *time_) { struct tm tm; - if (minmea_getdate(&tm, date, time_)) + if (minmea_getdatetime(&tm, date, time_)) return -1; time_t timestamp = timegm(&tm); /* See README.md if your system lacks timegm(). */ diff --git a/minmea.h b/minmea.h index 1e01bad..50f3d9d 100644 --- a/minmea.h +++ b/minmea.h @@ -211,7 +211,7 @@ bool minmea_parse_zda(struct minmea_sentence_zda *frame, const char *sentence); /** * Convert GPS UTC date/time representation to a UNIX calendar time. */ -int minmea_getdate(struct tm *tm, const struct minmea_date *date, const struct minmea_time *time_); +int minmea_getdatetime(struct tm *tm, const struct minmea_date *date, const struct minmea_time *time_); /** * Convert GPS UTC date/time representation to a UNIX timestamp. From 926077436a3ebf61bdd9187d41b273c67f62a2fa Mon Sep 17 00:00:00 2001 From: Kosma Moczek Date: Fri, 3 Jun 2022 01:10:22 +0200 Subject: [PATCH 5/5] tests: add tests for minmea_getdatetime --- tests.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests.c b/tests.c index c2ae730..2abe493 100644 --- a/tests.c +++ b/tests.c @@ -945,50 +945,76 @@ START_TEST(test_minmea_gettime) { struct minmea_date d = { 14, 2, 14 }; struct minmea_time t = { 13, 0, 9, 123456 }; + struct tm tm; struct timespec ts; + ck_assert(minmea_getdatetime(&tm, &d, &t) == 0); ck_assert(minmea_gettime(&ts, &d, &t) == 0); + ck_assert_int_eq(tm.tm_year, 2014-1900); + ck_assert_int_eq(tm.tm_mon, 1); + ck_assert_int_eq(tm.tm_mday, 14); + ck_assert_int_eq(tm.tm_hour, 13); + ck_assert_int_eq(tm.tm_min, 0); + ck_assert_int_eq(tm.tm_sec, 9); ck_assert_int_eq(ts.tv_sec, 1392382809); ck_assert_int_eq(ts.tv_nsec, 123456000); d.year = -1; + ck_assert(minmea_getdatetime(&tm, &d, &t) != 0); ck_assert(minmea_gettime(&ts, &d, &t) != 0); d.year = 14; t.hours = -1; + ck_assert(minmea_getdatetime(&tm, &d, &t) != 0); ck_assert(minmea_gettime(&ts, &d, &t) != 0); t.hours = 13; /* two digit year conversions */ d.year = 80; + ck_assert(minmea_getdatetime(&tm, &d, &t) == 0); ck_assert(minmea_gettime(&ts, &d, &t) == 0); + ck_assert_int_eq(tm.tm_year, 1980-1900); ck_assert_int_eq(ts.tv_sec, 319381209); /* 1980 */ d.year = 37; + ck_assert(minmea_getdatetime(&tm, &d, &t) == 0); ck_assert(minmea_gettime(&ts, &d, &t) == 0); + ck_assert_int_eq(tm.tm_year, 2037-1900); ck_assert_int_eq(ts.tv_sec, 2118229209); /* 2037 */ /* skip >= 2038 tests on 32-bit time_t platforms */ if (sizeof(time_t) == sizeof(int64_t)) { d.year = 79; + ck_assert(minmea_getdatetime(&tm, &d, &t) == 0); ck_assert(minmea_gettime(&ts, &d, &t) == 0); + ck_assert_int_eq(tm.tm_year, 2079-1900); ck_assert_int_eq(ts.tv_sec, 3443605209); /* 2079 */ } /* four digit year conversions */ d.year = 1979; + ck_assert(minmea_getdatetime(&tm, &d, &t) == 0); ck_assert(minmea_gettime(&ts, &d, &t) == 0); + ck_assert_int_eq(tm.tm_year, 1979-1900); ck_assert_int_eq(ts.tv_sec, 287845209); d.year = 1980; + ck_assert(minmea_getdatetime(&tm, &d, &t) == 0); ck_assert(minmea_gettime(&ts, &d, &t) == 0); + ck_assert_int_eq(tm.tm_year, 1980-1900); ck_assert_int_eq(ts.tv_sec, 319381209); d.year = 2037; + ck_assert(minmea_getdatetime(&tm, &d, &t) == 0); ck_assert(minmea_gettime(&ts, &d, &t) == 0); + ck_assert_int_eq(tm.tm_year, 2037-1900); ck_assert_int_eq(ts.tv_sec, 2118229209); /* skip >= 2038 tests on 32-bit time_t platforms */ if (sizeof(time_t) == sizeof(int64_t)) { d.year = 2079; + ck_assert(minmea_getdatetime(&tm, &d, &t) == 0); ck_assert(minmea_gettime(&ts, &d, &t) == 0); + ck_assert_int_eq(tm.tm_year, 2079-1900); ck_assert_int_eq(ts.tv_sec, 3443605209); d.year = 2080; + ck_assert(minmea_getdatetime(&tm, &d, &t) == 0); ck_assert(minmea_gettime(&ts, &d, &t) == 0); + ck_assert_int_eq(tm.tm_year, 2080-1900); ck_assert_int_eq(ts.tv_sec, 3475141209); } }