[Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.28,1.29

M.-A. Lemburg mal@lemburg.com
Mon, 04 Mar 2002 10:54:31 +0100


Tim Peters wrote:
> 
> Index: datetime.py
> ===================================================================
> RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v
> retrieving revision 1.28
> retrieving revision 1.29
> diff -C2 -d -r1.28 -r1.29
> *** datetime.py 3 Mar 2002 23:16:21 -0000       1.28
> --- datetime.py 4 Mar 2002 00:14:54 -0000       1.29
> ***************
> *** 71,94 ****
>       "ordinal -> (year, month, day), considering 01-Jan-0001 as day 1."
> 
> !     n400 = (n-1) // _DI400Y  # number of 400-year blocks preceding
> !     year = n400 * 400 + 1
> !     n -= n400 * _DI400Y
> 
> !     more = n // 365
> !     dby = _days_before_year(more + 1)
> !     if dby >= n:
> !         dby -= _days_in_year(more)
> !         more -= 1
> !     year += more
> !     assert n > dby
> !     n -= dby
> 
>       month = min(n//29 + 1, 12)
> !     dbm = _days_before_month(month, year)
> !     if dbm >= n:
>           month -= 1
> !         dbm -= _days_in_month(month, year)
> !     assert n > dbm
> !     return year, month, n-dbm
> 
>   # Month and day names.  For localized versions, see the calendar module.
> --- 71,126 ----
>       "ordinal -> (year, month, day), considering 01-Jan-0001 as day 1."
> 
> !     # n is a 1-based index, starting at 1-Jan-1.  The pattern of leap years
> !     # repeats exactly every 400 years.  The basic strategy is to find the
> !     # closest 400-year boundary at or before n, then work with the offset
> !     # from that boundary to n.  Life is much clearer if we subtract 1 from
> !     # n first -- then the values of n at 400-year boundaries are exactly
> !     # those divisible by _DI400Y:
> !     #
> !     #     D  M   Y            n              n-1
> !     #     -- --- ----        ----------     ----------------
> !     #     31 Dec -400        -_DI400Y       -_DI400Y -1
> !     #      1 Jan -399         -_DI400Y +1   -_DI400Y      400-year boundary
> !     #     ...
> !     #     30 Dec  000        -1             -2
> !     #     31 Dec  000         0             -1
> !     #      1 Jan  001         1              0            400-year boundary
> !     #      2 Jan  001         2              1
> !     #      3 Jan  001         3              2
> !     #     ...
> !     #     31 Dec  400         _DI400Y        _DI400Y -1
> !     #      1 Jan  401         _DI400Y +1     _DI400Y      400-year boundary
> !     n -= 1
> !     n400, n = divmod(n, _DI400Y)
> !     year = n400 * 400 + 1   # ..., -399, 1, 401, ...
> 
> !     # Now n is the (non-negative) offset, in days, from January 1 of year, to
> !     # the desired date.  First compute how many whole years precede the
> !     # desired date.  Dividing by 365 gives an upper bound quickly, and it's
> !     # easy to show that it's either exact or one too large (note that this
> !     # relies on that n < _DI400Y; if we did this before factoring out a close
> !     # 400-year boundary, there's no bound on how far off n//365 could be).
> !     whole_years_preceding = n // 365
> !     exact_days = _days_before_year(whole_years_preceding + 1)
> !     if exact_days > n:  # estimate is too large
> !         exact_days -= _days_in_year(whole_years_preceding)
> !         whole_years_preceding -= 1
> !     assert 0 <= exact_days <= n
> !     year += whole_years_preceding
> !     n -= exact_days
> 
> +     # Now the year is correct, and n is the offset from January 1.  We find
> +     # the month via another estimate that's either exact or one too large.
>       month = min(n//29 + 1, 12)
> !     exact_days = _days_before_month(month, year)
> !     if exact_days > n:  # estimate is too large
>           month -= 1
> !         exact_days -= _days_in_month(month, year)
> !     assert 0 <= exact_days <= n
> !     n -= exact_days
> !
> !     # Now the year and month are correct, and n is the offset from the
> !     # start of that month:  we're done!
> !     return year, month, n+1

Looks a lot like what I do in mxDateTime.c :-)

-- 
Marc-Andre Lemburg
CEO eGenix.com Software GmbH
______________________________________________________________________
Company & Consulting:                           http://www.egenix.com/
Python Software:                   http://www.egenix.com/files/python/