22"""
33Cython implementations of functions resembling the stdlib calendar module
44"""
5-
65cimport cython
76from numpy cimport (
87 int32_t,
@@ -19,7 +18,7 @@ cdef int32_t* days_per_month_array = [
1918 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 ,
2019 31 , 29 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 ]
2120
22- cdef int * sakamoto_arr = [0 , 3 , 2 , 5 , 0 , 3 , 5 , 1 , 4 , 6 , 2 , 4 ]
21+ cdef int * em = [0 , 0 , 31 , 59 , 90 , 120 , 151 , 181 , 212 , 243 , 273 , 304 , 334 ]
2322
2423# The first 13 entries give the month days elapsed as of the first of month N
2524# (or the total number of days in the year for N=13) in non-leap years.
@@ -76,11 +75,22 @@ cpdef int32_t get_days_in_month(int year, Py_ssize_t month) nogil:
7675
7776@ cython.wraparound (False )
7877@ cython.boundscheck (False )
79- @cython.cdivision
80- cdef int dayofweek(int y, int m, int d) nogil:
78+ @ cython.cdivision (True )
79+ cdef long quot(long a , long b) noexcept nogil:
80+ cdef long x
81+ x = a/ b
82+ if (a < 0 ):
83+ x -= (a % b != 0 )
84+ return x
85+
86+
87+ @ cython.wraparound (False )
88+ @ cython.boundscheck (False )
89+ @ cython.cdivision (True )
90+ cdef int dayofweek(int y, int m, int d) noexcept nogil:
8191 """
8292 Find the day of week for the date described by the Y/M/D triple y, m, d
83- using Sakamoto's method, from wikipedia.
93+ using Gauss' method, from wikipedia.
8494
8595 0 represents Monday. See [1]_.
8696
@@ -103,16 +113,27 @@ cdef int dayofweek(int y, int m, int d) nogil:
103113 [1] https://docs.python.org/3/library/calendar.html#calendar.weekday
104114
105115 [2] https://en.wikipedia.org/wiki/\
106- Determination_of_the_day_of_the_week#Sakamoto.27s_methods
116+ Determination_of_the_day_of_the_week#Gauss's_algorithm
107117 """
118+ # Note: this particular implementation comes from
119+ # http://berndt-schwerdtfeger.de/wp-content/uploads/pdf/cal.pdf
108120 cdef:
109- int day
110-
111- y -= m < 3
112- day = (y + y / 4 - y / 100 + y / 400 + sakamoto_arr[m - 1 ] + d) % 7
113- # convert to python day
114- return (day + 6 ) % 7
115-
121+ long c
122+ int g
123+ int f
124+ int e
125+
126+ if (m < 3 ):
127+ y -= 1
128+
129+ c = quot(y, 100 )
130+ g = y - c * 100
131+ f = 5 * (c - quot(c, 4 ) * 4 )
132+ e = em[m]
133+
134+ if (m > 2 ):
135+ e -= 1
136+ return (- 1 + d + e + f + g + g/ 4 ) % 7
116137
117138cdef bint is_leapyear(int64_t year) nogil:
118139 """
0 commit comments