MCPcopy Index your code
hub / github.com/python/cpython / _ord2ymd

Function _ord2ymd

Lib/_pydatetime.py:93–153  ·  view source on GitHub ↗

ordinal -> (year, month, day), considering 01-Jan-0001 as day 1.

(n)

Source from the content-addressed store, hash-verified

91assert _DI100Y == 25 * _DI4Y - 1
92
93def _ord2ymd(n):
94 "ordinal -> (year, month, day), considering 01-Jan-0001 as day 1."
95
96 # n is a 1-based index, starting at 1-Jan-1. The pattern of leap years
97 # repeats exactly every 400 years. The basic strategy is to find the
98 # closest 400-year boundary at or before n, then work with the offset
99 # from that boundary to n. Life is much clearer if we subtract 1 from
100 # n first -- then the values of n at 400-year boundaries are exactly
101 # those divisible by _DI400Y:
102 #
103 # D M Y n n-1
104 # -- --- ---- ---------- ----------------
105 # 31 Dec -400 -_DI400Y -_DI400Y -1
106 # 1 Jan -399 -_DI400Y +1 -_DI400Y 400-year boundary
107 # ...
108 # 30 Dec 000 -1 -2
109 # 31 Dec 000 0 -1
110 # 1 Jan 001 1 0 400-year boundary
111 # 2 Jan 001 2 1
112 # 3 Jan 001 3 2
113 # ...
114 # 31 Dec 400 _DI400Y _DI400Y -1
115 # 1 Jan 401 _DI400Y +1 _DI400Y 400-year boundary
116 n -= 1
117 n400, n = divmod(n, _DI400Y)
118 year = n400 * 400 + 1 # ..., -399, 1, 401, ...
119
120 # Now n is the (non-negative) offset, in days, from January 1 of year, to
121 # the desired date. Now compute how many 100-year cycles precede n.
122 # Note that it's possible for n100 to equal 4! In that case 4 full
123 # 100-year cycles precede the desired day, which implies the desired
124 # day is December 31 at the end of a 400-year cycle.
125 n100, n = divmod(n, _DI100Y)
126
127 # Now compute how many 4-year cycles precede it.
128 n4, n = divmod(n, _DI4Y)
129
130 # And now how many single years. Again n1 can be 4, and again meaning
131 # that the desired day is December 31 at the end of the 4-year cycle.
132 n1, n = divmod(n, 365)
133
134 year += n100 * 100 + n4 * 4 + n1
135 if n1 == 4 or n100 == 4:
136 assert n == 0
137 return year-1, 12, 31
138
139 # Now the year is correct, and n is the offset from January 1. We find
140 # the month via an estimate that's either exact or one too large.
141 leapyear = n1 == 3 and (n4 != 24 or n100 == 3)
142 assert leapyear == _is_leap(year)
143 month = (n + 50) >> 5
144 preceding = _DAYS_BEFORE_MONTH[month] + (month > 2 and leapyear)
145 if preceding > n: # estimate is too large
146 month -= 1
147 preceding -= _DAYS_IN_MONTH[month] + (month == 2 and leapyear)
148 n -= preceding
149 assert 0 <= n < _days_in_month(year, month)
150

Callers 2

_isoweek_to_gregorianFunction · 0.85
fromordinalMethod · 0.85

Calls 2

_is_leapFunction · 0.85
_days_in_monthFunction · 0.85

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…