@@ -562,6 +562,16 @@ void pandas_datetime_to_datetimestruct(npy_datetime val, PANDAS_DATETIMEUNIT fr,
562
562
convert_datetime_to_datetimestruct (& meta , val , result );
563
563
}
564
564
565
+ void pandas_timedelta_to_timedeltastruct (npy_timedelta val , PANDAS_DATETIMEUNIT fr ,
566
+ pandas_timedeltastruct * result ) {
567
+ pandas_datetime_metadata meta ;
568
+
569
+ meta .base = fr ;
570
+ meta .num - 1 ;
571
+
572
+ convert_timedelta_to_timedeltastruct (& meta , val , result );
573
+ }
574
+
565
575
PANDAS_DATETIMEUNIT get_datetime64_unit (PyObject * obj ) {
566
576
return (PANDAS_DATETIMEUNIT )((PyDatetimeScalarObject * )obj )-> obmeta .base ;
567
577
}
@@ -684,6 +694,7 @@ int convert_datetimestruct_to_datetime(pandas_datetime_metadata *meta,
684
694
return 0 ;
685
695
}
686
696
697
+
687
698
/*
688
699
* This provides the casting rules for the TIMEDELTA data type units.
689
700
*
@@ -980,3 +991,108 @@ int convert_datetime_to_datetimestruct(pandas_datetime_metadata *meta,
980
991
981
992
return 0 ;
982
993
}
994
+
995
+ /*
996
+ * Converts a timedelta from a timedeltastruct to a timedelta based
997
+ * on some metadata. The timedelta is assumed to be valid.
998
+ *
999
+ * Returns 0 on success, -1 on failure.
1000
+ */
1001
+ int convert_timedelta_to_timedeltastruct (pandas_timedelta_metadata * meta ,
1002
+ npy_timedelta td ,
1003
+ pandas_timedeltastruct * out ) {
1004
+
1005
+ npy_int64 perday ;
1006
+ npy_int64 frac ;
1007
+ npy_int64 sfrac ;
1008
+ npy_int64 ifrac ;
1009
+ int sign ;
1010
+ npy_int64 DAY_NS = 86400000000000LL ;
1011
+
1012
+ /* Initialize the output to all zeros */
1013
+ memset (out , 0 , sizeof (pandas_timedeltastruct ));
1014
+
1015
+ switch (meta -> base ) {
1016
+ case PANDAS_FR_ns :
1017
+
1018
+ // put frac in seconds
1019
+ if (td < 0 && td % (1000LL * 1000LL * 1000LL ) != 0 )
1020
+ frac = td / (1000LL * 1000LL * 1000LL ) - 1 ;
1021
+ else
1022
+ frac = td / (1000LL * 1000LL * 1000LL );
1023
+
1024
+ if (frac < 0 ) {
1025
+ sign = -1 ;
1026
+
1027
+ // even fraction
1028
+ if ((- frac % 86400LL ) != 0 ) {
1029
+ out -> days = - frac / 86400LL + 1 ;
1030
+ frac += 86400LL * out -> days ;
1031
+ } else {
1032
+ frac = - frac ;
1033
+ }
1034
+ } else {
1035
+ sign = 1 ;
1036
+ out -> days = 0 ;
1037
+ }
1038
+
1039
+ if (frac >= 86400 ) {
1040
+ out -> days += frac / 86400LL ;
1041
+ frac -= out -> days * 86400LL ;
1042
+ }
1043
+
1044
+ if (frac >= 3600 ) {
1045
+ out -> hrs = frac / 3600LL ;
1046
+ frac -= out -> hrs * 3600LL ;
1047
+ } else {
1048
+ out -> hrs = 0 ;
1049
+ }
1050
+
1051
+ if (frac >= 60 ) {
1052
+ out -> min = frac / 60LL ;
1053
+ frac -= out -> min * 60LL ;
1054
+ } else {
1055
+ out -> min = 0 ;
1056
+ }
1057
+
1058
+ if (frac >= 0 ) {
1059
+ out -> sec = frac ;
1060
+ frac -= out -> sec ;
1061
+ } else {
1062
+ out -> sec = 0 ;
1063
+ }
1064
+
1065
+ sfrac = (out -> hrs * 3600LL + out -> min * 60LL
1066
+ + out -> sec ) * (1000LL * 1000LL * 1000LL );
1067
+
1068
+ if (sign < 0 )
1069
+ out -> days = - out -> days ;
1070
+
1071
+ ifrac = td - (out -> days * DAY_NS + sfrac );
1072
+
1073
+ if (ifrac != 0 ) {
1074
+ out -> ms = ifrac / (1000LL * 1000LL );
1075
+ ifrac -= out -> ms * 1000LL * 1000LL ;
1076
+ out -> us = ifrac / 1000LL ;
1077
+ ifrac -= out -> us * 1000LL ;
1078
+ out -> ns = ifrac ;
1079
+ } else {
1080
+ out -> ms = 0 ;
1081
+ out -> us = 0 ;
1082
+ out -> ns = 0 ;
1083
+ }
1084
+
1085
+ out -> seconds = out -> hrs * 3600 + out -> min * 60 + out -> sec ;
1086
+ out -> microseconds = out -> ms * 1000 + out -> us ;
1087
+ out -> nanoseconds = out -> ns ;
1088
+ break ;
1089
+
1090
+ default :
1091
+ PyErr_SetString (PyExc_RuntimeError ,
1092
+ "NumPy datetime metadata is corrupted with invalid "
1093
+ "base unit" );
1094
+ return -1 ;
1095
+ }
1096
+
1097
+ return 0 ;
1098
+ }
0 commit comments