Discussion:
[musl] [PATCH V2] strptime: add support for %z field descriptor (ISO 8601 timezone)
Rafał Miłecki
2018-11-15 15:34:31 UTC
Permalink
From: Rafał Miłecki <***@milecki.pl>

This is glibc extension for parsing ISO 8601 formatted timezone offset.
Supported formats are: ±hh:mm, ±hhmm and ±hh.

While strptime() contains some helpers for parsing (e.g. numeric_range
and numeric_digits) they couldn't be used for %z due to a bigger
complexity of that field (two numbers, optional separator).

Signed-off-by: Rafał Miłecki <***@milecki.pl>
---
I found (when Googling) two people looking for that extension just
like me. One of these questions was asked back in 2015 [0] and the
reply was "it seems to be a reasonable extension" so I thought I'll
give it a try. I hope can consider adding support for that %z
extension.

This is V2 of a patch I sent back in July and that apparently has never
received a review.

I've tested this with libc-test cases added by a recently sent
[PATCH V2 libc-test] add strptime basic test
and it properly handles all 3 tz cases: "+0200", "-0530" and "-06".

[0] http://h206.n179.cust.dataforce.net/lists/musl/2015/08/14/7


V2: Initialize neg variable to 0 to fix parsing positive offsets.
---
src/time/strptime.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)

diff --git a/src/time/strptime.c b/src/time/strptime.c
index c54a0d8c..2aaaa577 100644
--- a/src/time/strptime.c
+++ b/src/time/strptime.c
@@ -154,6 +154,25 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri
adj = 1900;
want_century = 0;
goto numeric_digits;
+ case 'z':
+ neg=0;
+ if (*s == '+') s++;
+ else if (*s == '-') neg=1, s++;
+ else return 0;
+ tm->__tm_gmtoff = 0;
+ for (i=0; i<2 && isdigit(*s); i++)
+ tm->__tm_gmtoff = tm->__tm_gmtoff * 10 + *s++ - '0';
+ if (*s == ':' || isdigit(*s)) {
+ if (*s == ':') s++;
+ for (i=0; i<2 && isdigit(*s); i++)
+ tm->__tm_gmtoff = tm->__tm_gmtoff * 10 + *s++ - '0';
+ } else {
+ tm->__tm_gmtoff *= 100;
+ }
+ tm->__tm_gmtoff = tm->__tm_gmtoff / 100 * 60 + tm->__tm_gmtoff % 100;
+ tm->__tm_gmtoff *= 60;
+ if (neg) tm->__tm_gmtoff = -tm->__tm_gmtoff;
+ break;
case '%':
if (*s++ != '%') return 0;
break;
--
2.13.7
Loading...