Unix's Magical Moment, as Foretold by Tom Christiansen

By Allen Noren
February 13, 2009 | Comments: 15

Today I received the following from Tom Christiansen, author of several of our bestselling Perl books, frequent speaker at OSCON, and Perl consultant extraordinaire. He asked that we publish this special news on his behalf. If you're at all interested in numerological phenomena, and Perl, you need to give this a try. Tom, take it away:

"It is inappropriate to require that a time represented as
seconds since the Epoch precisely represent the number of
seconds between the referenced time and the Epoch."

            IEEE Std 1003.1b-1993 (POSIX) Section B.2.2.2
          [ epigram from chapter 3 of  The Perl Cookbook ]

As some of you know, something very, very special is about to occur,
and it falls just 1½ minutes shy of 2 hours past my coming birthday.
The closeness of these events I have foreseen for a very long time.

Here's what it is: your computer's internal time (a.k.a. "the epoch",
measured in number of seconds since 1970), hits the unique figure of
1234567890, lining up all the digits from 1 up through 0, just as
they're lined up across the top of your keyboard.

It really is a Magic Moment in history. This is readily shown
by typing a simple Perl command into any shell window:


    perl -le 'print scalar localtime(1234567890)'

Here in Boulder, I get back:

    Fri Feb 13 16:31:30 2009

However, when *your* clock shows the magic moment happening varies quite a
bit, depending on where you live. I below show how different this can be.

What struck me was how uncannily well the two times line up in
decimal, just a wee shift in the 78 walled off by a pair of 0's:

     1234560780
     1234567890

It was also curious to notice how as far as Damian Conway (author of Perl Best Practices, and for whom much of the code's naming, comments,
and structure were designed :-) and Nathan Torkington (Perl Cookbook
co-author) see things, both events will occur on St Valentine's Day!

Assuming Damian's in Australia/Melbourne....

   I was born at    E -217132020: Wed Feb 13 15:33:00 CST 1963.
   Next birthday at E+1234560780, Sat Feb 14 08:33:00 EST 2009.
   Magic moment is  E+1234567890: Sat Feb 14 10:31:30 EST 2009.

Assuming Nathan's in Pacific/Auckland....

   I was born at    E -217132020: Wed Feb 13 15:33:00 CST 1963.
   Next birthday at E+1234560780, Sat Feb 14 10:33:00 NZDT 2009.
   Magic moment is  E+1234567890: Sat Feb 14 12:31:30 NZDT 2009.

IIRC, Nathan's wife even *missed* a birthday once, flying over
the International Date Line. Travellers beware! }:-(

Which all goes to show how important it is that *in code* one must
*always* use epoch or gmtime internally, relegating localtime to
display purposes alone and at most. Otherwise each day seems to last
50 (FIFTY!) hours, ranging from UTC+14 .. UTC-12 and spanning the IDL.

Using anything but epoch time is--well, dodgy as a dancing dingo. ;-}

Following the output is the program that generates this. Enjoy--and um,
CAVEAT LECTOR. :-) In one case, I originally used the nominative in the
code, but then switched it to the ablative for reasons that should become
manifestly clear once you spot it.

Which identifier was this? :-)

--tom

Here's the regular run here at home. It says:

    I was born at    E -217132020: Wed Feb 13 15:33:00 CST 1963.
    I was born at    E -217132020: Wed Feb 13 14:33:00 MST 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 GMT 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 UTC 1963.
    Next birthday at E+1234560780, Fri Feb 13 14:33:00 MST 2009.
    Magic moment is  E+1234567890: Fri Feb 13 16:31:30 MST 2009.
    Given it is now  E+1234394951, I'm 1,451,526,971 seconds old.

    Seconds to the magic moment: 172,940
    Seconds until next birthday: 165,830
    Magic moment is just 7,110 seconds past my birthday!

[ Now I'll trim the stuff that won't change ]

Assuming I'm in America/Los_Angeles....

    I was born at    E -217132020: Wed Feb 13 15:33:00 CST 1963.
    I was born at    E -217132020: Wed Feb 13 13:33:00 PST 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 GMT 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 GMT 1963.
    Next birthday at E+1234560780, Fri Feb 13 13:33:00 PST 2009.
    Magic moment is  E+1234567890: Fri Feb 13 15:31:30 PST 2009.

Assuming I'm in US/Hawaii....

    I was born at    E -217132020: Wed Feb 13 15:33:00 CST 1963.
    I was born at    E -217132020: Wed Feb 13 11:33:00 HST 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 GMT 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 UTC 1963.
    Next birthday at E+1234560780, Fri Feb 13 11:33:00 HST 2009.
    Magic moment is  E+1234567890: Fri Feb 13 13:31:30 HST 2009.

