Requested by Brian Inglis in: https://savannah.gnu.org/support/?110644 * lib/parse-datetime.y (parser_control): New member J_zones_seen. (item): New item 'J'. (military_table): Add 'J'. (parse_datetime_body): Set and use J_zones_seen. * tests/test-parse-datetime.c (main): Test "J". --- ChangeLog | 11 +++++++++++ doc/parse-datetime.texi | 2 +- lib/parse-datetime.y | 15 ++++++++++++--- tests/test-parse-datetime.c | 10 ++++++++++ 4 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/ChangeLog b/ChangeLog index 3b1f715527..d86cf0048b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2022-05-17 Paul Eggert <[email protected]> + + parse-datetime: support 'J' military time zone + Requested by Brian Inglis in: + https://savannah.gnu.org/support/?110644 + * lib/parse-datetime.y (parser_control): New member J_zones_seen. + (item): New item 'J'. + (military_table): Add 'J'. + (parse_datetime_body): Set and use J_zones_seen. + * tests/test-parse-datetime.c (main): Test "J". + 2022-05-15 Reuben Thomas <[email protected]> doc: Update regex documentation to match implementation. diff --git a/doc/parse-datetime.texi b/doc/parse-datetime.texi index 575b4d5aea..44305d136c 100644 --- a/doc/parse-datetime.texi +++ b/doc/parse-datetime.texi @@ -304,7 +304,7 @@ Time zone items other than @samp{UTC} and @samp{Z} are obsolescent and are not recommended, because they are ambiguous; for example, @samp{EST} has a different meaning in Australia than in the United States, and @samp{A} has different -meaning as a military time zone than as an obsolescent +meaning as a military time zone than as an obsolete RFC 822 time zone. Instead, it's better to use unambiguous numeric time zone corrections like @samp{-0500}, as described in the previous section. diff --git a/lib/parse-datetime.y b/lib/parse-datetime.y index 7220d05dd7..0903c2003e 100644 --- a/lib/parse-datetime.y +++ b/lib/parse-datetime.y @@ -205,6 +205,7 @@ typedef struct bool rels_seen; idx_t dates_seen; idx_t days_seen; + idx_t J_zones_seen; idx_t local_zones_seen; idx_t dsts_seen; idx_t times_seen; @@ -624,6 +625,11 @@ item: pc->local_zones_seen++; debug_print_current_time (_("local_zone"), pc); } + | 'J' + { + pc->J_zones_seen++; + debug_print_current_time ("J", pc); + } | zone { pc->zones_seen++; @@ -1153,7 +1159,8 @@ static table const time_zone_table[] = RFC 822 got these backwards, but RFC 5322 makes the incorrect treatment optional, so do them the right way here. - Note 'T' is a special case, as it is used as the separator in ISO + 'J' is special, as it is local time. + 'T' is also special, as it is the separator in ISO 8601 date and time of day representation. */ static table const military_table[] = { @@ -1166,6 +1173,7 @@ static table const military_table[] = { "G", tZONE, HOUR ( 7) }, { "H", tZONE, HOUR ( 8) }, { "I", tZONE, HOUR ( 9) }, + { "J", 'J', 0 }, { "K", tZONE, HOUR (10) }, { "L", tZONE, HOUR (11) }, { "M", tZONE, HOUR (12) }, @@ -1816,6 +1824,7 @@ parse_datetime_body (struct timespec *result, char const *p, pc.dates_seen = 0; pc.days_seen = 0; pc.times_seen = 0; + pc.J_zones_seen = 0; pc.local_zones_seen = 0; pc.dsts_seen = 0; pc.zones_seen = 0; @@ -1941,7 +1950,7 @@ parse_datetime_body (struct timespec *result, char const *p, else { if (1 < (pc.times_seen | pc.dates_seen | pc.days_seen | pc.dsts_seen - | (pc.local_zones_seen + pc.zones_seen))) + | (pc.J_zones_seen + pc.local_zones_seen + pc.zones_seen))) { if (debugging (&pc)) { @@ -1953,7 +1962,7 @@ parse_datetime_body (struct timespec *result, char const *p, dbg_printf ("error: seen multiple days parts\n"); if (pc.dsts_seen > 1) dbg_printf ("error: seen multiple daylight-saving parts\n"); - if ((pc.local_zones_seen + pc.zones_seen) > 1) + if ((pc.J_zones_seen + pc.local_zones_seen + pc.zones_seen) > 1) dbg_printf ("error: seen multiple time-zone parts\n"); } goto fail; diff --git a/tests/test-parse-datetime.c b/tests/test-parse-datetime.c index 4310ee8a3d..6dbcb3ac93 100644 --- a/tests/test-parse-datetime.c +++ b/tests/test-parse-datetime.c @@ -151,6 +151,16 @@ main (_GL_UNUSED int argc, char **argv) ASSERT (expected.tv_sec == result.tv_sec && expected.tv_nsec == result.tv_nsec); + /* ISO 8601 extended date and time of day representation, + ' ' separator, 'J' (local) time zone */ + p = "2011-05-01 11:55:18J"; + expected.tv_sec = ref_time - gmtoff; + expected.tv_nsec = 0; + ASSERT (parse_datetime (&result, p, 0)); + LOG (p, expected, result); + ASSERT (expected.tv_sec == result.tv_sec + && expected.tv_nsec == result.tv_nsec); + /* ISO 8601, extended date and time of day representation, 'T' separator, UTC */ -- 2.36.1
