Gmail Calendar Documents Reader Web more »
Recently Visited Groups | Help | Sign in
Google Groups Home
Date arithmetic and Zune bug
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  Messages 1 - 25 of 41 - Collapse all  -  Translate all to Translated (View all originals)   Newer >
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Terje Mathisen  
View profile  
 More options Jan 5, 6:05 am
Newsgroups: comp.arch
From: Terje Mathisen <terje.mathi...@hda.hydro.com>
Date: Mon, 05 Jan 2009 12:05:45 +0100
Local: Mon, Jan 5 2009 6:05 am
Subject: Date arithmetic and Zune bug
I read with disbelief about how most of Microsoft's 30 GB Zune players
hung on Dec 31st, due to not being able to handle day number 366 of a
leap year, and started thinking about some discussions we've had here
over the years about the fastests/tightest/most elegant ways to convert
between year-month-day and day number.

The code I wrote to handle this problem was written in Jan 2000, then we
had another discussion in 2005, at which time one of the IBM regulars
(probably Hack?) pointed me at an IBM report which used very similar ideas.

Anyway, my code from 2005 uses about 10-15 regular instructions, plus
two unsigned multiplications, to do ymd2days, so about 10-20 clock cycles:

/* #define USE_UNSIGNED_MASK */

#ifdef USE_UNSIGNED_SHIFT
typedef unsigned mask_t;

# define INC_IF_MASK(x,mask) ((x) += (mask) & 1)
# define DEC_IF_MASK(x,mask) ((x) -= (mask) & 1)
#else
typedef int mask_t;

# define INC_IF_MASK(x,mask) ((x) -= (mask))
# define DEC_IF_MASK(x,mask) ((x) += (mask))
#endif

/* These operations are valid for any date after 1584,
  * according to the Gregorian (modern) calendar
  */

#define STARTYEAR 1200  /* Must be divisible by 400! */

/* Table to simplify conversions between mm-dd and day_in_year */
static short daysToMonth[13] =
        {-1,30,60,91,121,152,183,213,244,274,305,336,366};

unsigned ymd2days(unsigned y, unsigned m, unsigned d)
{
     unsigned days, y100;

        /* Start by setting March = month zero: */
     mask_t mask = (mask_t) (m -= 3);
        /* Mask will now be in the (mask_t) -2 to 9 range, a shift by 4 is
enough to make it -1 or 0: */
        mask >>= 4;

     DEC_IF_MASK(y, mask);                      /* Decrement year if jan/feb */
     m += (mask & 12);               /* and increment the month: The
year starts in March! */
     y -= STARTYEAR;
     y100 = y / 100;                 /* Centuries for leap year calc */
     days = y * 365 + (y >> 2) - y100 + (y100 >> 2);
     days += (unsigned) daysToMonth[m] + d;
     return days;

}

The reverse conversion is the fun one: It turns out that the fastest
method is to guess the year, then correct it if off by one. :-)

The code below will work on any platform which provides unsigned
integers with at least 29 bits of precision, but it will be slightly
faster with 30+ bit twos-complement signed ints.

void days2ymd(unsigned days, unsigned *yy, unsigned *mm, unsigned *dd)
{
     unsigned y400, y100, y, m, d, gd;
     mask_t mask;

     /* Start by subtracting any full 400-year cycles: */
     y400 = days / 146097;
     days -= y400 * 146097;

#if 0
     /* Very good approximation to the number of years, will be wrong
      * (too high) 257 times
      * in a 400-year cycle, i.e. in 0.18% of all calls.
      */

  /* A good compiler will replace this with a scaled reciprocal MUL! */
     y = (days + 1) * 400 / 146096;
#else
  /* Useful and faster approximation to the number of years, will be
   * wrong (too high) 910 times
   * in a 400-year cycle, i.e. in 0.62% of all calls.
   *
   * Requires unsigned values with up to 29 significant bits!
   */
     y = (days * 2871 + 1983) >> 20;
/*    y = (days * 22967 + 59235) >> 23; */
     /* peter (at) horizon.com suggested this! */
#endif

  /* Calculate # of centuries:
   * Since y will be in the 0 to 400 range, the following
   * approximation can be used instead of a division by 100:
   * y100 = y / 100;  ~ (y * 41) >> 12;
   */
     y100 = (y * 41) >> 12;

  /* # of days in those full years */
     gd = y * 365       /* Normal years */
        + (y >> 2)        /* + leap years every 4 years */
        - y100          /* - missing century leap years */
        + (y100 >> 2);  /* + every 400 years */

  /* test for the small chance of a wrong year: */
     if (gd > days) {
        y--;    /* y will be in the [0-399] range! */
        y100 = (y * 41) >> 12;
        /* The 400-year correction can be skipped! */
        gd = y * 365 + (y >> 2) - y100 /* + (y100 >> 2) */;
     }

     /* Calculate the offset into the current year: */
     days -= gd;
     /* Correct for starting date and 400-year cycles: */
     y += STARTYEAR + y400 * 400;

#if 1
     /* Make a FAST guess at the current month, can be too low: */
     m = days >> 5;

     mask = (mask_t) daysToMonth[m+1] - (mask_t) days;
        /* mask will be in the -18 to 18 range, use shift by 5: */
     mask >>= 5;
     /* If the guess was wrong then the mask will be -1, otherwise 0: */

     /* Increment month if needed */
     INC_IF_MASK(m, mask);

     /* The remainder is the day of the month */
     d = days - (unsigned) daysToMonth[m];

     /* Correct for the March 1 starting point: */
     mask = (mask_t) (9 - m) >> 4;
     m += 3;
     INC_IF_MASK(y, mask);
     m -= (unsigned) (mask & 12);

#else
   /* Based on code from an IBM report: Slightly slower, but
    * uses no table lookups!
    */
     m = ((days + 31) * 1071);
     d = (((m & 0x7fff) * 62669) >> 26) + 1;
     m >>= 15;

     mask = (mask_t) (10 - m) >> 4;
     m += 2;
     INC_IF_MASK(y, mask);
     m -= (unsigned) (mask & 12);
#endif

     *yy = y; *mm = m; *dd = d;

}

