@@ -357,18 +357,15 @@ cdef int64_t asfreq_QtoDT(int64_t ordinal, asfreq_info *af_info) nogil:
357
357
return upsample_daytime(unix_date, af_info)
358
358
359
359
360
- cdef void MtoD_ym(int64_t ordinal, int * year, int * month) nogil:
361
- year[0 ] = ordinal // 12 + 1970
362
- month[0 ] = ordinal % 12 + 1
363
-
364
-
365
360
cdef int64_t asfreq_MtoDT(int64_t ordinal, asfreq_info * af_info) nogil:
366
361
cdef:
367
362
int64_t unix_date
368
363
int year, month
369
364
370
365
ordinal += af_info.is_end
371
- MtoD_ym(ordinal, & year, & month)
366
+
367
+ year = ordinal // 12 + 1970
368
+ month = ordinal % 12 + 1
372
369
373
370
unix_date = unix_date_from_ymd(year, month, 1 )
374
371
unix_date -= af_info.is_end
@@ -449,10 +446,7 @@ cdef int64_t asfreq_DTtoA(int64_t ordinal, asfreq_info *af_info) nogil:
449
446
450
447
ordinal = downsample_daytime(ordinal, af_info)
451
448
pandas_datetime_to_datetimestruct(ordinal, NPY_FR_D, & dts)
452
- if dts.month > af_info.to_end:
453
- return < int64_t> (dts.year + 1 - 1970 )
454
- else :
455
- return < int64_t> (dts.year - 1970 )
449
+ return dts_to_year_ordinal(& dts, af_info.to_end)
456
450
457
451
458
452
cdef int DtoQ_yq(int64_t ordinal, asfreq_info * af_info, npy_datetimestruct* dts) nogil:
@@ -483,7 +477,7 @@ cdef int64_t asfreq_DTtoM(int64_t ordinal, asfreq_info *af_info) nogil:
483
477
484
478
ordinal = downsample_daytime(ordinal, af_info)
485
479
pandas_datetime_to_datetimestruct(ordinal, NPY_FR_D, & dts)
486
- return < int64_t > (( dts.year - 1970 ) * 12 + dts.month - 1 )
480
+ return dts_to_month_ordinal( & dts)
487
481
488
482
489
483
cdef int64_t asfreq_DTtoW(int64_t ordinal, asfreq_info * af_info) nogil:
@@ -716,6 +710,40 @@ cdef int64_t unix_date_from_ymd(int year, int month, int day) nogil:
716
710
return unix_date
717
711
718
712
713
+ cdef inline int64_t dts_to_month_ordinal(npy_datetimestruct* dts) nogil:
714
+ # AKA: use npy_datetimestruct_to_datetime(NPY_FR_M, &dts)
715
+ return < int64_t> ((dts.year - 1970 ) * 12 + dts.month - 1 )
716
+
717
+
718
+ cdef inline int64_t dts_to_year_ordinal(npy_datetimestruct * dts, int to_end) nogil:
719
+ cdef:
720
+ int64_t result
721
+
722
+ result = npy_datetimestruct_to_datetime(NPY_DATETIMEUNIT.NPY_FR_Y, dts)
723
+ if dts.month > to_end:
724
+ return result + 1
725
+ else :
726
+ return result
727
+
728
+
729
+ cdef inline int64_t dts_to_qtr_ordinal(npy_datetimestruct* dts, int to_end) nogil:
730
+ cdef:
731
+ int quarter
732
+
733
+ adjust_dts_for_qtr(dts, to_end)
734
+ quarter = month_to_quarter(dts.month)
735
+ return < int64_t> ((dts.year - 1970 ) * 4 + quarter - 1 )
736
+
737
+
738
+ cdef inline int get_anchor_month(int freq, int freq_group) nogil:
739
+ cdef:
740
+ int fmonth
741
+ fmonth = freq - freq_group
742
+ if fmonth == 0 :
743
+ fmonth = 12
744
+ return fmonth
745
+
746
+
719
747
# specifically _dont_ use cdvision or else ordinals near -1 are assigned to
720
748
# incorrect dates GH#19643
721
749
@ cython.cdivision (False )
@@ -740,23 +768,12 @@ cdef int64_t get_period_ordinal(npy_datetimestruct *dts, int freq) nogil:
740
768
freq_group = get_freq_group(freq)
741
769
742
770
if freq_group == FR_ANN:
743
- fmonth = freq - FR_ANN
744
- if fmonth == 0 :
745
- fmonth = 12
746
-
747
- mdiff = dts.month - fmonth
748
- if mdiff <= 0 :
749
- return dts.year - 1970
750
- else :
751
- return dts.year - 1970 + 1
771
+ fmonth = get_anchor_month(freq, freq_group)
772
+ return dts_to_year_ordinal(dts, fmonth)
752
773
753
774
elif freq_group == FR_QTR:
754
- fmonth = freq - FR_QTR
755
- if fmonth == 0 :
756
- fmonth = 12
757
-
758
- mdiff = dts.month - fmonth + 12
759
- return (dts.year - 1970 ) * 4 + (mdiff - 1 ) // 3
775
+ fmonth = get_anchor_month(freq, freq_group)
776
+ return dts_to_qtr_ordinal(dts, fmonth)
760
777
761
778
elif freq_group == FR_WK:
762
779
unix_date = npy_datetimestruct_to_datetime(NPY_FR_D, dts)
0 commit comments