D'oh::Year - Catch stupid mistakes when mucking with years, like Y2K bugs
use D'oh::Year; ($year) = (localtime); print "We're going to party like its 19$year"; # No you're not. print "Welcome to the year 20$year!"; # Sorry, Buck.
NO, PERL DOES NOT HAVE A Y2K BUG! but alot of people seem determined to add it. Perl, and most other languges through various historical reasons, like to return years in the form of the number of years since 1900. This has led to the false assumption that its actually returning the last two digits of the current year (1999 => 99) and the mistaken assumption that you can set the current year as "19$year".
This is a Y2K bug, the honor is not just given to COBOL progrmamers.
Bugs of this nature can easily be detected (most of the time) by an automated process. This is it.
When D'oh::Year is used, it provides special versions of localtime() and gmtime() which return a rigged value for the year. When used properly (usually 1900 + $year) you'll notice no difference. But when used for EVIL it will die with a message about misuse of the year.
The following things are naughty (where $year is from gmtime() or localtime()):
"19$year", 19.$year "20$year", 20.$year "200$year", 200.$year $year -= 100, $year = $year - 100;
THE FOLLOWING ARE THE CORRECT WAYS TO MANIPULATE THE DATE Take note, please.
$year += 1900; # Get the complete year. $year %= 100; # Get the last two digits of the year. # ie "01" in 2001 and "99" in 1999
Its simple. Just use (do not require!) the module. If it detects a problem, it will cause your program to abort with an error. If you don't like this, you can use the module with the
:WARN tag like so:
use D'oh::Year qw(:WARN);
and it will warn upon seeing a year mishandling instead of dying.
Because there is a slight performance loss when using D'oh::Year, you might want to only use it during development and testing. A few suggestions for use...
Set up /usr/bin/perl on your development machine as a shell wrapper around perl which always uses D'oh::Year:
#!/bin/sh perl -MD::oh::Year $@
This might be a little draconian for normal usage.
perl -MD::oh::Year myprogram
This program does its checking at run time not compile time. Thus it is not simply enough to slap D'oh::Year on a program, run it once and expect it to find everything. For a thourough scrubbing you must make sure every line of code is excersied... but you already have test harnesses set up to do that, RIGHT?!
Sorting time()'s as strings is a common mistake. I can't detect it without some XS code to look at the op stack.
I can't handle this without being able to override printf(), but can't do that because it has a complex prototype. This could be handled, but it would require a patch to pp_printf. I can do sprintf(), but I don't think its wise to be non-orthoganal and lead non-doc readers on that if sprintf() is handled, printf() should be, too.
Original idea by Andrew Langmead
Original code by Mark "The Ominous" Dominous
Cleaned up and maintained by Michael G Schwern <email@example.com>.