This second function uses four integer multiplications, one of them is a
reciprocal to avoid division, the rest are all shifts/adds/subs etc.

Running time is on the order of 30-70 cycles, depending upon the speed
of integer muls.

Terje

--
- <Terje.Mathi...@hda.hydro.com>
"almost all programming can be viewed as an exercise in caching"


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Rob Warnock  
View profile  
 More options Jan 5, 6:36 am
Newsgroups: comp.arch
From: r...@rpw3.org (Rob Warnock)
Date: Mon, 05 Jan 2009 05:36:26 -0600
Local: Mon, Jan 5 2009 6:36 am
Subject: Re: Date arithmetic and Zune bug
Terje Mathisen <terje.mathi...@hda.hydro.com> wrote:

+---------------
| I read with disbelief about how most of Microsoft's 30 GB Zune players
| hung on Dec 31st, due to not being able to handle day number 366 of a
| leap year...
+---------------

It's worse that you think. ;-}  ;-}  See the latest issue of RISKS
for the actual failing code:

    http://catless.ncl.ac.uk/Risks/25.50.html#subj2.2
    Zounds! Zinger: Zune Zapped Zealously with Zero-tolerance
    David Magda <dma...@ee.ryerson.ca>
    Thu, 1 Jan 2009 15:26:18 -0500
    ...
    The issue is an infinite loop:

    > while (days > 365) {
    >     if (IsLeapYear(year))    {
    >         if (days > 366) {
    >             days -= 366;
    >             year += 1;
    >         }
    >     } else {
    >         days -= 365;
    >         year += 1;
    >     }
    > }
    ...
    http://www.zuneboards.com/forums/349447-post1.html

I suspect it was trying to do something like this, only it missed:

    while (days > (IsLeapYear(year) ? 366 : 365)) {
        days -= (IsLeapYear(year) ? 366 : 365);
        year += 1;
    }

-Rob

p.s. Yes, I know, "IsLeapYear()" is probably expensive, so the
speed demons among us will probably want to rewrite it like this:  ;-}

    while (days > (year_length = (IsLeapYear(year) ? 366 : 365))) {
        days -= year_length;
        year += 1;
    }

-----
Rob Warnock                     <r...@rpw3.org>
627 26th Avenue                 <URL:http://rpw3.org/>
San Mateo, CA 94403             (650)572-2607


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Terje Mathisen  
View profile  
 More options Jan 5, 7:14 am
Newsgroups: comp.arch
From: Terje Mathisen <terje.mathi...@hda.hydro.com>
Date: Mon, 05 Jan 2009 13:14:31 +0100
Local: Mon, Jan 5 2009 7:14 am
Subject: Re: Date arithmetic and Zune bug

Rob Warnock wrote:
> Terje Mathisen <terje.mathi...@hda.hydro.com> wrote:
> +---------------
> | I read with disbelief about how most of Microsoft's 30 GB Zune players
> | hung on Dec 31st, due to not being able to handle day number 366 of a
> | leap year...
> +---------------

> It's worse that you think. ;-}  ;-}  See the latest issue of RISKS

No, it isn't.

> for the actual failing code:

I first found a link to the full driver code, and knowing there was a
date bug, it took me less than a minute to locate the error below.

The point is that the fully correct version, that handles all possible
dates until we run out of bits in integers, runs _faster_ than even the
rewritten version, since the loop has to iterate at least 28 times!

I just reran a benchmark of the functions I posted: Doing the
conversions both forwards and back, plus a post-conversion check that
all generated dates are legal, and that the input date was equal to the
output:

It took about 42 ns/iteration on my laptop, which means about 90 clock
cycles, of which maximum 70 can have been used for the days2ymd() call.

28++ iterations of a loop which includes an inline IsLeapYear() call has
to take significantly more time!

Terje

--
- <Terje.Mathi...@hda.hydro.com>
"almost all programming can be viewed as an exercise in caching"


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Paul Gotch  
View profile  
 More options Jan 5, 9:00 am
Newsgroups: comp.arch
From: Paul Gotch <pa...@at-cantab-dot.net>
Date: 05 Jan 2009 14:00:03 +0000 (GMT)
Local: Mon, Jan 5 2009 9:00 am
Subject: Re: Date arithmetic and Zune bug

Terje Mathisen <terje.mathi...@hda.hydro.com> wrote:
> I read with disbelief about how most of Microsoft's 30 GB Zune players
> hung on Dec 31st

