[prev in list] [next in list] [prev in thread] [next in thread]
List: perl5-porters
Subject: PROPOSAL: D'oh::Year [was: Re: Making -DPERL_Y2KWARN useful after 946684800]
From: Michael G Schwern <schwern () pobox ! com>
Date: 1999-10-31 9:27:15
[Download RAW message or body]
Well, I made good on my threat, finally. I just uploaded D'oh::Year
to CPAN (along with a wrapper for y2k.pm) which catches miscellaneous
naughtiness done when playing with the year returned from localtime()
and gmtime().
It currently catches things of the general form:
"19$year"
"20$year"
"200$year"
$year -= 100;
and will eventually catch (these need a little XS):
@times = sort (time, $time_before_2001); # Sept 9, 2001 bug
printf "19%02d", $year;
printf "2%03d", $year; # not entirely necessary, $year -= 100
# covers this for the most part.
It does this at a fairly fine grain by overriding localtime() and
gmtime() to return the year as an object with concatination,
numerization and stringification overloaded. Best of all, no core
patch (yet... I'll probably need one to handle printf()).
So I submit this as a candidate for inclusion into the core. Everyone
screws up printing the year in Perl at some point, and it would be
nice to answer the "PERL HAS A Y2K BUG" posts on clpm with a simple
"go use this module". D'oh::Year not only deals with y2k bugs, but
also handles year mishandling I'll expect to see post-y2k along with
the potential to be expanded to handle other canonical date bugs.
I ask for it to be considered orthoginal to -DPERL_Y2K_WARN rather
than as a replacement. I see no reason to intertwine their fates.
Its available as
http://www.pobox.com/~schwern/src/D-oh-Year-0.04.tar.gz if it hasn't
trickled around CPAN by the reading of this message.
BTW As it relies upon overload, it only appears to work on 5.005_03
and higher. Its a bust on 5.005_02. 5.005_61 has a minor popstack
problem that appears to have been fixed in _62.
I reproduce the man page here for your viewing pleasure:
NAME
D'oh::Year - Catch stupid mistakes when mucking with years, like Y2K
bugs
SYNOPSIS
use D'oh::Year;
($year) = (localtime)[5];
print "We're going to party like its 19$year"; # No you're not.
print "Welcome to the year 20$year!"; # Sorry, Buck.
DESCRIPTION
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
USAGE
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...
Shove it down their throats
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.
Add it to your test harness
Make a quick check
`perl -MD::oh::Year myprogram'
CAVEATS
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?!
Also, because of its dependency on overload.pm, it does not appear to
work on anything but 5.005_03 and higher. It will not work on 5.005_02.
TODO
sort @times
Sorting time()'s as strings is a common mistake. I can't detect it
without some XS code to look at the op stack.
printf "19%02d", $year
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.
AUTHOR
Original idea by Andrew Langmead
Original code by Mark "The Ominous" Dominous
Cleaned up and maintained by Michael G Schwern <schwern@pobox.com>.
--
Michael G Schwern schwern@pobox.com
http://www.pobox.com/~schwern
/(?:(?:(1)[.-]?)?\(?(\d{3})\)?[.-]?)?(\d{3})[.-]?(\d{4})(x\d+)?/i
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic