[Bug Tcl 8.1] incorrect leap year handling in generic/tclDate.c

0 views
Skip to first unread message

Hume Smith

unread,
May 13, 1999, 3:00:00 AM5/13/99
to
scriptic...@auto.genned.post wrote:

> The leap year handling in the Convert() routine in generic/tclDate.c is
> incorrect. Leap years are divisible by 4, unless it's divisible by 100,
> in which case it's a leap year only if it's divisible by 400. Hence
> 2000 is a leap year, but 2100 is not.

cripes... i thought i had sent them a fix for that a year ago :)

Michael L. Siemon

unread,
May 13, 1999, 3:00:00 AM5/13/99
to
In article <926646238....@news.glinx.com>, Hume Smith
<hclsmit...@glinx.delete.com> wrote:

+ scriptic...@auto.genned.post wrote:
+
+ > The leap year handling in the Convert() routine in generic/tclDate.c
+ > is incorrect. <snip accurate statement>

+ cripes... i thought i had sent them a fix for that a year ago :)

Well, it's clearly wrong, but can anyone tell me where it would matter?

I ran a few cases with clock format adding chunks of time to <now> to
step over the 2000 leap year, and got correct output. In what contexts
would this Convert() routine be called from standard TCL commands?
(if it is merely there for C programs to call, they can use a correct
algorithm instead...)
--
Michael L. Siemon We must know the truth, and we must
m...@panix.com love the truth we know, and we must
act according to the measure of our love.
-- Thomas Merton

scriptic...@auto.genned.post

unread,
May 14, 1999, 3:00:00 AM5/14/99
to

Tcl 8.1 Bug: Generated by Scriptics' bug entry form at
http://www.scriptics.com/support/bugForm.html
Responses to this post are encouraged.
------

Submitted by: Isaac Hollander
OperatingSystem: Sun Solaris
Synopsis: incorrect leap year handling in generic/tclDate.c

ReproducibleScript:
This is already reported as bugID 1985, but I can't figure out how to
update an existing bug. Please close out bugID 1985 and use this bug
report.



The leap year handling in the Convert() routine in generic/tclDate.c is
incorrect. Leap years are divisible by 4, unless it's divisible by 100,
in which case it's a leap year only if it's divisible by 400. Hence
2000 is a leap year, but 2100 is not.

The code is incorrect in all versions of tcl I've looked at from 8.0p2
through the latest code in CVS.

Patch:
$ diff -c tclDate.c tclDate.c.orig
*** tclDate.c Thu May 6 17:32:51 1999
--- tclDate.c.orig Mon Feb 10 13:03:15 1997
***************
*** 430,439 ****
Julian += DaysInMonth[i];
if (Year >= EPOCH) {
for (i = EPOCH; i < Year; i++)
! Julian += 365 + ( (i % 4 == 0) && ((i % 100 != 0) || (i % 400 == 0
)) );
} else {
for (i = Year; i < EPOCH; i++)
! Julian -= 365 + ( (i % 4 == 0) && ((i % 100 != 0) || (i % 400 == 0
)) );
}
Julian *= SECSPERDAY;
Julian += TclDateTimezone * 60L;
--- 430,439 ----
Julian += DaysInMonth[i];
if (Year >= EPOCH) {
for (i = EPOCH; i < Year; i++)
! Julian += 365 + (i % 4 == 0);
} else {
for (i = Year; i < EPOCH; i++)
! Julian -= 365 + (i % 4 == 0);
}
Julian *= SECSPERDAY;
Julian += TclDateTimezone * 60L;
$

PatchFiles:
generic/tclDate.c

Comments:
This is a crucial Y2K issue. Scriptics's Y2K statement discusses the 2
digit year issue in great details, but does not address proper leap year
handling.

lvi...@cas.org

unread,
May 14, 1999, 3:00:00 AM5/14/99
to

According to Hume Smith <hclsmit...@glinx.delete.com>:
:cripes... i thought i had sent them a fix for that a year ago :)

I seem to remember you did - check www.deja.com to see. I would hazard
a guess that between the move between 3 or 4 sites it either got lost or
a bug that was fixed got 'unfixed' somewhere along the line...

--
<URL: mailto:lvi...@cas.org> Quote: Saving the world before bedtime.
<*> O- <URL: http://www.purl.org/NET/lvirden/>
Unless explicitly stated to the contrary, nothing in this posting
should be construed as representing my employer's opinions.

lvi...@cas.org

unread,
May 14, 1999, 3:00:00 AM5/14/99
to

According to Michael L. Siemon <m...@panix.com>:
:Well, it's clearly wrong, but can anyone tell me where it would matter?

The main place is that Scriptics has assured its paying customers about
it's 'y2k' compliance and most customers consider correct leap year handling
to be a part of the responsibility of a vendor.

Michael L. Siemon

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
In article <7hg4cn$bm9$1...@srv38s4u.cas.org>, lvi...@cas.org wrote:

+ According to Michael L. Siemon <m...@panix.com>:
+ :Well, it's clearly wrong, but can anyone tell me where it would matter?
+
+ The main place is that Scriptics has assured its paying customers about
+ it's 'y2k' compliance and most customers consider correct leap year handling
+ to be a part of the responsibility of a vendor.