It should be noted that this appears to be a bug in some versions of
the Freescale iMX31 Board Support Package for Windows CE. Obviously
from the consumer's point of view it make little difference if it is
MS's or Freescale's bug.

-p
--
"Unix is user friendly, it's just picky about who its friends are."
 - Anonymous
--------------------------------------------------------------------


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ken Hagan  
View profile  
 More options Jan 5, 12:20 pm
Newsgroups: comp.arch
From: "Ken Hagan" <K.Ha...@thermoteknix.com>
Date: Mon, 05 Jan 2009 17:20:23 -0000
Local: Mon, Jan 5 2009 12:20 pm
Subject: Re: Date arithmetic and Zune bug
On Mon, 05 Jan 2009 11:05:45 -0000, Terje Mathisen  

<terje.mathi...@hda.hydro.com> wrote:
> I read with disbelief about how most of Microsoft's 30 GB Zune players  
> hung on Dec 31st, due to not being able to handle day number 366 of a  
> leap year

Disbelief? You jest, sir. Leap year problems are easy to pose but the
historical evidence is that both programmers and QA testers find them
almost impossible to handle. My impression is that far more software
failed on 29:Feb:2000 than did 8 weeks previously, which is quite
stunning when you consider that the requirement here was for a no-op.

    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Anne & Lynn Wheeler  
View profile  
 More options Jan 5, 2:14 pm
Newsgroups: comp.arch
From: Anne & Lynn Wheeler <l...@garlic.com>
Date: Mon, 05 Jan 2009 14:14:46 -0500
Local: Mon, Jan 5 2009 2:14 pm
Subject: Re: Date arithmetic and Zune bug

"Ken Hagan" <K.Ha...@thermoteknix.com> writes:
> Disbelief? You jest, sir. Leap year problems are easy to pose but the
> historical evidence is that both programmers and QA testers find them
> almost impossible to handle. My impression is that far more software
> failed on 29:Feb:2000 than did 8 weeks previously, which is quite
> stunning when you consider that the requirement here was for a no-op.

there was y2k discussion thread in the early 80s (talking about the
impending century problem) ... and there were instances of other kinds
of failures in processing dates ... frequent failures involve leap yrs;
one of the entries extracted here (including problem in airline
reservation system that happened on 29feb72 and a problem in how dates
are handled for shuttle missions):
http://www.garlic.com/~lynn/99.html#email841207

in these old threads:
http://www.garlic.com/~lynn/99.html#24 BA Solves Y2K (Was: Re: Chinese Solve Y2K)
http://www.garlic.com/~lynn/99.html#233 Computer of the century

--
40+yrs virtualization experience (since Jan68), online at home since Mar70


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Gavin Scott  
View profile  
 More options Jan 5, 3:01 pm
Newsgroups: comp.arch
From: ga...@allegro.com (Gavin Scott)
Date: Mon, 05 Jan 2009 14:01:45 -0600
Local: Mon, Jan 5 2009 3:01 pm
Subject: Re: Date arithmetic and Zune bug

Ken Hagan <K.Ha...@thermoteknix.com> wrote:
> Disbelief? You jest, sir. Leap year problems are easy to pose but the
> historical evidence is that both programmers and QA testers find them
> almost impossible to handle.

Of course date-sensitive bugs are the worst sort, since they're
generally impossible to detect through testing unless you test at
exactly the right time, and worse, they tend to strike your entire
customer base on the same day, often with very little warning (one
learns to pay more attention to calls from New Zealand).

I wonder how many products now have, as part of their QA, a machine
running with a clock set some time in the future, say 1-3 months
ahead, for the express purpose of finding this sort of thing.

A related class of bugs that's also hard to test for are the "system
fails after being up for exactly N days", but these at least have a
simple temporary workaround and don't strike everyone at once.

G.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Andrew Reilly  
View profile  
 More options Jan 5, 5:51 pm
Newsgroups: comp.arch
From: Andrew Reilly <andrew-newsp...@areilly.bpc-users.org>
Date: 5 Jan 2009 22:51:00 GMT
Subject: Re: Date arithmetic and Zune bug

On Mon, 05 Jan 2009 12:05:45 +0100, Terje Mathisen wrote:
> I read with disbelief about how most of Microsoft's 30 GB Zune players
> hung on Dec 31st, due to not being able to handle day number 366 of a
> leap year, and started thinking about some discussions we've had here
> over the years about the fastests/tightest/most elegant ways to convert
> between year-month-day and day number.

The thing that I find curious about these sorts of incident is what
business of devices like the Zune is the date, anyway?  I suppose that
they have some kind of convenience clock function, like my iPod, but I'm
sure most users wouldn't care if they just didn't.

There were lots of industrial/control/embedded devices that were held up
as potential y2k catastrophe initiators, back then, that had no business
knowing what the date was, IMO.  None of the audio gear that I've built  
ever did, except for that one that was sitting inside an industrial
Windows PC.  I suppose the Zune is a bit like that...

Cheers,

--
Andrew


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Rob Warnock  
View profile  
 More options Jan 5, 8:18 pm
Newsgroups: comp.arch
From: r...@rpw3.org (Rob Warnock)
Date: Mon, 05 Jan 2009 19:18:52 -0600
Local: Mon, Jan 5 2009 8:18 pm
Subject: Re: Date arithmetic and Zune bug
Terje Mathisen  <terje.mathi...@hda.hydro.com> wrote:
+---------------
| Rob Warnock wrote:

