summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2017-01-10 22:40:16 (GMT)
committersebres <sebres@users.sourceforge.net>2017-01-10 22:40:16 (GMT)
commitbc93c0f3ab88c29a0985e463ccd73fafaddddbc9 (patch)
treecca855feaafbb0568d92cc2b06cb9d8116e194c5
parent61be8dc3b8493311781e3fec5575cb85161d16ab (diff)
downloadtcl-bc93c0f3ab88c29a0985e463ccd73fafaddddbc9.zip
tcl-bc93c0f3ab88c29a0985e463ccd73fafaddddbc9.tar.gz
tcl-bc93c0f3ab88c29a0985e463ccd73fafaddddbc9.tar.bz2
min length of %Y token (year with century) is 4, optional tokens possibility (zone), test cases extended
-rw-r--r--generic/tclClockFmt.c40
-rw-r--r--generic/tclDate.h1
-rw-r--r--tests-perf/clock.perf.tcl7
-rw-r--r--tests/clock.test12
4 files changed, 50 insertions, 10 deletions
diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c
index 999f191..9211481 100644
--- a/generic/tclClockFmt.c
+++ b/generic/tclClockFmt.c
@@ -1089,7 +1089,7 @@ static ClockScanTokenMap ScnSTokenMap[] = {
{CTOKT_DIGIT, CLF_YEAR, 0, 1, 2, TclOffset(DateInfo, date.year),
NULL},
/* %Y */
- {CTOKT_DIGIT, CLF_YEAR | CLF_CENTURY, 0, 1, 4, TclOffset(DateInfo, date.year),
+ {CTOKT_DIGIT, CLF_YEAR | CLF_CENTURY, 0, 4, 4, TclOffset(DateInfo, date.year),
NULL},
/* %H %k %I %l */
{CTOKT_DIGIT, CLF_TIME, 0, 1, 2, TclOffset(DateInfo, date.hour),
@@ -1116,7 +1116,7 @@ static ClockScanTokenMap ScnSTokenMap[] = {
{CTOKT_DIGIT, CLF_ISO8601YEAR | CLF_ISO8601, 0, 2, 2, TclOffset(DateInfo, date.iso8601Year),
NULL},
/* %G */
- {CTOKT_DIGIT, CLF_ISO8601YEAR | CLF_ISO8601 | CLF_ISO8601CENTURY, 0, 1, 4, TclOffset(DateInfo, date.iso8601Year),
+ {CTOKT_DIGIT, CLF_ISO8601YEAR | CLF_ISO8601 | CLF_ISO8601CENTURY, 0, 4, 4, TclOffset(DateInfo, date.iso8601Year),
NULL},
/* %V */
{CTOKT_DIGIT, CLF_ISO8601, 0, 1, 2, TclOffset(DateInfo, date.iso8601Week),
@@ -1125,7 +1125,7 @@ static ClockScanTokenMap ScnSTokenMap[] = {
{CTOKT_PARSER, CLF_ISO8601, 0, 0, 0, 0,
ClockScnToken_DayOfWeek_Proc, NULL},
/* %z %Z */
- {CTOKT_PARSER, 0, 0, 0, 0, 0,
+ {CTOKT_PARSER, CLF_OPTIONAL, 0, 0, 0, 0,
ClockScnToken_TimeZone_Proc, NULL},
/* %s */
{CTOKT_DIGIT, CLF_LOCALSEC | CLF_SIGNED, 0, 1, 0xffff, TclOffset(DateInfo, date.localSeconds),
@@ -1508,6 +1508,10 @@ ClockScan(
}
}
yyInput = p;
+ /* end of input string */
+ if (p >= end) {
+ break;
+ }
switch (map->type)
{
case CTOKT_DIGIT:
@@ -1553,6 +1557,10 @@ ClockScan(
size = p - yyInput;
if (size < map->minSize) {
/* missing input -> error */
+ if ((map->flags & CLF_OPTIONAL)) {
+ yyInput = p;
+ continue;
+ }
goto not_match;
}
/* string 2 number, put number into info structure by offset */
@@ -1578,6 +1586,10 @@ ClockScan(
case TCL_OK:
break;
case TCL_RETURN:
+ if ((map->flags & CLF_OPTIONAL)) {
+ yyInput = p;
+ continue;
+ }
goto not_match;
break;
default:
@@ -1611,15 +1623,23 @@ ClockScan(
break;
}
}
-
- /* ignore spaces at end */
- while (p < end && isspace(UCHAR(*p))) {
- p++;
- }
/* check end was reached */
if (p < end) {
- /* something after last token - wrong format */
- goto not_match;
+ /* ignore spaces at end */
+ while (p < end && isspace(UCHAR(*p))) {
+ p++;
+ }
+ if (p < end) {
+ /* something after last token - wrong format */
+ goto not_match;
+ }
+ }
+ /* end of string, check only optional tokens at end, otherwise - not match */
+ if (tok->map != NULL) {
+ if ( !(opts->flags & CLF_STRICT) && (tok->map->type == CTOKT_SPACE)
+ || (tok->map->flags & CLF_OPTIONAL)) {
+ goto not_match;
+ }
}
/*
diff --git a/generic/tclDate.h b/generic/tclDate.h
index fe38436..64135d3 100644
--- a/generic/tclDate.h
+++ b/generic/tclDate.h
@@ -30,6 +30,7 @@
#define ONE_YEAR 365 /* days */
+#define CLF_OPTIONAL (1 << 0) /* token is non mandatory */
#define CLF_JULIANDAY (1 << 3)
#define CLF_TIME (1 << 4)
#define CLF_LOCALSEC (1 << 5)
diff --git a/tests-perf/clock.perf.tcl b/tests-perf/clock.perf.tcl
index 3c69414..41cc9e1 100644
--- a/tests-perf/clock.perf.tcl
+++ b/tests-perf/clock.perf.tcl
@@ -150,6 +150,13 @@ proc test-scan {{reptime 1000}} {
# Scan : century, lookup table month and day (list scan: entries with position 12 / 31)
{clock scan {2016 Dec 31} -format {%C%y %b %Od} -locale en -gmt 1}
+ # Scan : ISO date-time (CEST)
+ {clock scan "2009-06-30T18:30:00+02:00" -format "%Y-%m-%dT%H:%M:%S%z"}
+ {clock scan "2009-06-30T18:30:00 CEST" -format "%Y-%m-%dT%H:%M:%S %z"}
+ # Scan : ISO date-time (UTC)
+ {clock scan "2009-06-30T18:30:00Z" -format "%Y-%m-%dT%H:%M:%S%z"}
+ {clock scan "2009-06-30T18:30:00 UTC" -format "%Y-%m-%dT%H:%M:%S %z"}
+
# Scan : dynamic format (cacheable)
{clock scan "25.11.2015 10:35:55" -format [string trim "%d.%m.%Y %H:%M:%S "] -base 0 -gmt 1}
diff --git a/tests/clock.test b/tests/clock.test
index 1d02f39..a4641c6 100644
--- a/tests/clock.test
+++ b/tests/clock.test
@@ -18587,6 +18587,18 @@ test clock-6.16 {input of ambiguous short locale token (%b)} {
} result] $result $errorCode
} {1 {input string does not match supplied format} {CLOCK badInputString}}
+test clock-6.17 {spaces are always optional in non-strict mode (default)} {
+ list [clock scan "2009-06-30T18:30:00+02:00" -format "%Y-%m-%dT%H:%M:%S %z" -gmt 1] \
+ [clock scan "2009-06-30T18:30:00 +02:00" -format "%Y-%m-%dT%H:%M:%S %z" -gmt 1] \
+ [clock scan "2009-06-30T18:30:00Z" -format "%Y-%m-%dT%H:%M:%S %z" -timezone CET] \
+ [clock scan "2009-06-30T18:30:00 Z" -format "%Y-%m-%dT%H:%M:%S %z" -timezone CET]
+} {1246379400 1246379400 1246386600 1246386600}
+
+test clock-6.18 {zone token (%z) is optional} {
+ list [clock scan "2009-06-30T18:30:00 -01:00" -format "%Y-%m-%dT%H:%M:%S %z" -gmt 1] \
+ [clock scan "2009-06-30T18:30:00" -format "%Y-%m-%dT%H:%M:%S %z" -gmt 1] \
+ [clock scan " 2009-06-30T18:30:00 " -format "%Y-%m-%dT%H:%M:%S %z" -gmt 1] \
+} {1246390200 1246386600 1246386600}
test clock-7.1 {Julian Day} {
clock scan 0 -format %J -gmt true