aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Chemeris <Alexander.Chemeris@gmail.com>2014-03-07 21:03:44 +0100
committerAlexander Chemeris <Alexander.Chemeris@gmail.com>2014-03-16 15:08:54 +0400
commitb9a9418b66d2d06e4023453c5a56dc8ea1e96677 (patch)
tree1cc83a4f2893479aab14b9515d208f8bb02c19f3
parent7fb5e2de4b8a582cbfd9ab1f00e0db1402145fc3 (diff)
sms: Fix gsm340_scts() to correctly decode absolute valid times.achemeris/sms-validity
- Support negative timezone offsets decoding. - Correctly account timezone offset and artificial offset mktime() introduces.
-rw-r--r--src/gsm/gsm0411_utils.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/src/gsm/gsm0411_utils.c b/src/gsm/gsm0411_utils.c
index bb59a10..197f2c3 100644
--- a/src/gsm/gsm0411_utils.c
+++ b/src/gsm/gsm0411_utils.c
@@ -100,11 +100,13 @@ void gsm340_gen_scts(uint8_t *scts, time_t time)
time_t gsm340_scts(uint8_t *scts)
{
struct tm tm;
- uint8_t yr = gsm411_unbcdify(*scts++);
+ uint8_t yr, tz;
int ofs;
+ time_t timestamp;
memset(&tm, 0x00, sizeof(struct tm));
+ yr = gsm411_unbcdify(*scts++);
if (yr <= 80)
tm.tm_year = 100 + yr;
else
@@ -114,15 +116,32 @@ time_t gsm340_scts(uint8_t *scts)
tm.tm_hour = gsm411_unbcdify(*scts++);
tm.tm_min = gsm411_unbcdify(*scts++);
tm.tm_sec = gsm411_unbcdify(*scts++);
-#ifdef HAVE_TM_GMTOFF_IN_TM
- tm.tm_gmtoff = gsm411_unbcdify(*scts++) * 15*60;
-#endif
/* according to gsm 03.40 time zone is
"expressed in quarters of an hour" */
- ofs = gsm411_unbcdify(*scts++) * 15*60;
+ tz = *scts++;
+ ofs = gsm411_unbcdify(tz&0x7f) * 15*60;
+ if (tz&0x80)
+ ofs = -ofs;
+ /* mktime() doesn't take tm.tm_gmtoff into account. Instead, it fills this
+ * field with the current timezone. Which means that the resulting time is
+ * off by several hours after that. So here we're setting tm.tm_isdt to -1
+ * to indicate that the tm time is local, but later we subtract the
+ * offset introduced by mktime. */
+ tm.tm_isdst = -1;
+
+ timestamp = mktime(&tm);
+ if (timestamp < 0)
+ return -1;
+
+ /* Take into account timezone offset */
+ timestamp -= ofs;
+#ifdef HAVE_TM_GMTOFF_IN_TM
+ /* Remove an artificial timezone offset, introduced by mktime() */
+ timestamp += tm.tm_gmtoff;
+#endif
- return mktime(&tm) - ofs;
+ return timestamp;
}
/* Decode validity period format 'relative'.