| > p.s. Yes, I know, "IsLeapYear()" is probably expensive, so the
| > speed demons among us will probably want to rewrite it like this:  ;-}
| >
| >     while (days > (year_length = (IsLeapYear(year) ? 366 : 365))) {
| >  days -= year_length;
| >  year += 1;
| >     }
|
| The point is that the fully correct version, that handles all possible
| dates until we run out of bits in integers, runs _faster_ than even the
| rewritten version, since the loop has to iterate at least 28 times!
+---------------

Yes, of course. For the record, I was *not* arguing with your
fully correct version or its performance, only noting that even a
minimally-correct [though obviously slow] version is (1) one-third
the size of the broken one, (2) slightly faster, (3) *much* easier
both to write and to read later, and (4) trivial. To say it another
way, "What *WERE* they thinking?!?" [Ans: Probably weren't.]

+---------------
| I just reran a benchmark of the functions I posted: ...
| It took about 42 ns/iteration on my laptop, which means about 90 clock
| cycles, of which maximum 70 can have been used for the days2ymd() call.
+---------------

Neat!

-Rob

-----
Rob Warnock                     <r...@rpw3.org>
627 26th Avenue                 <URL:http://rpw3.org/>
San Mateo, CA 94403             (650)572-2607


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Anne & Lynn Wheeler  
View profile  
 More options Jan 6, 4:58 pm
Newsgroups: comp.arch
From: Anne & Lynn Wheeler <l...@garlic.com>
Date: Tue, 06 Jan 2009 16:58:59 -0500
Local: Tues, Jan 6 2009 4:58 pm
Subject: Re: Date arithmetic and Zune bug

re:
http://www.garlic.com/~lynn/2009.html#16 Date arithmetic and Zune bug

for a little other topic drift (leap "seconds" rather than "year"):

'Leap Second' Snafu Affects Oracle Clusterware
http://www.pcworld.com/article/156453/leap_second_snafu_affects_oracl...

back circa 1970 ... i spent 3months with a number of other people
discussing what to do about "leap seconds" (that and what does the
"start of the century" mean ... i.e. did the century start in 1900 or
1901?) ... this was for the 370 TOD clock.

--
40+yrs virtualization experience (since Jan68), online at home since Mar70


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
H. Peter Anvin  
View profile  
 More options Jan 7, 3:18 am
Newsgroups: comp.arch
From: "H. Peter Anvin" <h...@zytor.com>
Date: Wed, 07 Jan 2009 00:18:12 -0800
Local: Wed, Jan 7 2009 3:18 am
Subject: Re: Date arithmetic and Zune bug

Terje Mathisen wrote:
> I read with disbelief about how most of Microsoft's 30 GB Zune players
> hung on Dec 31st, due to not being able to handle day number 366 of a
> leap year, and started thinking about some discussions we've had here
> over the years about the fastests/tightest/most elegant ways to convert
> between year-month-day and day number.

> The code I wrote to handle this problem was written in Jan 2000, then we
> had another discussion in 2005, at which time one of the IBM regulars
> (probably Hack?) pointed me at an IBM report which used very similar ideas.

> Anyway, my code from 2005 uses about 10-15 regular instructions, plus
> two unsigned multiplications, to do ymd2days, so about 10-20 clock cycles:

[... code ...]

Yes, a good hint one is doing it wrong is when you spot a loop in date
code.  It's just plain broken.

> This second function uses four integer multiplications, one of them is a
> reciprocal to avoid division, the rest are all shifts/adds/subs etc.

This is, of course, good if you have to do a *lot* of these conversions
(or you're writing a library, in which case you have to assume so), but
otherwise I'd suggest leaving the divisions in to make the code more
understandable to lower-level programmers.

One important bit about anything dealing with Gregorian dates is the
observation Christian Zeller did well over a century ago: the math gets
a lot cleaner if you treat January and February as months 13 and 14 of
(year-1).  March was, in fact, historically the first month, as
evidenced by our names for months 9 to 12: "September" ("seventh month")
to "December" ("tenth month")...

        -hpa


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ken Hagan  
View profile  
 More options Jan 7, 5:01 am
Newsgroups: comp.arch
From: "Ken Hagan" <K.Ha...@thermoteknix.com>
Date: Wed, 07 Jan 2009 10:01:50 -0000
Local: Wed, Jan 7 2009 5:01 am
Subject: Re: Date arithmetic and Zune bug
On Wed, 07 Jan 2009 08:18:12 -0000, H. Peter Anvin <h...@zytor.com> wrote:

> ... March was, in fact, historically the first month, as
> evidenced by our names for months 9 to 12: "September" ("seventh month")
> to "December" ("tenth month")...

...and by the fact that the leap day was originally placed at the very
end of the year (where any sane person would put it) but wasn't moved
to December in the Gregorian reform, presumably for reasons of backwards
compatibility. :)

    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Rob Warnock  
View profile  
 More options Jan 7, 7:10 am
Newsgroups: comp.arch
From: r...@rpw3.org (Rob Warnock)
Date: Wed, 07 Jan 2009 06:10:03 -0600
Local: Wed, Jan 7 2009 7:10 am
Subject: Re: Date arithmetic and Zune bug
H. Peter Anvin <h...@zytor.com> wrote:
+---------------
| One important bit about anything dealing with Gregorian dates is the
| observation Christian Zeller did well over a century ago: the math gets
| a lot cleaner if you treat January and February as months 13 and 14 of
| (year-1).  March was, in fact, historically the first month, as
| evidenced by our names for months 9 to 12: "September" ("seventh month")
| to "December" ("tenth month")...
+---------------

Eric Naggum's classic paper on the subject [known mostly among the Lisp
community, but applicable & readily accessible to a general audience]:

    http://naggum.no/lugm-time.html
    The Long, Painful History of Time
    Erik Naggum, Naggum Software
    Oslo, Norway
    1999-10-11