Assuming I'm in America/Sao_Paulo....

    I was born at    E -217132020: Wed Feb 13 15:33:00 CST 1963.
    I was born at    E -217132020: Wed Feb 13 18:33:00 BRT 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 GMT 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 GMT 1963.
    Next birthday at E+1234560780, Fri Feb 13 19:33:00 BRST 2009.
    Magic moment is  E+1234567890: Fri Feb 13 21:31:30 BRST 2009.
    Given it is now  E+1234395599, I'm 1,451,527,619 seconds old.

Assuming I'm in Canada/Newfoundland....

    I was born at    E -217132020: Wed Feb 13 15:33:00 CST 1963.
    I was born at    E -217132020: Wed Feb 13 18:03:00 NST 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 GMT 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 UTC 1963.
    Next birthday at E+1234560780, Fri Feb 13 18:03:00 NST 2009.
    Magic moment is  E+1234567890: Fri Feb 13 20:01:30 NST 2009.

Assuming I'm in Europe/Paris....

    I was born at    E -217132020: Wed Feb 13 15:33:00 CST 1963.
    I was born at    E -217132020: Wed Feb 13 22:33:00 CET 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 GMT 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 UTC 1963.
    Next birthday at E+1234560780, Fri Feb 13 22:33:00 CET 2009.
    Magic moment is  E+1234567890: Sat Feb 14 00:31:30 CET 2009.

Assuming I'm in Australia/Melbourne....

    I was born at    E -217132020: Wed Feb 13 15:33:00 CST 1963.
    I was born at    E -217132020: Thu Feb 14 07:33:00 EST 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 GMT 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 UTC 1963.
    Next birthday at E+1234560780, Sat Feb 14 08:33:00 EST 2009.
    Magic moment is  E+1234567890: Sat Feb 14 10:31:30 EST 2009.

Assuming I'm in America/New_York....

    I was born at    E -217132020: Wed Feb 13 15:33:00 CST 1963.
    I was born at    E -217132020: Wed Feb 13 16:33:00 EST 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 GMT 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 UTC 1963.
    Next birthday at E+1234560780, Fri Feb 13 16:33:00 EST 2009.
    Magic moment is  E+1234567890: Fri Feb 13 18:31:30 EST 2009.

Assuming I'm in Pacific/Auckland....

    I was born at    E -217132020: Wed Feb 13 15:33:00 CST 1963.
    I was born at    E -217132020: Thu Feb 14 09:33:00 NZST 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 GMT 1963.
    I was born at    E -217132020: Wed Feb 13 21:33:00 UTC 1963.
    Next birthday at E+1234560780, Sat Feb 14 10:33:00 NZDT 2009.
    Magic moment is  E+1234567890: Sat Feb 14 12:31:30 NZDT 2009.

==================================================================

#!/usr/bin/perl
#
# hodie - show countdown till my birthday and the magic moment
#
# Tom Christiansen
# tchrist@perl.com
#
# Wed Feb 11 17:05:38 MST 2009
#
################

use strict;
use warnings FATAL => "all";

use Time::localtime     qw[ :DEFAULT   ];
use Time::Local         qw[  timelocal ];
use POSIX               qw[  strftime  ];

use constant {

    RIGHT_NOW    => $^T,

    EPOCH_FMT    => q(E%+11d),  # epoch format for printf
     DATE_FMT    => q(%+),      # date  format for strftime

    # aka: Greenwich, UTC, Universal, Zulu
    STD_TIMEZONE => "GMT",
    BIRTH_ZONE   => "America/Chicago",  # er: Beloit, Wisconsin

    # aka: 1,234,567,890 or even 1_234_567_890 
    MAGIC_MOMENT => 1234567890,    

    #########################
    ## quam olim natus fui ##
    #########################
    BIRTH_YEAR   => 1963,
    BIRTH_MON    =>    1,  # ( 0 .. 11 )
    BIRTH_MDAY   =>   13,
    BIRTH_HOUR   =>   15,  # 3pm 
    BIRTH_MIN    =>   33, 
    BIRTH_SEC    =>    0,  # NPI

}; 

our(
    $EF,            # interpolable version of EPOCH_FMT
    $BZERO,         # hora natalis mea
    $BANNO,         # anniversarius ille
);

main();
exit();
die "NOT REACHED";

##########################################################

sub commify {
    local $_ = @_ ? shift : $_;
    while (s/^([-+]?\d+)(\d{3})/$1,$2/) { ;;; }
    return $_;
}

BEGIN {
    last unless 1 == eval q{
        use Scalar::Util qw(set_prototype); 
        1;
    };
    set_prototype( \&commify, 
                   ( $] >= 5.0_10_000 ) 
                        ? q(_) 
                        : q(;$)
                 );
}

sub main {
    nits();
    nascor();
    magical_moments();
} 

sub nits {
    $EF = EPOCH_FMT;
}

