DifferenceBetweenDate ( StartDate, EndDate)
{
StartYear <- Integer(StartDate(1:2))
-- pick the year in the first two digits and convert from a string to an
integer
EndYear <- Integer(EndDate(1:2))
--pick the year in the first two digits and convert from a string to an
integer
StartMonth <- Integer(StartDate(3:4))
-- pick the year in the first two digits and convert from a string to an
integer
EndMonth <- Integer(EndDate(3:4))
--pick the year in the first two digits and convert from a string to an
integer
StartDay <- Integer(StartDate(5:6))
-- pick the year in the first two digits and convert from a string to an
integer
EndDay <- Integer(EndDay(5:6))
--pick the year in the first two digits and convert from a string to an
integer
ElapsedDays <- EndDay -
StartDay + CorrectionForDaysOfMonth
IF EndMonth > StartMonth
THEN
ElapsedMonths <- EndMonth - StartMonth + CorrectionForMonths
ELSE
ElapasedMonths <- EndMonth - StartMonth + 12 + CorrectionForMonths
ElapsedYears <- EndYear
- StartYear
TotalElapsedDays <- ElapsedYears * 365 + CorrectionLeapYears + ElapsedMonths * 30 + ElapsedDays
RETURN TotalElapsedDays
}
A database that this program might read might look like this:
580119Silverman Jeffrey
535348980MM3098112
841122Silverman Daniel
535231231MS0198112
821028Silverman Sarah
535191923FS0198112
This program and this database are not year 2000 compliant. When the year 2000 rolls around, it will pick up 00 from the year field, subtract the StartYear, and come up with a negative number. It will then multiply that by 365 and that error will swamp the rest of the calculation.
Suppose now that I go an fix the program. That's easy to do:
DifferenceBetweenDate ( StartDate, EndDate)
{
StartYear <- Integer(StartDate(1:4))
-- pick the year in the first two digits and convert from a string to an
integer
EndYear <- Integer(EndDate(1:4))
--pick the year in the first two digits and convert from a string to an
integer
StartMonth <- Integer(StartDate(5:6))
-- pick the year in the first two digits and convert from a string to an
integer
EndMonth <- Integer(EndDate(5:6))
--pick the year in the first two digits and convert from a string to an
integer
StartDay <- Integer(StartDate(7:8))
-- pick the year in the first two digits and convert from a string to an
integer
EndDay <- Integer(EndDay(7:8))
--pick the year in the first two digits and convert from a string to an
integer
ElapsedDays <- EndDay -
StartDay + CorrectionForDaysOfMonth
IF EndMonth > StartMonth
THEN
ElapsedMonths <- EndMonth - StartMonth + CorrectionForMonths
ELSE
ElapasedMonths <- EndMonth - StartMonth + 12 + CorrectionForMonths
ElapsedYears <- EndYear
- StartYear
TotalElapsedDays <- ElapsedYears * 365 + CorrectionLeapYears + ElapsedMonths * 30 + ElapsedDays
RETURN TotalElapsedDays
}
There are a couple of problems with this new program. Can you
find them? The revised program is just as correct as the original
program (there is a lot of software in those correction functions, which
need not concern us here). Go ahead and think for a moment - I can
wait.
The first problem is that if I run this corrected program against uncorrected
data, then the program will give bad results and might even crash.
The second problem is that, while I fixed the code, I didn't fix the comments!
If another programmer comes through in a few years to check what I've done,
and find this, he or she will be very confused. There is no software
tool made that will detect this second problem, in fact, I think it is
theoretically impossible to build a such a tool.
Well, suppose I write a program to correct the data. The corrected
data looks like this:
19580119Silverman Jeffrey
535348980MM3098112
19841122Silverman Daniel
535231231MS0198112
19821028Silverman Sarah
535191923FS0198112
Am I done? Well, no. The problem is that this database is probably read by many programs. If some of the programs are corrected, and some of the programs are not correct, then there will be problems. If an uncorrected program reads a corrected database, it will think that the year is always 19 and the month is 58, or 84, or something. So now you have to have two databases. Keeping the data straight and correct between the databases will be an ongoing challenge. Part of the value of a database is having it stay up to date all the time; having two databases means that there is a delay from database to database.
Warning! Warning! Warning!Extreme cynicism approaching! They also knew that they would go on to other jobs and when the problem became generally known, they would be elsewhere. Many of them have retired. But management also gets some blame for being short sighted, for emphasizing rapid delivery instead of taking the time to test properly, and for build single big systems instead of lots of little systems.
Human Relations (HR) gets in the way. Have you ever turned in a resume to an HR person, knowing full well that this person hasn't a clue what you do or how you do it? Have you worked a contract job, where the job was to get this thing done as quickly as possible and then good bye? The Federal Government, for example, has some talented people, but more frequently has to contract out to get the DP services they need. Congress doesn't help: it mandates overly complicated solutions to simple problems (consider, for example, the Internal Revenue code).
Some of the problem can be traced to planned obsolesence. This is really cynical but here is an article on the subject in the health care field. End of cynicism
Ordinary people (non programmers and non DP managers) trust us (programmers, software engineers, sysadmins, DP managers) to build computer systems which do certain tasks. Ideally, quicker, cheaper, and more reliably than existing human systems. Most of the time, we succeed. But sometimes we fail. In general, I would like to know if non-computer people are generally happy with the proliferation of computer systems. Please E-mail me with your comments on this question.
For a discussion of an operating system which is Y2K and has been since 1980 (sic!), see this article on the VAX/VMS boot process. VMS rocks!
The Federal Communications Commission (FCC)
General Services Administration (GSA)
Y2K for Women. This is an interesting site. I am somewhat offended at the idea that simply because I am not a woman and perhaps especially because I am a software engineer, therefore I don't care about the health safety and well being of my family. If women really want men to become more sensitive and feeling, then it seems incumbent on the women to begin the process by treating the men as if we had feelings. However, once you get beyond that insult, there is a very important idea here, one that's actually fairly old: Be Prepared! The thesis is that disasters happen, get ready for them. That means having supplies of food, water, batteries, tents, etc. so that if you are cut off from civilization, you can survive.
http://www.ieee.org/organizations/tab/Y2k3/tsld001.htm
(A text version) and http://www.ieee.org/organizations/tab/Y2k3/sld001.htm
is a nice presentation of a moderate view about what is going to happen.
In particular, slide http://www.ieee.org/organizations/tab/Y2k3/sld019.htm
shows graphically that some systems will fail, some will not; some will
recover quickly, some will recover better than they were, some will recover
as good as they were, some will not recover.
In the case of the program above, I came up with
a fix in about 10 minutes. However, I haven't compiled it or tested
it, and I made a mistake in the code, and I have another program which
I have to solve in a meaningful way.
The UNIX operating system, including linux, uses a 32 bit counter which counts seconds from 1-Jan-1970. This is good until sometime in the year 2038. By that time, most UNIX software will be running on 64 bit platforms (I hope), and UNIX will use a 64 bit counter. Programs using the time_t typedef will work without changing the source code, although they might need recompilation.
Earlier, I mentioned that the coding was not optimal. A more optimal coding would be to calculate a number based on the year, month, and day. Microsoft Excel does this, and Excel is Y2K compliant. For example, a more efficient coding of the year field is two hexadecimal digits instead of two decimal digits. Then, the year field would be okay until the year 2156, and this solution is backwards compatible with all existing software. "Backwards compatible" in this context means that if an uncoverted program or a converted program writes to the database, a converted program can read the data correctly. Further, if a converted program writes to the database and an unconverted program attempts to read the database, then the program can probably be expected to signal the error.
Javascript also uses a seconds counter - I haven't bothered to figure out when it starts, but since it is already past 4.3 billion, it must be at least 64 bits. The Java Date package is year 2000 compliant and has been from day 1.
September 9, 1999 to September 10, 1999 (to confirm correct translation
of 9/9/99, which is sometimes used as an End of File marker (A
technique taught in introduction to programming classes. Why?
Because it is easy for people who barely understand BASIC to understand.
The problem is that then these people go out and write production code,
but they write it in Intro to Programming style))
December 31, 1998 to January 1, 1999 (to check whether 99 is used to
mean "no expiration date" (Again, an intro to progrmaming
trick))
December 31, 1999 to January 1, 2000 (to check century transition;
January 1 should be a Saturday)
February 28, 2000 to February 29, 2000 (to verify leap year calculation)
February 29, 2000 to March 1, 2000 (to verify leap year calculation;
March 1 should be a Wednesday)
Any time after Mon Jan 18 19:14:06 2038.
I used this "C" program to test the time function:
#include <time.h>
main(int argc, char *argv[] )
{
time_t t = atoi(argv[1]);
char s[60];
printf ( "%s\n", ctime( &t ) );
}
Here are some runs:
[jeffs@angel jeff]$ ./timetest 2147483646
Mon Jan 18 19:14:06 2038
[jeffs@angel jeff]$ ./timetest 2147483647
Mon Jan 18 19:14:07 2038
[jeffs@angel jeff]$ ./timetest 2147483645
Mon Jan 18 19:14:05 2038
[jeffs@angel jeff]$ ./timetest 2147483646
Mon Jan 18 19:14:06 2038
[jeffs@angel jeff]$ ./timetest 2147483647
Mon Jan 18 19:14:07 2038
[jeffs@angel jeff]$ ./timetest 2147483648
Mon Jan 18 19:14:07 2038
[jeffs@angel jeff]$ ./timetest 2147483649
Mon Jan 18 19:14:07 2038
2147483647 = 1024 * 1024 * 1024 -1
Now, here is where the story turns personally
bizarre: I was born at 6:30 AM on January 19th, 1958; the UNIX time crisis
will occur about 11 hours before my 80th birthday.
net time /set /yes \\timeserver
Put this command in a .BAT file and reference the .BAT file from the \windows\startup folder.
If you are running Linux, then you can get the time across the network with the rtime command, as in:
rdate -p -s clock.llnl.gov
There are lots of lists of timeservers on the 'web; this particular timeserver is at the Lawrence Livermore National Lab in California.