suggests doing something very similar:

    ...
    The Roman tradition of starting the year in the month of March
    has also been lost.  Most agrarian societies were far more
    interested in the onset of spring than in the winter solstice,
    even though various deities were naturally celebrated when the
    sun returned. ...but Julius Caesar decided to move the Roman
    calendar back two months... far more important was the decision
    to retain the leap day in February.  In the old calendar, the
    leap day was added at the end of the year, as makes perfect
    sense, when the month was already short, but now it is squeezed
    into the middle of the first quarter, complicating all sorts of
    calculations, and affecting how much people work.  In the old
    days, the leap day was used as an extra day for the various
    fertility festivities.

    [If one starts the year on March 1st] the simplicity of the scheme
    is quite amazing: a 400-year cycle not only starts 2000-03-01
    (as it did 1600-03-01), it contains an even number of weeks: 20,871.
    This means that we can make do with a single 400-year calculation
    for all time within the Gregorian calendar with respect to days of
    week, leap days, etc.
    ...
    The LOCAL-TIME Concept
    ...
    Because we are [in 1999] very close to the beginning of the next
    400-year leap-year cycle, thanks to Pope Gregory, day 0 is defined
    to be 2000-03-01, which much less arbitrary than other systems,
    but not obviously so.  Each 400-year cycle contains 146,097 days,
    so an arbitrary decision was made to limit the day to a maximal
    negative value of -146,097, or 1600-03-01.  This can be changed
    at the peril of accurately representing days that do not belong
    to the calendar used at the time.
    ...
    [Because bignum arithmetic is expensive] The LOCAL-TIME concept
    therefore represents time as three disjoint fixnums [relatively
    small tagged integers that consume only one machine word, including
    a few bits of type tag]:

       1. the number of days since (or until, when negative) 2000-03-01
       2. the number of seconds since the start of the day in
          Coordinated Universal Time
       3. the number of milliseconds since the start of the second.

    All numbers have origin 0.  Only the number of days may be negative.
    ...[more details about why this makes sense, how conversions and
    date/time calculations (including intervals) are done in the system]...

Note: Even if you don't care for his proposed system, the paper is
a delightful tour of calendric history which touches on the influences
of geography, politics, science, and general historical randomness.  ;-}

-Rob

-----
Rob Warnock                     <r...@rpw3.org>
627 26th Avenue                 <URL:http://rpw3.org/>
San Mateo, CA 94403             (650)572-2607


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
n...@cam.ac.uk  
View profile  
 More options Jan 7, 12:11 pm
Newsgroups: comp.arch
From: n...@cam.ac.uk
Date: Wed, 7 Jan 2009 17:11:50 +0000 (GMT)
Local: Wed, Jan 7 2009 12:11 pm
Subject: Re: Date arithmetic and Zune bug
In article <7OGdnVSGY6kGBvnUnZ2dnUVZ_gCdn...@speakeasy.net>,

Rob Warnock <r...@rpw3.org> wrote:

>Eric Naggum's classic paper on the subject [known mostly among the Lisp
>community, but applicable & readily accessible to a general audience]:

>suggests doing something very similar:

>    The Roman tradition of starting the year in the month of March
>    has also been lost.  Most agrarian societies were far more
>    interested in the onset of spring than in the winter solstice,
>    even though various deities were naturally celebrated when the
>    sun returned. ...

Well, he may address the point, but that statement is grossly
misleading in isolation.

The reason that the winter solstice was the primary seasonal
festival, has survived Christianity more-or-less unchanged and is
much more important (even today) in northern Europe than elsewhere
is FAR more likely to be due to how close we live to the Arctic
circle.  All of the other agrarian societies came from closer to
the equator, often much closer.

I am pretty surprised that a Norwegian missed that aspect!

Regards,
Nick Maclaren.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Muzaffer Kal  
View profile  
 More options Jan 7, 2:20 pm
Newsgroups: comp.arch
From: Muzaffer Kal <k...@dspia.com>
Date: Wed, 07 Jan 2009 11:20:31 -0800
Local: Wed, Jan 7 2009 2:20 pm
Subject: Re: Date arithmetic and Zune bug

On Wed, 07 Jan 2009 06:10:03 -0600, r...@rpw3.org (Rob Warnock) wrote:
>    [If one starts the year on March 1st] the simplicity of the scheme
>    is quite amazing: a 400-year cycle not only starts 2000-03-01
>    (as it did 1600-03-01), it contains an even number of weeks: 20,871.

Is 20,871 supposed to be the number of weeks? If so, I'm not sure if
the latter portion of the above statement is correct.

Muzaffer Kal

