summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2024-03-14 20:55:49 (GMT)
committersebres <sebres@users.sourceforge.net>2024-03-14 20:55:49 (GMT)
commitac6aee3987018f33e9455fec6a2fe74f5fc8ee56 (patch)
treefe3868b69ec0406b03f20da581faf7eaedf91956
parent106663837fcd779ecbb5632ce108aa344b64587c (diff)
downloadtcl-ac6aee3987018f33e9455fec6a2fe74f5fc8ee56.zip
tcl-ac6aee3987018f33e9455fec6a2fe74f5fc8ee56.tar.gz
tcl-ac6aee3987018f33e9455fec6a2fe74f5fc8ee56.tar.bz2
validation check: fixed time point of first stage - it must work TZ independently (the conversion of local time to UTC may adjust date/time tokens);
-rw-r--r--generic/tclClock.c26
-rw-r--r--generic/tclDate.h4
-rw-r--r--tests/clock.test139
3 files changed, 99 insertions, 70 deletions
diff --git a/generic/tclClock.c b/generic/tclClock.c
index cd66713..bde903e 100644
--- a/generic/tclClock.c
+++ b/generic/tclClock.c
@@ -3684,6 +3684,20 @@ ClockScanObjCmd(
goto done;
}
+ /*
+ * If no GMT and not free-scan (where valid stage 1 is done in-between),
+ * validate with stage 1 before local time conversion, otherwise it may
+ * adjust date/time tokens to valid values
+ */
+ if ( (opts.flags & CLF_VALIDATE_S1) &&
+ info->flags & (CLF_ASSEMBLE_SECONDS|CLF_LOCALSEC)
+ ) {
+ ret = ClockValidDate(&yy, &opts, CLF_VALIDATE_S1);
+ if (ret != TCL_OK) {
+ goto done;
+ }
+ }
+
/* Convert date info structure into UTC seconds */
ret = ClockScanCommit(&yy, &opts);
@@ -3691,9 +3705,9 @@ ClockScanObjCmd(
goto done;
}
- /* Apply validation rules, if expected */
+ /* Apply remaining validation rules, if expected */
if ( (opts.flags & CLF_VALIDATE) ) {
- ret = ClockValidDate(&yy, &opts, opts.formatObj == NULL ? 2 : 3);
+ ret = ClockValidDate(&yy, &opts, opts.flags & CLF_VALIDATE);
if (ret != TCL_OK) {
goto done;
}
@@ -3819,9 +3833,10 @@ ClockValidDate(
yydate.tzOffset);
#endif
- if (!(stage & 1)) {
+ if (!(stage & CLF_VALIDATE_S1) || !(opts->flags & CLF_VALIDATE_S1)) {
goto stage_2;
}
+ opts->flags &= ~CLF_VALIDATE_S1; /* stage 1 is done */
/* first year (used later in hath / daysInPriorMonths) */
if ((info->flags & (CLF_YEAR|CLF_ISO8601YEAR))) {
@@ -3900,9 +3915,10 @@ ClockValidDate(
}
}
- if (!(stage & 2)) {
+ if (!(stage & CLF_VALIDATE_S2) || !(opts->flags & CLF_VALIDATE_S2)) {
return TCL_OK;
}
+ opts->flags &= ~CLF_VALIDATE_S2; /* stage 2 is done */
/*
* Further tests expected ready calculated julianDay (inclusive relative),
@@ -4047,7 +4063,7 @@ ClockFreeScan(
* relative time (otherwise always valid recalculated date & time).
*/
if ( (opts->flags & CLF_VALIDATE) ) {
- if (ClockValidDate(info, opts, 1) != TCL_OK) {
+ if (ClockValidDate(info, opts, CLF_VALIDATE_S1) != TCL_OK) {
goto done;
}
}
diff --git a/generic/tclDate.h b/generic/tclDate.h
index 3544dee..81910ff 100644
--- a/generic/tclDate.h
+++ b/generic/tclDate.h
@@ -268,7 +268,9 @@ ClockInitDateInfo(DateInfo *info) {
* Structure containing the command arguments supplied to [clock format] and [clock scan]
*/
-#define CLF_VALIDATE (1 << 2)
+#define CLF_VALIDATE_S1 (1 << 0)
+#define CLF_VALIDATE_S2 (1 << 1)
+#define CLF_VALIDATE (CLF_VALIDATE_S1|CLF_VALIDATE_S2)
#define CLF_EXTENDED (1 << 4)
#define CLF_STRICT (1 << 8)
#define CLF_LOCALE_USED (1 << 15)
diff --git a/tests/clock.test b/tests/clock.test
index 5a4b72f..5fbef7b 100644
--- a/tests/clock.test
+++ b/tests/clock.test
@@ -37086,60 +37086,68 @@ test clock-46.6 {freescan: regression test - bad time} -constraints valid_off \
[clock scan "13:00 pm" -base 0 -gmt 1]
} -result {-1 -1}
+proc _invalid_test {args} {
+ global valid_mode
+ # ensure validation works TZ independently, since the conversion
+ # of local time to UTC may adjust date/time tokens, depending on TZ:
+ set res {}
+ foreach tz {:GMT :CET {} :Europe/Berlin :localtime} {
+ foreach {v} $args {
+ if {$valid_mode} { # globally -valid 1
+ lappend res [catch {clock scan $v -timezone $tz} msg] $msg
+ } else {
+ lappend res [catch {clock scan $v -valid 1 -timezone $tz} msg] $msg
+ }
+ }
+ }
+ set res
+}
# test without and with relative offsets:
foreach {idx relstr} {"" "" "+rel" "+ 15 month + 40 days + 30 hours + 80 minutes +9999 seconds"} {
test clock-46.10$idx {freescan: validation rules: invalid time} \
-body {
# 13:00 am/pm are invalid input strings...
- list [catch {clock scan "13:00 am$relstr" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "13:00 pm$relstr" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: invalid time (hour)} 1 {unable to convert input string: invalid time (hour)}}
+ _invalid_test "13:00 am$relstr" "13:00 pm$relstr"
+ } -result [lrepeat 10 1 {unable to convert input string: invalid time (hour)}]
test clock-46.11$idx {freescan: validation rules: invalid time} \
-body {
# invalid minutes in input strings...
- list [catch {clock scan "23:70$relstr" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "11:80 pm$relstr" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: invalid time (minutes)} 1 {unable to convert input string: invalid time (minutes)}}
+ _invalid_test "23:70$relstr" "11:80 pm$relstr"
+ } -result [lrepeat 10 1 {unable to convert input string: invalid time (minutes)}]
test clock-46.12$idx {freescan: validation rules: invalid time} \
-body {
# invalid seconds in input strings...
- list [catch {clock scan "23:00:70$relstr" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "11:00:80 pm$relstr" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: invalid time} 1 {unable to convert input string: invalid time}}
+ _invalid_test "23:00:70$relstr" "11:00:80 pm$relstr"
+ } -result [lrepeat 10 1 {unable to convert input string: invalid time}]
test clock-46.13$idx {freescan: validation rules: invalid day} \
-body {
- list [catch {clock scan "29 Feb 2017$relstr" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "30 Feb 2016$relstr" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: invalid day} 1 {unable to convert input string: invalid day}}
+ _invalid_test "29 Feb 2017$relstr" "30 Feb 2016$relstr"
+ } -result [lrepeat 10 1 {unable to convert input string: invalid day}]
test clock-46.14$idx {freescan: validation rules: invalid day} \
-body {
- list [catch {clock scan "0 Feb 2017$relstr" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "00 Feb 2017$relstr" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: invalid day} 1 {unable to convert input string: invalid day}}
+ _invalid_test "0 Feb 2017$relstr" "00 Feb 2017$relstr"
+ } -result [lrepeat 10 1 {unable to convert input string: invalid day}]
test clock-46.15$idx {freescan: validation rules: invalid month} \
-body {
- list [catch {clock scan "13/13/2017$relstr" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "00/00/2017$relstr" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: invalid month} 1 {unable to convert input string: invalid month}}
+ _invalid_test "13/13/2017$relstr" "00/00/2017$relstr"
+ } -result [lrepeat 10 1 {unable to convert input string: invalid month}]
test clock-46.16$idx {freescan: validation rules: invalid day of week} \
-body {
- list [catch {clock scan "Sat Jan 01 00:00:00 1970$relstr" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "Thu Jan 03 00:00:00 1970$relstr" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: invalid day of week} 1 {unable to convert input string: invalid day of week}}
+ _invalid_test "Sat Jan 02 00:00:00 1970$relstr" "Thu Jan 04 00:00:00 1970$relstr"
+ } -result [lrepeat 10 1 {unable to convert input string: invalid day of week}]
test clock-46.17$idx {scan: validation rules: invalid year} -setup {
set orgcfg [list -min-year [clock configure -min-year] -max-year [clock configure -max-year] \
-year-century [clock configure -year-century] -century-switch [clock configure -century-switch]]
clock configure -min-year 2000 -max-year 2100 -year-century 2000 -century-switch 38
} -body {
- list [catch {clock scan "70-01-01$relstr" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "1870-01-01$relstr" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "9570-01-01$relstr" -valid 1 -gmt 1} msg] $msg \
- } -result [lrepeat 3 1 {unable to convert input string: invalid year}] -cleanup {
+ _invalid_test "70-01-01$relstr" "1870-01-01$relstr" "9570-01-01$relstr"
+ } -result [lrepeat 15 1 {unable to convert input string: invalid year}] -cleanup {
clock configure {*}$orgcfg
unset -nocomplain orgcfg
}
}; # foreach
+rename _invalid_test {}
unset -nocomplain idx relstr
set dst_hole_check {
@@ -37204,60 +37212,66 @@ test clock-46.19-4 {scan: validation rules regression: all scans successful, if
} -result [lrepeat 4 {*}[if {$valid_mode} {list 0 1 1 0 0 0} else {list 0 0 0 0 0 0}]]
unset -nocomplain dst_hole_check
+proc _invalid_test {args} {
+ global valid_mode
+ # ensure validation works TZ independently, since the conversion
+ # of local time to UTC may adjust date/time tokens, depending on TZ:
+ set res {}
+ foreach tz {:GMT :CET {} :Europe/Berlin :localtime} {
+ foreach {v fmt} $args {
+ if {$valid_mode} { # globally -valid 1
+ lappend res [catch {clock scan $v -format $fmt -timezone $tz} msg] $msg
+ } else {
+ lappend res [catch {clock scan $v -format $fmt -valid 1 -timezone $tz} msg] $msg
+ }
+
+ }
+ }
+ set res
+}
test clock-46.20 {scan: validation rules: invalid time} \
-body {
# 13:00 am/pm are invalid input strings...
- list [catch {clock scan "13:00 am" -format "%H:%M %p" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "13:00 pm" -format "%H:%M %p" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: invalid time (hour)} 1 {unable to convert input string: invalid time (hour)}}
+ _invalid_test "13:00 am" "%H:%M %p" "13:00 pm" "%H:%M %p"
+ } -result [lrepeat 10 1 {unable to convert input string: invalid time (hour)}]
test clock-46.21 {scan: validation rules: invalid time} \
-body {
# invalid minutes in input strings...
- list [catch {clock scan "23:70" -format "%H:%M" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "11:80 pm" -format "%H:%M %p" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: invalid time (minutes)} 1 {unable to convert input string: invalid time (minutes)}}
+ _invalid_test "23:70" "%H:%M" "11:80 pm" "%H:%M %p"
+ } -result [lrepeat 10 1 {unable to convert input string: invalid time (minutes)}]
test clock-46.22 {scan: validation rules: invalid time} \
-body {
# invalid seconds in input strings...
- list [catch {clock scan "23:00:70" -format "%H:%M:%S" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "11:00:80 pm" -format "%H:%M:%S %p" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: invalid time} 1 {unable to convert input string: invalid time}}
+ _invalid_test "23:00:70" "%H:%M:%S" "11:00:80 pm" "%H:%M:%S %p"
+ } -result [lrepeat 10 1 {unable to convert input string: invalid time}]
test clock-46.23 {scan: validation rules: invalid day} \
-body {
- list [catch {clock scan "29 Feb 2017" -format "%d %b %Y" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "30 Feb 2016" -format "%d %b %Y" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: invalid day} 1 {unable to convert input string: invalid day}}
+ _invalid_test "29 Feb 2017" "%d %b %Y" "30 Feb 2016" "%d %b %Y"
+ } -result [lrepeat 10 1 {unable to convert input string: invalid day}]
test clock-46.24 {scan: validation rules: invalid day} \
-body {
- list [catch {clock scan "0 Feb 2017" -format "%d %b %Y" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "00 Feb 2017" -format "%d %b %Y" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: invalid day} 1 {unable to convert input string: invalid day}}
+ _invalid_test "0 Feb 2017" "%d %b %Y" "00 Feb 2017" "%d %b %Y"
+ } -result [lrepeat 10 1 {unable to convert input string: invalid day}]
test clock-46.25 {scan: validation rules: invalid month} \
-body {
- list [catch {clock scan "13/13/2017" -format "%m/%d/%Y" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "00/00/2017" -format "%m/%d/%Y" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: invalid month} 1 {unable to convert input string: invalid month}}
+ _invalid_test "13/13/2017" "%m/%d/%Y" "00/01/2017" "%m/%d/%Y"
+ } -result [lrepeat 10 1 {unable to convert input string: invalid month}]
test clock-46.26 {scan: validation rules: ambiguous day} \
-body {
- list [catch {clock scan "1970-01-01--002" -format "%Y-%m-%d--%j" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "70-01-01--002" -format "%y-%m-%d--%j" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: ambiguous day} 1 {unable to convert input string: ambiguous day}}
+ _invalid_test "1970-01-02--004" "%Y-%m-%d--%j" "70-01-02--004" "%y-%m-%d--%j"
+ } -result [lrepeat 10 1 {unable to convert input string: ambiguous day}]
test clock-46.27 {scan: validation rules: ambiguous year} \
-body {
- list [catch {clock scan "19700101 00W014" -format "%Y%m%d %gW%V%u" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "1970001 00W014" -format "%Y%j %gW%V%u" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: ambiguous year} 1 {unable to convert input string: ambiguous year}}
+ _invalid_test "19700106 00W014" "%Y%m%d %gW%V%u" "1970006 00W014" "%Y%j %gW%V%u"
+ } -result [lrepeat 10 1 {unable to convert input string: ambiguous year}]
test clock-46.28 {scan: validation rules: invalid day of week} \
-body {
- list [catch {clock scan "Sat Jan 01 00:00:00 1970" -format "%a %b %d %H:%M:%S %Y" -valid 1 -gmt 1} msg] $msg
- } -result {1 {unable to convert input string: invalid day of week}}
+ _invalid_test "Sat Jan 02 00:00:00 1970" "%a %b %d %H:%M:%S %Y"
+ } -result [lrepeat 5 1 {unable to convert input string: invalid day of week}]
test clock-46.29-1 {scan: validation rules: invalid day of year} \
-body {
- list [catch {clock scan "000-2017" -format "%j-%Y" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "366-2017" -format "%j-%Y" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "000-2017" -format "%j-%G" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "366-2017" -format "%j-%G" -valid 1 -gmt 1} msg] $msg
- } -result [lrepeat 4 1 {unable to convert input string: invalid day of year}]
+ _invalid_test "000-2017" "%j-%Y" "366-2017" "%j-%Y" "000-2017" "%j-%G" "366-2017" "%j-%G"
+ } -result [lrepeat 20 1 {unable to convert input string: invalid day of year}]
test clock-46.29-2 {scan: validation rules: valid day of leap/not leap year} \
-body {
list [clock format [clock scan "366-2016" -format "%j-%Y" -valid 1 -gmt 1] -format "%d-%m-%Y"] \
@@ -37270,10 +37284,8 @@ test clock-46.30 {scan: validation rules: invalid year} -setup {
-year-century [clock configure -year-century] -century-switch [clock configure -century-switch]]
clock configure -min-year 2000 -max-year 2100 -year-century 2000 -century-switch 38
} -body {
- list [catch {clock scan "01-01-70" -format "%d-%m-%y" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "01-01-1870" -format "%d-%m-%C%y" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "01-01-1970" -format "%d-%m-%Y" -valid 1 -gmt 1} msg] $msg \
- } -result [lrepeat 3 1 {unable to convert input string: invalid year}] -cleanup {
+ _invalid_test "01-01-70" "%d-%m-%y" "01-01-1870" "%d-%m-%C%y" "01-01-1970" "%d-%m-%Y"
+ } -result [lrepeat 15 1 {unable to convert input string: invalid year}] -cleanup {
clock configure {*}$orgcfg
unset -nocomplain orgcfg
}
@@ -37282,13 +37294,12 @@ test clock-46.31 {scan: validation rules: invalid iso year} -setup {
-year-century [clock configure -year-century] -century-switch [clock configure -century-switch]]
clock configure -min-year 2000 -max-year 2100 -year-century 2000 -century-switch 38
} -body {
- list [catch {clock scan "01-01-70" -format "%d-%m-%g" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "01-01-9870" -format "%d-%m-%C%g" -valid 1 -gmt 1} msg] $msg \
- [catch {clock scan "01-01-9870" -format "%d-%m-%G" -valid 1 -gmt 1} msg] $msg \
- } -result [lrepeat 3 1 {unable to convert input string: invalid iso year}] -cleanup {
+ _invalid_test "01-01-70" "%d-%m-%g" "01-01-9870" "%d-%m-%C%g" "01-01-9870" "%d-%m-%G"
+ } -result [lrepeat 15 1 {unable to convert input string: invalid iso year}] -cleanup {
clock configure {*}$orgcfg
unset -nocomplain orgcfg
}
+rename _invalid_test {}
test clock-47.1 {regression test - four-digit time} {
clock scan 0012