2
2
"""
3
3
Cython implementations of functions resembling the stdlib calendar module
4
4
"""
5
-
6
5
cimport cython
7
6
from numpy cimport (
8
7
int32_t,
@@ -19,7 +18,7 @@ cdef int32_t* days_per_month_array = [
19
18
31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 ,
20
19
31 , 29 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 ]
21
20
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 ]
23
22
24
23
# The first 13 entries give the month days elapsed as of the first of month N
25
24
# (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:
76
75
77
76
@ cython.wraparound (False )
78
77
@ 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:
81
91
"""
82
92
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.
84
94
85
95
0 represents Monday. See [1]_.
86
96
@@ -103,16 +113,27 @@ cdef int dayofweek(int y, int m, int d) nogil:
103
113
[1] https://docs.python.org/3/library/calendar.html#calendar.weekday
104
114
105
115
[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
107
117
"""
118
+ # Note: this particular implementation comes from
119
+ # http://berndt-schwerdtfeger.de/wp-content/uploads/pdf/cal.pdf
108
120
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
116
137
117
138
cdef bint is_leapyear(int64_t year) nogil:
118
139
"""
0 commit comments