DSPIA INC.
ASIC/FPGA Design Services
http://www.dspia.com


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Terje Mathisen  
View profile  
 More options Jan 7, 2:20 pm
Newsgroups: comp.arch
From: Terje Mathisen <terje.mathi...@hda.hydro.com>
Date: Wed, 07 Jan 2009 20:20:01 +0100
Local: Wed, Jan 7 2009 2:20 pm
Subject: Re: Date arithmetic and Zune bug
H. Peter Anvin wrote:

 > Terje Mathisen wrote:
 >> I read with disbelief about how most of Microsoft's 30 GB Zune players
 >> hung on Dec 31st, due to not being able to handle day number 366 of a
 >> leap year, and started thinking about some discussions we've had here
 >> over the years about the fastests/tightest/most elegant ways to convert
 >> between year-month-day and day number.
 >>
 >> The code I wrote to handle this problem was written in Jan 2000, then we
 >> had another discussion in 2005, at which time one of the IBM regulars
 >> (probably Hack?) pointed me at an IBM report which used very similar
ideas.
 >>
 >> Anyway, my code from 2005 uses about 10-15 regular instructions, plus
 >> two unsigned multiplications, to do ymd2days, so about 10-20 clock
cycles:
 >
 > [... code ...]
 >
 > Yes, a good hint one is doing it wrong is when you spot a loop in date
 > code.  It's just plain broken.
 >
 >> This second function uses four integer multiplications, one of them is a
 >> reciprocal to avoid division, the rest are all shifts/adds/subs etc.
 >
 > This is, of course, good if you have to do a *lot* of these conversions
 > (or you're writing a library, in which case you have to assume so), but
 > otherwise I'd suggest leaving the divisions in to make the code more
 > understandable to lower-level programmers.

Sorry: It is written as a constant division, but I have verified (by
code inspection) that pretty much all modern compilers, for x86, Power,
Sparc, Alpha, ARM will convert that into a reciprocal division.
 >
 > One important bit about anything dealing with Gregorian dates is the
 > observation Christian Zeller did well over a century ago: the math gets
 > a lot cleaner if you treat January and February as months 13 and 14 of
 > (year-1).  March was, in fact, historically the first month, as
 > evidenced by our names for months 9 to 12: "September" ("seventh month")
 > to "December" ("tenth month")...

<BG>

My STARTDATE is #define'd as March 1st, 1200 (or any other year
divisible by 400).

I number the months from 0 to 11 starting with March, then correct at
the end. Here's the conversion logic:

     /* Correct for the March 1 starting point: */
     mask = (mask_t) (9 - m) >> 4; // -1 if (m == 10 || m == 11)
     m += 3;
     INC_IF_MASK(y, mask);
     m -= (unsigned) (mask & 12);

Terje

--
- <Terje.Mathi...@hda.hydro.com>
"almost all programming can be viewed as an exercise in caching"


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Terje Mathisen  
View profile  
 More options Jan 7, 2:27 pm
Newsgroups: comp.arch
From: Terje Mathisen <terje.mathi...@hda.hydro.com>
Date: Wed, 07 Jan 2009 20:27:50 +0100
Local: Wed, Jan 7 2009 2:27 pm
Subject: Re: Date arithmetic and Zune bug

n...@cam.ac.uk wrote:
> The reason that the winter solstice was the primary seasonal
> festival, has survived Christianity more-or-less unchanged and is
> much more important (even today) in northern Europe than elsewhere
> is FAR more likely to be due to how close we live to the Arctic
> circle.  All of the other agrarian societies came from closer to
> the equator, often much closer.

> I am pretty surprised that a Norwegian missed that aspect!

I don't think he missed it that badly, it is common knowledge that after
Olaf Trygvasson (later St Olaf) converted the country from the old Norse
gods to Christianity, the new priests simply subsumed the old Juleblot,
celebrated around winter solstice, into the Christmas celebration.

Here in Norway (as well as the rest of Scandinavia afaik) we still call
it 'Jul' and 'Julefeiring (Jul celebration)', and the days are named
Julaften (Jul evening) for the 24th, then 1 and 2 Juledag (1st and 2nd
day of Jul), going all the way till either the 13th or 20th day of Jul
when the festivities are officially over.

Jesus' birth, Christianity etc isn't mentioned at all in the naming of
the period.

Terje
--
- <Terje.Mathi...@hda.hydro.com>
"almost all programming can be viewed as an exercise in caching"


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Terje Mathisen  
View profile  
 More options Jan 7, 2:32 pm
Newsgroups: comp.arch
From: Terje Mathisen <terje.mathi...@hda.hydro.com>
Date: Wed, 07 Jan 2009 20:32:18 +0100
Local: Wed, Jan 7 2009 2:32 pm
Subject: Re: Date arithmetic and Zune bug

Muzaffer Kal wrote:
> On Wed, 07 Jan 2009 06:10:03 -0600, r...@rpw3.org (Rob Warnock) wrote:
>>    [If one starts the year on March 1st] the simplicity of the scheme
>>    is quite amazing: a 400-year cycle not only starts 2000-03-01
>>    (as it did 1600-03-01), it contains an even number of weeks: 20,871.

> Is 20,871 supposed to be the number of weeks? If so, I'm not sure if
> the latter portion of the above statement is correct.

146097 : 7 = 20871, so this is correct.

