aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Willmann <daniel@totalueberwachung.de>2014-04-16 18:33:15 +0200
committerDaniel Willmann <daniel@totalueberwachung.de>2014-04-16 20:53:37 +0200
commit7d3258046cef22ffbdf14237ce7ca33b74bc0170 (patch)
tree1e85e890e79c447b9153241ef8703e178119df75
parent6dcf22920aed79b06aea8a7bdb68af88aff3a00f (diff)
gsm0411_utils: Implement gsm340_gen_scts without depending on GMTOFF
The helper function time_gmtoff calculates the local<->gmt time difference at the time provided.
-rw-r--r--src/gsm/gsm0411_utils.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/src/gsm/gsm0411_utils.c b/src/gsm/gsm0411_utils.c
index 71973a95..0dd5ff84 100644
--- a/src/gsm/gsm0411_utils.c
+++ b/src/gsm/gsm0411_utils.c
@@ -72,14 +72,43 @@ uint8_t gsm411_unbcdify(uint8_t value)
return ret;
}
+/* Get the local timezone offset from GMT of the unix time provided.
+ * For this the unix time is converted to a struct tm representation once
+ * as localtime and once as UTC. As there are no portable functions to
+ * calculate the differerence of two struct tm convert them both back to
+ * a unix timestamp and calculate the difference. */
+static time_t time_gmtoff(time_t time)
+{
+ struct tm tm_local, tm_utc;
+ time_t ts_local, ts_utc;
+
+ tzset();
+ localtime_r(&time, &tm_local);
+ gmtime_r(&time, &tm_utc);
+
+ /* tm_local is already in local time with DST offset included. For the
+ * conversion back reset DST flag to 0. */
+ tm_local.tm_isdst = 0;
+ tm_utc.tm_isdst = 0;
+ ts_local = mktime(&tm_local);
+ ts_utc = mktime(&tm_utc);
+
+ return ts_local - ts_utc;
+}
+
/* Generate 03.40 TP-SCTS */
void gsm340_gen_scts(uint8_t *scts, time_t time)
{
struct tm tm;
+ int gmt_offset;
+ /* The reentrant function require tzset() to be called */
tzset();
localtime_r(&time, &tm);
+ /* Get the gmt offset */
+ gmt_offset = time_gmtoff(time);
+
*scts++ = gsm411_bcdify(tm.tm_year % 100);
*scts++ = gsm411_bcdify(tm.tm_mon + 1);
*scts++ = gsm411_bcdify(tm.tm_mday);
@@ -87,15 +116,10 @@ void gsm340_gen_scts(uint8_t *scts, time_t time)
*scts++ = gsm411_bcdify(tm.tm_min);
*scts++ = gsm411_bcdify(tm.tm_sec);
-#ifdef HAVE_TM_GMTOFF_IN_TM
- if (tm.tm_gmtoff >= 0)
- *scts++ = gsm411_bcdify(tm.tm_gmtoff/(60*15));
+ if (gmt_offset >= 0)
+ *scts++ = gsm411_bcdify(gmt_offset/(60*15));
else
- *scts++ = gsm411_bcdify(-tm.tm_gmtoff/(60*15)) | 0x08;
-#else
-#warning find a portable way to obtain timezone offset
- *scts++ = 0;
-#endif
+ *scts++ = gsm411_bcdify(-gmt_offset/(60*15)) | 0x08;
}
/* Decode 03.40 TP-SCTS (into utc/gmt timestamp) */