@@ -806,24 +806,22 @@ cdef int64_t get_period_ordinal(npy_datetimestruct *dts, int freq) nogil:
806
806
return unix_date_to_week(unix_date, freq - FR_WK)
807
807
808
808
809
- cdef void get_date_info(int64_t ordinal, int freq,
810
- npy_datetimestruct * dts) nogil:
809
+ cdef void get_date_info(int64_t ordinal, int freq, npy_datetimestruct * dts) nogil:
811
810
cdef:
812
- int64_t unix_date
813
- double abstime
811
+ int64_t unix_date, nanos
812
+ npy_datetimestruct dts2
814
813
815
814
unix_date = get_unix_date(ordinal, freq)
816
- abstime = get_abs_time(freq, unix_date, ordinal)
817
-
818
- while abstime < 0 :
819
- abstime += 86400
820
- unix_date -= 1
815
+ nanos = get_time_nanos(freq, unix_date, ordinal)
821
816
822
- while abstime >= 86400 :
823
- abstime -= 86400
824
- unix_date += 1
817
+ pandas_datetime_to_datetimestruct(unix_date, NPY_FR_D, dts)
825
818
826
- date_info_from_days_and_time(dts, unix_date, abstime)
819
+ dt64_to_dtstruct(nanos, & dts2)
820
+ dts.hour = dts2.hour
821
+ dts.min = dts2.min
822
+ dts.sec = dts2.sec
823
+ dts.us = dts2.us
824
+ dts.ps = dts2.ps
827
825
828
826
829
827
cdef int64_t get_unix_date(int64_t period_ordinal, int freq) nogil:
@@ -855,74 +853,50 @@ cdef int64_t get_unix_date(int64_t period_ordinal, int freq) nogil:
855
853
856
854
857
855
@cython.cdivision
858
- cdef void date_info_from_days_and_time(npy_datetimestruct * dts,
859
- int64_t unix_date,
860
- double abstime) nogil:
856
+ cdef int64_t get_time_nanos(int freq, int64_t unix_date, int64_t ordinal) nogil:
861
857
"""
862
- Set the instance's value using the given date and time.
858
+ Find the number of nanoseconds after midnight on the given unix_date
859
+ that the ordinal represents in the given frequency.
863
860
864
861
Parameters
865
862
----------
866
- dts : npy_datetimestruct*
863
+ freq : int
867
864
unix_date : int64_t
868
- days elapsed since datetime(1970, 1, 1)
869
- abstime : double
870
- seconds elapsed since beginning of day described by unix_date
865
+ ordinal : int64_t
871
866
872
- Notes
873
- -----
874
- Updates dts inplace
867
+ Returns
868
+ -------
869
+ int64_t
875
870
"""
876
871
cdef:
877
- int inttime
878
- int hour, minute
879
- double second, subsecond_fraction
880
-
881
- # Bounds check
882
- # The calling function is responsible for ensuring that
883
- # abstime >= 0.0 and abstime <= 86400
884
-
885
- # Calculate the date
886
- pandas_datetime_to_datetimestruct(unix_date, NPY_FR_D, dts)
872
+ int64_t sub, factor
887
873
888
- # Calculate the time
889
- inttime = < int > abstime
890
- hour = inttime / 3600
891
- minute = (inttime % 3600 ) / 60
892
- second = abstime - < double > (hour * 3600 + minute * 60 )
874
+ freq = get_freq_group(freq)
893
875
894
- dts.hour = hour
895
- dts.min = minute
896
- dts.sec = < int > second
897
-
898
- subsecond_fraction = second - dts.sec
899
- dts.us = int ((subsecond_fraction) * 1e6 )
900
- dts.ps = int (((subsecond_fraction) * 1e6 - dts.us) * 1e6 )
876
+ if freq <= FR_DAY:
877
+ return 0
901
878
879
+ elif freq == FR_NS:
880
+ factor = 1
902
881
903
- @cython.cdivision
904
- cdef double get_abs_time(int freq, int64_t unix_date, int64_t ordinal) nogil:
905
- cdef:
906
- int freq_index, day_index, base_index
907
- int64_t per_day, start_ord
908
- double unit, result
882
+ elif freq == FR_US:
883
+ factor = 10 ** 3
909
884
910
- if freq <= FR_DAY :
911
- return 0
885
+ elif freq == FR_MS :
886
+ factor = 10 ** 6
912
887
913
- freq_index = freq // 1000
914
- day_index = FR_DAY // 1000
915
- base_index = FR_SEC // 1000
888
+ elif freq == FR_SEC:
889
+ factor = 10 ** 9
916
890
917
- per_day = get_daytime_conversion_factor(day_index, freq_index)
918
- unit = get_daytime_conversion_factor(freq_index, base_index)
891
+ elif freq == FR_MIN:
892
+ factor = 10 ** 9 * 60
919
893
920
- if base_index < freq_index:
921
- unit = 1 / unit
894
+ else :
895
+ # We must have freq == FR_HR
896
+ factor = 10 ** 9 * 3600
922
897
923
- start_ord = unix_date * per_day
924
- result = < double > (unit * (ordinal - start_ord))
925
- return result
898
+ sub = ordinal - unix_date * 24 * 3600 * 10 ** 9 / factor
899
+ return sub * factor
926
900
927
901
928
902
cdef int get_yq(int64_t ordinal, int freq, int * quarter, int * year):
@@ -1176,11 +1150,7 @@ cdef int64_t period_ordinal_to_dt64(int64_t ordinal, int freq) except? -1:
1176
1150
if ordinal == NPY_NAT:
1177
1151
return NPY_NAT
1178
1152
1179
- if freq == 11000 :
1180
- # Microsecond, avoid get_date_info to prevent floating point errors
1181
- pandas_datetime_to_datetimestruct(ordinal, NPY_FR_us, & dts)
1182
- else :
1183
- get_date_info(ordinal, freq, & dts)
1153
+ get_date_info(ordinal, freq, & dts)
1184
1154
1185
1155
check_dts_bounds(& dts)
1186
1156
return dtstruct_to_dt64(& dts)
0 commit comments