It does mean that you can discard the number of initial 400-year cycles
when using the day number to calculate the day of week.

OTOH, I much prefer to put the zero point at 1200-03-01, or even
earlier, since this means that all Gregorian dates will have a positive
day number, something which makes the conversion algorithms more easily
portable across all cpu architectures, including those without two's
complement integer arithmetic.

Terje

--
- <Terje.Mathi...@hda.hydro.com>
"almost all programming can be viewed as an exercise in caching"


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
n...@cam.ac.uk  
View profile  
 More options Jan 7, 2:33 pm
Newsgroups: comp.arch
From: n...@cam.ac.uk
Date: Wed, 7 Jan 2009 19:33:51 +0000 (GMT)
Local: Wed, Jan 7 2009 2:33 pm
Subject: Re: Date arithmetic and Zune bug
In article <Gf6dnTS8KtWqn_jUnZ2dnUVZ8qXin...@giganews.com>,
Terje Mathisen  <terje.mathi...@hda.hydro.com> wrote:

>n...@cam.ac.uk wrote:
>> The reason that the winter solstice was the primary seasonal
>> festival, has survived Christianity more-or-less unchanged and is
>> much more important (even today) in northern Europe than elsewhere
>> is FAR more likely to be due to how close we live to the Arctic
>> circle.  All of the other agrarian societies came from closer to
>> the equator, often much closer.

>> I am pretty surprised that a Norwegian missed that aspect!

>I don't think he missed it that badly, it is common knowledge that after
>Olaf Trygvasson (later St Olaf) converted the country from the old Norse
>gods to Christianity, the new priests simply subsumed the old Juleblot,
>celebrated around winter solstice, into the Christmas celebration.

Yes, of course, but I was referring to the relative importance of
the winter solstice and 'spring' - specifically with respect to
when the year starts.

Where we live, the feeling "Thank God, at least the days are getting
longer" is dominant, and must have been more so in the days of
candles.  In places closer to the equator, the gloom of winter is
FAR less marked, and consequentially the solstice is less important.

Regards,
Nick Maclaren.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Kai Harrekilde-Petersen  
View profile  
 More options Jan 7, 2:34 pm
Newsgroups: comp.arch
From: Kai Harrekilde-Petersen <k...@harrekilde.dk>
Date: Wed, 07 Jan 2009 20:34:23 +0100
Local: Wed, Jan 7 2009 2:34 pm
Subject: Re: Date arithmetic and Zune bug

Yup (although spelling varies slightly).  Even the english have
'Yuletide' - adapted from the Danish vikings ;-)

Kai
--
Kai Harrekilde-Petersen <khp(at)harrekilde(dot)dk>


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Joe Pfeiffer  
View profile  
 More options Jan 7, 2:35 pm
Newsgroups: comp.arch
From: Joe Pfeiffer <pfeif...@cs.nmsu.edu>
Date: Wed, 07 Jan 2009 12:35:32 -0700
Local: Wed, Jan 7 2009 2:35 pm
Subject: Re: Date arithmetic and Zune bug

Terje Mathisen <terje.mathi...@hda.hydro.com> writes:
> Muzaffer Kal wrote:
>> On Wed, 07 Jan 2009 06:10:03 -0600, r...@rpw3.org (Rob Warnock) wrote:
>>>    [If one starts the year on March 1st] the simplicity of the scheme
>>>    is quite amazing: a 400-year cycle not only starts 2000-03-01
>>>    (as it did 1600-03-01), it contains an even number of weeks: 20,871.

>> Is 20,871 supposed to be the number of weeks? If so, I'm not sure if
>> the latter portion of the above statement is correct.

> 146097 : 7 = 20871, so this is correct.

> It does mean that you can discard the number of initial 400-year
> cycles when using the day number to calculate the day of week.

Though I believe that makes it an integral number of weeks, not an
even number.

    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Kai Harrekilde-Petersen  
View profile  
 More options Jan 7, 2:44 pm
Newsgroups: comp.arch
From: Kai Harrekilde-Petersen <k...@harrekilde.dk>
Date: Wed, 07 Jan 2009 20:44:39 +0100
Local: Wed, Jan 7 2009 2:44 pm
Subject: Re: Date arithmetic and Zune bug

n...@cam.ac.uk writes:
> Where we live, the feeling "Thank God, at least the days are getting
> longer" is dominant, and must have been more so in the days of
> candles.  In places closer to the equator, the gloom of winter is
> FAR less marked, and consequentially the solstice is less important.

And you near live Cambridge? =8-|

Its' quite marked how just the ~500km from Copenhagen to Oslo and
again Oslo - Trondheim changes the amount of daylight both in the
winter and the summer.

Kai
--
Kai Harrekilde-Petersen <khp(at)harrekilde(dot)dk>


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
n...@cam.ac.uk  
View profile  
 More options Jan 7, 2:53 pm
Newsgroups: comp.arch
From: n...@cam.ac.uk
Date: Wed, 7 Jan 2009 19:53:29 +0000 (GMT)
Local: Wed, Jan 7 2009 2:53 pm
Subject: Re: Date arithmetic and Zune bug
In article <utz8a3o74....@harrekilde.dk>,
Kai Harrekilde-Petersen  <k...@harrekilde.dk> wrote:

