[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/