Index: changes.md ================================================================== --- changes.md +++ changes.md @@ -8,11 +8,10 @@ ## Changes since Tcl 9.0.0 - [zlib-8.8, zlib-8.16 fail on Fedora 40, gcc 14.1.1](https://core.tcl-lang.org/tcl/tktview/73d5cb) - [regression in tzdata, %z instead of offset TZ-name](https://core.tcl-lang.org/tcl/tktview/2c237b) - [Tcl will not start properly if there is an init.tcl file in the current dir](https://core.tcl-lang.org/tcl/tktview/43c94f) - - [clock scan of leapsecond: wrong result](https://core.tcl-lang.org/tcl/tktview/f2b5f8) - [clock scan "24:00", ISO-8601 compatibility](https://core.tcl-lang.org/tcl/tktview/aee9f2) - [install registry and dde in $INSTALL_DIR\lib always](https://core.tcl-lang.org/tcl/tktview/364bd9) - [cannot build .chm help file (Windows)](https://core.tcl-lang.org/tcl/tktview/bb110c) - [TIP 701 - Tcl_FSTildeExpand C API](https://core.tcl-lang.org/tips/doc/trunk/tip/701.md) - [buffer overwrite for non-BMP characters in utf-16](https://core.tcl-lang.org/tcl/tktview/66da4d) Index: doc/clock.n ================================================================== --- doc/clock.n +++ doc/clock.n @@ -919,11 +919,12 @@ A time of day, which is of the form: .QW "\fIhh\fR?\fB:\fImm\fR?\fB:\fIss\fR?? ?\fImeridian\fR? ?\fIzone\fR?" or .QW "\fBhhmm \fR?\fBmeridian\fR? ?\fBzone\fR?" . If no \fImeridian\fR is specified, \fIhh\fR is interpreted on -a 24-hour clock. +a 24-hour clock. The "24:00" and "24:00:00" formats (with or without +colon) are supported only if no \fImeridian\fR is specified. .TP \fIdate\fR . A specific month and day with optional year. The acceptable formats are @@ -949,11 +950,13 @@ .QW "\fICCyymmdd\fBT\fIhh:mm:ss\fR" , or .QW "\fICCyy-mm-dd\fBT\fIhh:mm:ss\fR" . Note that only these four formats are accepted. The command does \fInot\fR accept the full range of point-in-time -specifications specified in ISO8601. Other formats can be recognized by +specifications specified in ISO8601. For example, leap seconds are +not supported. The "24:00" and "24:00:00" formats (with or without +colon) are supported. Other formats can be recognized by giving an explicit \fB\-format\fR option to the \fBclock scan\fR command. .TP \fIrelative time\fR . A specification relative to the current time. The format is \fBnumber Index: generic/tclClock.c ================================================================== --- generic/tclClock.c +++ generic/tclClock.c @@ -3783,11 +3783,10 @@ int stage) /* Stage to validate (1, 2 or 3 for both) */ { const char *errMsg = "", *errCode = ""; TclDateFields temp; int tempCpyFlg = 0; - int leapDay = -1; ClockClientData *dataPtr = opts->dataPtr; #if 0 printf("yyMonth %d, yyDay %d, yyDayOfYear %d, yyHour %d, yyMinutes %d, yySeconds %" TCL_LL_MODIFIER "d, " "yySecondOfDay %" TCL_LL_MODIFIER "d, sec %" TCL_LL_MODIFIER "d, daySec %" TCL_LL_MODIFIER "d, tzOffset %d\n", @@ -3808,24 +3807,18 @@ || yydate.iso8601Year > dataPtr->validMaxYear) { errMsg = "invalid iso year"; errCode = "iso year"; goto error; } - if ((yydate.iso8601Year < 1972) || (yydate.iso8601Year > 2017)) { - leapDay = 0; - } } if (info->flags & CLF_YEAR) { if (yyYear < dataPtr->validMinYear || yyYear > dataPtr->validMaxYear) { errMsg = "invalid year"; errCode = "year"; goto error; } - if ((yyYear < 1972) || (yyYear > 2017)) { - leapDay = 0; - } } else if ((info->flags & CLF_ISO8601YEAR)) { yyYear = yydate.iso8601Year; /* used to recognize leap */ } if ((info->flags & (CLF_ISO8601YEAR | CLF_YEAR)) == (CLF_ISO8601YEAR | CLF_YEAR)) { @@ -3840,36 +3833,18 @@ if (info->flags & CLF_MONTH) { if (yyMonth < 1 || yyMonth > 12) { errMsg = "invalid month"; errCode = "month"; goto error; - } else if (leapDay) { - switch (yyMonth) { - case 6: - leapDay = 30; - break; - case 12: - leapDay = 31; - break; - case 1: - case 7: - leapDay = 1; - break; - default: - leapDay = 0; - break; - } } } /* day of month */ if (info->flags & (CLF_DAYOFMONTH|CLF_DAYOFWEEK)) { if (yyDay < 1 || yyDay > 31) { errMsg = "invalid day"; errCode = "day"; goto error; - } else if ((leapDay > 0) && (info->flags & CLF_DAYOFMONTH) && (yyDay != leapDay)) { - leapDay = 0; } if ((info->flags & CLF_MONTH)) { const int *h = hath[IsGregorianLeapYear(&yydate)]; if (yyDay > h[yyMonth - 1]) { @@ -3907,23 +3882,19 @@ /* hour */ if (yyHour < 0 || yyHour > ((yyMeridian == MER24) ? 24 : 12)) { errMsg = "invalid time (hour)"; errCode = "hour"; goto error; - } else if (yyHour == 24) { - leapDay = 0; } /* minutes */ if (yyMinutes < 0 || yyMinutes > 59 || (yyMinutes && (yyHour == 24))) { errMsg = "invalid time (minutes)"; errCode = "minutes"; goto error; - } else if ((yyMinutes % 15) != 14) { - leapDay = 0; } /* oldscan could return secondOfDay (parsedTime) -1 by invalid time (ex.: 25:00:00) */ - if (yySeconds < 0 || yySeconds > (leapDay ? 60 : 59) || yySecondOfDay <= -1 || (yySeconds && (yyHour == 24))) { + if (yySeconds < 0 || yySeconds > 59 || yySecondOfDay <= -1 || (yySeconds && (yyHour == 24))) { errMsg = "invalid time"; errCode = "seconds"; goto error; } } Index: tests/clock.test ================================================================== --- tests/clock.test +++ tests/clock.test @@ -38459,13 +38459,12 @@ set res; # must be empty } -result {} test clock-68.1a {Leap second, minute, hour [f2b5f89c0d], regression test (validity check)} -body { set res {} foreach {d i} { - "2012-06-30 23:59:60" 1341100800 "2012-06-30 24:00:00" 1341100800 - } { + } { # check with free scan: if {[set t [clock scan $d -gmt 1]] != $i} { lappend res "free-scan \"$d\" == $t, expected $i" } # check with formatted scan: @@ -38473,23 +38472,23 @@ lappend res "fmt-scan \"$d\" == $t, expected $i" } } set res; # must be empty } -result {} -test clock-68.2 {Leap second, minute, hour [f2b5f89c0d], regression test (validity check)} -constraints !valid_off -body { - # regardless solution for [f2b5f89c0d], this conversions must fail on -valid 1 (constraints !valid_off), - # because of wrong day and month for the leap second. There were only leap seconds from 1972 - 2016: +test clock-68.2 {Leap second, "24:00", regression test (validity check)} -constraints !valid_off -body { + # Leap seconds are not supported. "24:00" is supported. set res {} foreach {d i} { "2012-06-29 23:59:60" "invalid time" "2012-05-30 23:59:60" "invalid time" "2012-05-30 23:60:60" "invalid time" "2012-05-30 24:00:01" "invalid time" "2012-05-30 24:01:00" "invalid time" "1971-06-30 23:59:60" "invalid time" + "2012-06-30 23:59:60" "invalid time" "2018-06-30 23:59:60" "invalid time" - } { + } { # check with free scan: if {![catch { clock scan $d -gmt 1 } t] || ![string match *$i* $t]} { lappend res "free-scan \"$d\" == \"$t\", expected \"$i\"" } # check with formatted scan: