develooper Front page | perl.perl5.porters | Postings from October 1999

PROPOSAL: D'oh::Year [was: Re: Making -DPERL_Y2KWARN useful after 946684800]

Thread Previous | Thread Next
Michael G Schwern
October 31, 1999 01:49
PROPOSAL: D'oh::Year [was: Re: Making -DPERL_Y2KWARN useful after 946684800]
Message ID:
Well, I made good on my threat, finally.  I just uploaded D'oh::Year
to CPAN (along with a wrapper for which catches miscellaneous
naughtiness done when playing with the year returned from localtime()
and gmtime().

It currently catches things of the general form:




	$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 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:

    D'oh::Year - Catch stupid mistakes when mucking with years, like Y2K

        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.
    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

       "19$year",  19.$year
       "20$year",  20.$year
       "200$year", 200.$year
       $year -= 100, $year = $year - 100;


       $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...

    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:


            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'

    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, it does not appear to
    work on anything but 5.005_03 and higher. It will not work on 5.005_02.

    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,

    Original idea by Andrew Langmead

    Original code by Mark "The Ominous" Dominous

    Cleaned up and maintained by Michael G Schwern <>.


Michael G Schwern                                 

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About