Yes.  As many people have pointed out, the English festival of
Christmas has never had anything to do with Christianity, and
is merely a renamed festival of Yule.  That is what I meant by
"surviving Christianity" - it is the only one of the major
seasonal festivals that remains in anything approximating its
original state.

We don't know for certain that Yule was introduced into Europe by
the Germanic peoples, and was not originally a Celtic festival,
as far as I know.  Given the importance of Hogmanay, my personal
guess is the latter.

Regards,
Nick Maclaren.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
n...@cam.ac.uk  
View profile  
 More options Jan 7, 3:02 pm
Newsgroups: comp.arch
From: n...@cam.ac.uk
Date: Wed, 7 Jan 2009 20:02:06 +0000 (GMT)
Local: Wed, Jan 7 2009 3:02 pm
Subject: Re: Date arithmetic and Zune bug
In article <upriy3nq0....@harrekilde.dk>,
Kai Harrekilde-Petersen  <k...@harrekilde.dk> wrote:

>n...@cam.ac.uk writes:

>> Where we live, the feeling "Thank God, at least the days are getting
>> longer" is dominant, and must have been more so in the days of
>> candles.  In places closer to the equator, the gloom of winter is
>> FAR less marked, and consequentially the solstice is less important.

>And you near live Cambridge? =8-|

>Its' quite marked how just the ~500km from Copenhagen to Oslo and
>again Oslo - Trondheim changes the amount of daylight both in the
>winter and the summer.

Quite.  Britain's winters are gloomier than you might expect from
the latitude, so Cambridge and Copenhagen are probably comparable
in that respect.  But, before the rise of northern Europe, the
northernmost 'civilisation' was centred at 42 degrees north!

Regards,
Nick Maclaren.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Bernd Paysan  
View profile  
 More options Jan 7, 4:50 pm
Newsgroups: comp.arch
From: Bernd Paysan <bernd.pay...@gmx.de>
Date: Wed, 07 Jan 2009 22:50:59 +0100
Local: Wed, Jan 7 2009 4:50 pm
Subject: Re: Date arithmetic and Zune bug

Muzaffer Kal wrote:
> On Wed, 07 Jan 2009 06:10:03 -0600, r...@rpw3.org (Rob Warnock) wrote:
>>    [If one starts the year on March 1st] the simplicity of the scheme
>>    is quite amazing: a 400-year cycle not only starts 2000-03-01
>>    (as it did 1600-03-01), it contains an even number of weeks: 20,871.

> Is 20,871 supposed to be the number of weeks? If so, I'm not sure if
> the latter portion of the above statement is correct.

A 400-year cycle, no matter when you start and end it, contains exactly
20871 weeks or 146097 days. Starting it on 1600-3-1 simplifies the leap
year calculation slightly. Starting it on March 1st simplifies the month
calculation. Even though Augustus screwed up the original scheme, where a
division by 30.5 gave the correct month, he didn't screw up too badly. Now
a division by 30.6 gives the correct month (rounding still tricky, but with
the right offset, it works). There are 153 days from 3-1 to 8-1, and
another 153 days from 8-1 to 1-1 next year. The remaining 59 or 60 days
follow the same pattern: First month 31 days, next month less, so that
scheme works again.

So how to calculate the current year-month-day?

* year=floor(day/146097)*400 gives your base cycle start, day=day%146097
will be used further. (day+2)%7 gives day-of-the-week. First day of the
week is Monday (if your week starts on another day, change the offset).

* year+=min(floor(day/36524),3)*100 gives the century (you can't have a
century 4 here, it's just the hangover leap year in y2k); of course we keep
the rest day=day%36524 for further calculation (add 365 if the division
actually gave 4).

* year+=floor(day/1461)*4 breaks things down further, we keep day=day%1461.

* year+=min(floor(day/365),3) gives the current year, again we keep the
remainder day=day%365 as above (if min triggers, add 365).

* month=floor((day+31)*5/153). We keep floor(remainder/5) as day of the
month.

* Finally, we make the necessary corrections: month+=2, if month>12, year++,
month-=12.

No table necessary. I tested this with a fairly short Forth program:

\ convert day since 0-3-1 to ymd

: /mod3 ( n1 n2 -- r q )
    dup >r /mod dup 4 = IF  drop r@ + 3  THEN  rdrop ;

: day2dow ( day -- dow )
    2 + 7 mod ;

: day2ymd ( day -- y m d )
    146097 /mod 400 * swap
    36524 /mod3 100 * rot + swap
    1461 /mod 4 * rot + swap
    365 /mod3 rot + swap
    31 + 5 153 */mod swap 5 /
    >r 2 + dup 12 > IF  12 - swap 1+ swap  THEN
    r> 1+ ;

: ymd2day ( y m d -- day )  -rot
    2 - dup 0<= IF  12 + swap 1- swap  THEN
    153 5 */ 31 - swap
    4 /mod swap 365 * swap
    25 /mod swap 1461 * swap
    4 /mod swap 36524 * swap
    146097 * + + + + + ;

With floored division, this works even fine with negative numbers, just
remember that the year 0 really is 1BC. It is fairly trivial to extend this
little program to work correctly even before the October 15th, 1582 (or
whenever the switch happend according to the current locale).

--
Bernd Paysan
"If you want it done right, you have to do it yourself"
http://www.jwdt.com/~paysan/


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Messages 1 - 25 of 41   Newer >
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google