Ummm, I understand that (I have had to assure my management that TCL
was Y2K compliant.) I agree that the function must be fixed or removed.
What I don't understand (and am asking) is _where is it in fact used_ in
core functionality? as I cannot in easy cases generate a 2000-leapyear
error with the commands I would expect to show up the problem.

Scott Redman

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
I applied the patch.

-- Scott Redman

Scott Stanton

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
lvi...@cas.org wrote:
>
> According to Hume Smith <hclsmit...@glinx.delete.com>:
> :cripes... i thought i had sent them a fix for that a year ago :)
>

We'll reapply the patch, although I don't think it will actually affect
anything. The epoch doesn't extend past 2038, so you can't actually process
dates that are within the problem range. This will basically be dead code
until the 2038 issue is resolved.

___________________________________________________________
Scott Stanton 650-210-0105 tel
Sr. Software Engineer 650-210-0101 fax
Scriptics Corporation scott....@scriptics.com
The Tcl Platform Company http://www.scriptics.com

Cary O'Brien

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
Yikes.

tcl>clock scan "Feb 28 2000"
925516800
tcl>clock scan "Feb 29 2000"
Error: unable to convert date-time string "Feb 29 2000"

This is un-good.

-- cary

Gawain Lavers

unread,
May 14, 1999, 3:00:00 AM5/14/99
to

Maybe I'm screwed up about this, and I forget the rule anyway, but I
thought that 2000 would not be a leap year, so this would be right.

Scott Redman

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
It's busted even for "Feb 29 1996". I'm looking into it...

-- Scott

Scott Redman

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
No, 2000 is a leap year (years divisible by 100 are not, unless they
are also divisible by 400).

-- Scott

Gawain Lavers wrote:
>
> Cary O'Brien wrote:
> >
> > Yikes.
> >
> > tcl>clock scan "Feb 28 2000"
> > 925516800
> > tcl>clock scan "Feb 29 2000"
> > Error: unable to convert date-time string "Feb 29 2000"
> >
> > This is un-good.
> >
> > -- cary
>

Gawain Lavers

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
Scott Redman wrote:
>
> No, 2000 is a leap year (years divisible by 100 are not, unless they
> are also divisible by 400).
>
> -- Scott
>

Cool, I'll try to remember it now. I was afraid that it was going to be
another case of me being right and the rest of the world being wrong.

Robert Baptista

unread,
May 14, 1999, 3:00:00 AM5/14/99
to Gawain Lavers
Gee, does that happen often?

Scott Redman

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
Try this:

clock scan "Feb 29 00:00:00 2000"

If you don't put the time-of-day, it uses the date for the
time-of-day instead, and assumes the current year for the year.
Probably needs better documentation?

-- Scott


Scott Redman wrote:
>
> It's busted even for "Feb 29 1996". I'm looking into it...
>
> -- Scott
>

Gordon Johnstone

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
Cary O'Brien wrote:
>
> Yikes.
>
> tcl>clock scan "Feb 28 2000"
> 925516800
> tcl>clock scan "Feb 29 2000"
> Error: unable to convert date-time string "Feb 29 2000"
>
> This is un-good.
>
> -- cary

I see the bug report is only for 8.1. 8.0.4, and 8.0.2 are the same.
Or has someone already mentioned that.

Gordon

gdjohnstone.vcf

Michael L. Siemon

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
In article <mls-140599...@mls.dialup.access.net>, m...@panix.com
(Michael L. Siemon) wrote:

To answer my own question: The bug report is spurious -- there is NO ERROR
in the
algorithm of Convert. As I saw when I looked up the source at work. In fact, the
routine explicitly errors out before START_OF_TIME and after END_OF_TIME, and
in that range (on all platforms) the leap year algorithm is strictly Julian. The
routine does not even NEED the (correct, Gregorian) initialization of the number
of days in February -- but that is a trivial nicety. By using a pure
Julian algorithm
in the loop on years, two expression evaluations per pass are saved, with
no loss
of correctness.

(Note: try "clock scan 3/1/2100" and you will see what I mean -- the
failure case
that the bug report is trying to "fix" is not a possible case.)

Now, when the Y2L38 Bug is addressed, this code will _have_ to be revisited! :-)

