@@ -24,7 +24,7 @@ from frequencies cimport get_freq_code
24
24
from nattype cimport NPY_NAT
25
25
from np_datetime cimport (pandas_datetimestruct,
26
26
dtstruct_to_dt64, dt64_to_dtstruct,
27
- is_leapyear, days_per_month_table)
27
+ is_leapyear, days_per_month_table, dayofweek )
28
28
29
29
# ---------------------------------------------------------------------
30
30
# Constants
@@ -145,45 +145,44 @@ def apply_index_wraps(func):
145
145
# ---------------------------------------------------------------------
146
146
# Business Helpers
147
147
148
- cpdef int get_lastbday(int wkday , int days_in_month) :
148
+ cpdef int get_lastbday(int year , int month) nogil :
149
149
"""
150
150
Find the last day of the month that is a business day.
151
151
152
- (wkday, days_in_month) is the output from monthrange(year, month)
153
-
154
152
Parameters
155
153
----------
156
- wkday : int
157
- days_in_month : int
154
+ year : int
155
+ month : int
158
156
159
157
Returns
160
158
-------
161
159
last_bday : int
162
160
"""
161
+ cdef:
162
+ int wkday, days_in_month
163
+
164
+ wkday = dayofweek(year, month, 1 )
165
+ days_in_month = get_days_in_month(year, month)
163
166
return days_in_month - max (((wkday + days_in_month - 1 ) % 7 ) - 4 , 0 )
164
167
165
168
166
- cpdef int get_firstbday(int wkday , int days_in_month = 0 ) :
169
+ cpdef int get_firstbday(int year , int month) nogil :
167
170
"""
168
171
Find the first day of the month that is a business day.
169
172
170
- (wkday, days_in_month) is the output from monthrange(year, month)
171
-
172
173
Parameters
173
174
----------
174
- wkday : int
175
- days_in_month : int, default 0
175
+ year : int
176
+ month : int
176
177
177
178
Returns
178
179
-------
179
180
first_bday : int
180
-
181
- Notes
182
- -----
183
- `days_in_month` arg is a dummy so that this has the same signature as
184
- `get_lastbday`.
185
181
"""
186
- cdef int first
182
+ cdef:
183
+ int first, wkday
184
+
185
+ wkday = dayofweek(year, month, 1 )
187
186
first = 1
188
187
if wkday == 5 : # on Saturday
189
188
first = 3
@@ -556,52 +555,50 @@ def shift_months(int64_t[:] dtindex, int months, object day=None):
556
555
out[i] = dtstruct_to_dt64(& dts)
557
556
558
557
elif day == ' business_start' :
559
- for i in range (count):
560
- if dtindex[i] == NPY_NAT:
561
- out[i] = NPY_NAT
562
- continue
558
+ with nogil:
559
+ for i in range (count):
560
+ if dtindex[i] == NPY_NAT:
561
+ out[i] = NPY_NAT
562
+ continue
563
563
564
- dt64_to_dtstruct(dtindex[i], & dts)
565
- months_to_roll = months
566
- wkday, days_in_month = monthrange(dts.year, dts.month)
567
- compare_day = get_firstbday(wkday, days_in_month)
564
+ dt64_to_dtstruct(dtindex[i], & dts)
565
+ months_to_roll = months
566
+ compare_day = get_firstbday(dts.year, dts.month)
568
567
569
- if months_to_roll > 0 and dts.day < compare_day:
570
- months_to_roll -= 1
571
- elif months_to_roll <= 0 and dts.day > compare_day:
572
- # as if rolled forward already
573
- months_to_roll += 1
568
+ if months_to_roll > 0 and dts.day < compare_day:
569
+ months_to_roll -= 1
570
+ elif months_to_roll <= 0 and dts.day > compare_day:
571
+ # as if rolled forward already
572
+ months_to_roll += 1
574
573
575
- dts.year = year_add_months(dts, months_to_roll)
576
- dts.month = month_add_months(dts, months_to_roll)
574
+ dts.year = year_add_months(dts, months_to_roll)
575
+ dts.month = month_add_months(dts, months_to_roll)
577
576
578
- wkday, days_in_month = monthrange(dts.year, dts.month)
579
- dts.day = get_firstbday(wkday, days_in_month)
580
- out[i] = dtstruct_to_dt64(& dts)
577
+ dts.day = get_firstbday(dts.year, dts.month)
578
+ out[i] = dtstruct_to_dt64(& dts)
581
579
582
580
elif day == ' business_end' :
583
- for i in range (count):
584
- if dtindex[i] == NPY_NAT:
585
- out[i] = NPY_NAT
586
- continue
581
+ with nogil:
582
+ for i in range (count):
583
+ if dtindex[i] == NPY_NAT:
584
+ out[i] = NPY_NAT
585
+ continue
587
586
588
- dt64_to_dtstruct(dtindex[i], & dts)
589
- months_to_roll = months
590
- wkday, days_in_month = monthrange(dts.year, dts.month)
591
- compare_day = get_lastbday(wkday, days_in_month)
587
+ dt64_to_dtstruct(dtindex[i], & dts)
588
+ months_to_roll = months
589
+ compare_day = get_lastbday(dts.year, dts.month)
592
590
593
- if months_to_roll > 0 and dts.day < compare_day:
594
- months_to_roll -= 1
595
- elif months_to_roll <= 0 and dts.day > compare_day:
596
- # as if rolled forward already
597
- months_to_roll += 1
591
+ if months_to_roll > 0 and dts.day < compare_day:
592
+ months_to_roll -= 1
593
+ elif months_to_roll <= 0 and dts.day > compare_day:
594
+ # as if rolled forward already
595
+ months_to_roll += 1
598
596
599
- dts.year = year_add_months(dts, months_to_roll)
600
- dts.month = month_add_months(dts, months_to_roll)
597
+ dts.year = year_add_months(dts, months_to_roll)
598
+ dts.month = month_add_months(dts, months_to_roll)
601
599
602
- wkday, days_in_month = monthrange(dts.year, dts.month)
603
- dts.day = get_lastbday(wkday, days_in_month)
604
- out[i] = dtstruct_to_dt64(& dts)
600
+ dts.day = get_lastbday(dts.year, dts.month)
601
+ out[i] = dtstruct_to_dt64(& dts)
605
602
606
603
else :
607
604
raise ValueError (" day must be None, 'start', 'end', "
@@ -635,7 +632,7 @@ cpdef datetime shift_month(datetime stamp, int months, object day_opt=None):
635
632
"""
636
633
cdef:
637
634
int year, month, day
638
- int wkday, days_in_month, dy
635
+ int days_in_month, dy
639
636
640
637
dy = (stamp.month + months) // 12
641
638
month = (stamp.month + months) % 12
@@ -645,20 +642,21 @@ cpdef datetime shift_month(datetime stamp, int months, object day_opt=None):
645
642
dy -= 1
646
643
year = stamp.year + dy
647
644
648
- wkday, days_in_month = monthrange(year, month)
649
645
if day_opt is None :
646
+ days_in_month = get_days_in_month(year, month)
650
647
day = min (stamp.day, days_in_month)
651
648
elif day_opt == ' start' :
652
649
day = 1
653
650
elif day_opt == ' end' :
654
- day = days_in_month
651
+ day = get_days_in_month(year, month)
655
652
elif day_opt == ' business_start' :
656
653
# first business day of month
657
- day = get_firstbday(wkday, days_in_month )
654
+ day = get_firstbday(year, month )
658
655
elif day_opt == ' business_end' :
659
656
# last business day of month
660
- day = get_lastbday(wkday, days_in_month )
657
+ day = get_lastbday(year, month )
661
658
elif is_integer_object(day_opt):
659
+ days_in_month = get_days_in_month(year, month)
662
660
day = min (day_opt, days_in_month)
663
661
else :
664
662
raise ValueError (day_opt)
@@ -691,22 +689,22 @@ cpdef int get_day_of_month(datetime other, day_opt) except? -1:
691
689
692
690
"""
693
691
cdef:
694
- int wkday, days_in_month
692
+ int days_in_month
695
693
696
694
if day_opt == ' start' :
697
695
return 1
698
-
699
- wkday, days_in_month = monthrange(other.year, other.month)
700
- if day_opt == ' end' :
696
+ elif day_opt == ' end' :
697
+ days_in_month = get_days_in_month(other.year, other.month)
701
698
return days_in_month
702
699
elif day_opt == ' business_start' :
703
700
# first business day of month
704
- return get_firstbday(wkday, days_in_month )
701
+ return get_firstbday(other.year, other.month )
705
702
elif day_opt == ' business_end' :
706
703
# last business day of month
707
- return get_lastbday(wkday, days_in_month )
704
+ return get_lastbday(other.year, other.month )
708
705
elif is_integer_object(day_opt):
709
- day = min (day_opt, days_in_month)
706
+ days_in_month = get_days_in_month(other.year, other.month)
707
+ return min (day_opt, days_in_month)
710
708
elif day_opt is None :
711
709
# Note: unlike `shift_month`, get_day_of_month does not
712
710
# allow day_opt = None
0 commit comments