sub zdate($) { strftime( DATE_FMT,    CORE::gmtime( $_[0] )) }
sub ldate($) { strftime( DATE_FMT, CORE::localtime( $_[0] )) }
sub  date($) { &ldate }

sub diem($) {
    my $era = shift();
    printf "I was born at    $EF: %s.\n", $era, date($era);
} 

sub magical_moments { 

    my $senex   = (  RIGHT_NOW    - $BZERO      );
    my $expecto = ( $BANNO        -  RIGHT_NOW  );
    my $mdelta  = (  MAGIC_MOMENT -  RIGHT_NOW  );
    my $mgksex  = (  MAGIC_MOMENT - $BANNO      );

    diem($BZERO);

    printf "Next birthday at $EF, %s.\n", $BANNO, date($BANNO);
    printf "Magic moment is  $EF: %s.\n", 
                             MAGIC_MOMENT, date(MAGIC_MOMENT);
    printf "Given it is now  $EF, I'm %s seconds old.\n\n", 
                          RIGHT_NOW, commify($senex);
    printf "Seconds to the magic moment: %s\n", commify($mdelta);
    printf "Seconds until next birthday: %s\n", commify($expecto);
    printf "Magic moment is just %s seconds past my birthday!\n",
                        commify($mgksex);
}

sub nascor {

    # local() to assure extant TZ restoration/deletion 
    local $ENV{TZ} = BIRTH_ZONE;

    my $b_year = BIRTH_YEAR;
    my $b_mon  = BIRTH_MON;   
    my $b_mday = BIRTH_MDAY; 
    my $b_hour = BIRTH_HOUR;
    my $b_min  = BIRTH_MIN;
    my $b_sec  = BIRTH_SEC;  

    # good thing we support negative epochal moments here
    my $b_time = timelocal( $b_sec,  $b_min, $b_hour,
                            $b_mday, $b_mon, $b_year );

    # use following (unsigned) cast to defeat sign extension
    ### $b_time = unpack("I", pack("i", $b_time));  

    $BZERO = $b_time;

    $BANNO = do { 
        my ($annus, $anniverse);
        $annus = 1900  + localtime(RIGHT_NOW)->year();
        $anniverse     = timelocal( $b_sec,  $b_min, $b_hour,
                                    $b_mday, $b_mon, $annus );
        if ($anniverse < RIGHT_NOW) {
            $anniverse = timelocal( $b_sec,  $b_min, $b_hour,
                                    $b_mday, $b_mon, (1 + $annus) );
        } 
        $anniverse;     # do{} retval
    };

    diem($BZERO);

    {
        no warnings qw(redefine);
        local *date = \&zdate;          # so shoot me

        $ENV{TZ} = STD_TIMEZONE;
        diem($BZERO);

        ### libc bug? docs say this shouldn't count leap-seconds now!!
        $ENV{TZ} = q();    # UTC, no leap-seconds
        diem($BZERO);
        # nother bug: on some systems, claims UTC above; on others, GMT
    }
}

die "STILL NOT REACHED";

You might also be interested in:

15 Comments

I'm confused about why this number is special.

Why is it any more special than 1234567891? Or 1357902468?

It's special, Sam, because it contains one of each of the symbols we use in base 10 arithmetic, and it has them in the order you would see them if you were counting up and looking at the bottom digit (the ending 0 is the lower digit of 10).

It's neat. I wonder if there are any interesting hexadecimal magic moments coming up?

There are lots of interesting dates that have been happening since the new millenium. Just last month we had 1/4/9, the first three squares!

A friend's son was born in 2/3/5, the first three primes.

@mike: To you 1/4/9 was last month, but to many people it's April Fool's day and hasn't come yet. The only internationally unambiguous way to specify a date is to put the year first, e.g. I was married on the interesting date 3-9-27.

By the same logic, every number is special. And this number is no more special than any other.

It's neat in an arbitrary and meaningless way.

Okay Sam, it's neat in an arbitrary and meaningless way.

@AJ: Dante would have gone gaga with the date of your marriage. He would have been so beside himself that he probably would have squealed. For him, three was a very, very good number (think the Trinity), same goes for 9. And 27? Three cubed? Unbelievable! Numerology factors a LOT in Dante's writing.

Yes, but what's wrong with that? You're perfectly free to ignore it if you don't care.

Matt

Heh, Sam reminds me of the people who went around on 1999-12-31, telling everybody the new millennium really starts after 2000-12-31. Great fun at parties!

Darn, I missed it by less than two hours.

Happy Birthday, Tom.

Thanks, Mike.

--tom

Do you really know which second you were born?

Don't forget to post a followup on 987654321...

Off topic - the "Perl {sucks,is dead,is old}" talk is only proved accurate when articles only show up here once every couple of months...

.

News Topics

Recommended for You

Got a Question?