Michael L. Siemon

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
In article <7hhohc$63d$1...@saltmine.radix.net>, cob...@Radix.Net (Cary
O'Brien) wrote:

+ Yikes.
+
+ tcl>clock scan "Feb 28 2000"
+ 925516800
+ tcl>clock scan "Feb 29 2000"
+ Error: unable to convert date-time string "Feb 29 2000"
+
+ This is un-good.

It is indeed -- what are you executing? no TCL I have tried
does this.

Scott Redman

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
In order to make an attempt at preventing at least one post-Y2L38 bug,
we're going to apply the patch anyway. If it isn't done now, who
knows when it will be handled?

-- Scott

"Michael L. Siemon" wrote:
>
> In article <mls-140599...@mls.dialup.access.net>, m...@panix.com
> (Michael L. Siemon) wrote:
>
> To answer my own question: The bug report is spurious -- there is NO ERROR
> in the
> algorithm of Convert. As I saw when I looked up the source at work. In fact, the
> routine explicitly errors out before START_OF_TIME and after END_OF_TIME, and
> in that range (on all platforms) the leap year algorithm is strictly Julian. The
> routine does not even NEED the (correct, Gregorian) initialization of the number
> of days in February -- but that is a trivial nicety. By using a pure
> Julian algorithm
> in the loop on years, two expression evaluations per pass are saved, with
> no loss
> of correctness.
>
> (Note: try "clock scan 3/1/2100" and you will see what I mean -- the
> failure case
> that the bug report is trying to "fix" is not a possible case.)
>
> Now, when the Y2L38 Bug is addressed, this code will _have_ to be revisited! :-)

lvi...@cas.org

unread,
May 15, 1999, 3:00:00 AM5/15/99
to

According to Scott Stanton <scott....@Scriptics.com>:
:dates that are within the problem range. This will basically be dead code

:until the 2038 issue is resolved.

At least on Solaris 2.7, the 2038 deadline is solved by time_t being longer
than a long...

Francois GORET

unread,
May 15, 1999, 3:00:00 AM5/15/99
to
Cary O'Brien wrote:

> Yikes.
>


> tcl>clock scan "Feb 28 2000"

> 925516800


> tcl>clock scan "Feb 29 2000"

> Error: unable to convert date-time string "Feb 29 2000"
>

> This is un-good.
>
> -- cary

The correct syntax seems to be:
clock scan "Feb 29, 2000"

Note the coma after the day. If you just say "Feb 29 2000", well TCL
silently ignores the year and try
to convert using the current year. Take a look in the sources at
generic/tclGetDate.y around line
230.
Hope that helps Francois


Gordon Johnstone

unread,
May 17, 1999, 3:00:00 AM5/17/99
to
"Michael L. Siemon" wrote:
>
> In article <7hhohc$63d$1...@saltmine.radix.net>, cob...@Radix.Net (Cary
> O'Brien) wrote:
>
> + Yikes.
> +
> + tcl>clock scan "Feb 28 2000"
> + 925516800
> + tcl>clock scan "Feb 29 2000"
> + Error: unable to convert date-time string "Feb 29 2000"
> +
> + This is un-good.
>
> It is indeed -- what are you executing? no TCL I have tried
> does this.
> --
> Michael L. Siemon We must know the truth, and we must
> m...@panix.com love the truth we know, and we must
> act according to the measure of our love.
> -- Thomas Merton
I get this on Solaris 2.0.5 with tcl 8.0.2, RedHat 2.1 tcl 8.0.2, and NT
tcl 8.0.2 and tcl 8.0.4.

I e-mailed Scriptics to say that their web site y2k page should be
updated to reflect this and Brent Welch mailed back with :-
<extract>
The problem is the lack of a comma between "Feb 29" and "2000".
Try this, which works:


clock scan "Feb 29, 2000"

<extract>

But this is still odd behaviour as other dates don't require this comma.

Gordon

gdjohnstone.vcf

Donal K. Fellows

unread,
May 17, 1999, 3:00:00 AM5/17/99
to
In article <7hhohc$63d$1...@saltmine.radix.net>,
Cary O'Brien <cob...@Radix.Net> wrote:
> Yikes.
> tcl>clock scan "Feb 28 2000"
> 925516800

Which is a time *this* year. Guess what; it is doing something other
than what you think it is doing! Try:
puts [clock format [clock scan "Feb 28 2000"] -gmt 1]
to get something in a canonical *human-readable* form.

Donal.
--
Donal K. Fellows http://www.cs.man.ac.uk/~fellowsd/ fell...@cs.man.ac.uk
-- The small advantage of not having California being part of my country would
be overweighed by having California as a heavily-armed rabid weasel on our
borders. -- David Parsons <o r c @ p e l l . p o r t l a n d . o r . u s>

Volker Hetzer

unread,
May 17, 1999, 3:00:00 AM5/17/99
to
Scott Redman wrote:
>
> Try this:
>
> clock scan "Feb 29 00:00:00 2000"
>
> If you don't put the time-of-day, it uses the date for the
> time-of-day instead, and assumes the current year for the year.
> Probably needs better documentation?
The doc is right, but you have to put

clock format [clock scan "feb 29 ,2000"]

The comma in the docu is meant seriosly. Perhaps it should be stated
in the doc that it is no spelling mistake:

The acceptable formats are mm/dd?/yy?,
monthname dd ?, yy?, dd monthname ?yy? and day, dd monthname yy.
^!!!!!!

Greetings!
Volker

lvi...@cas.org

unread,
May 19, 1999, 3:00:00 AM5/19/99
to

According to Volker Hetzer <volker...@abg1.siemens.de>:
:The acceptable formats are mm/dd?/yy?,

:monthname dd ?, yy?, dd monthname ?yy? and day, dd monthname yy.
: ^!!!!!!

I wonder if it would be worthwhile to come up with patches for more
date formats?

Reply all
Reply to author
Forward
0 new messages