@@ -562,6 +562,17 @@ 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 ,
566
+ PANDAS_DATETIMEUNIT fr ,
567
+ pandas_timedeltastruct * result ) {
568
+ pandas_datetime_metadata meta ;
569
+
570
+ meta .base = fr ;
571
+ meta .num - 1 ;
572
+
573
+ convert_timedelta_to_timedeltastruct (& meta , val , result );
574
+ }
575
+
565
576
PANDAS_DATETIMEUNIT get_datetime64_unit (PyObject * obj ) {
566
577
return (PANDAS_DATETIMEUNIT )((PyDatetimeScalarObject * )obj )-> obmeta .base ;
567
578
}
@@ -980,3 +991,107 @@ 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
+ npy_int64 perday ;
1005
+ npy_int64 frac ;
1006
+ npy_int64 sfrac ;
1007
+ npy_int64 ifrac ;
1008
+ int sign ;
1009
+ npy_int64 DAY_NS = 86400000000000LL ;
1010
+
1011
+ /* Initialize the output to all zeros */
1012
+ memset (out , 0 , sizeof (pandas_timedeltastruct ));
1013
+
1014
+ switch (meta -> base ) {
1015
+ case PANDAS_FR_ns :
1016
+
1017
+ // put frac in seconds
1018
+ if (td < 0 && td % (1000LL * 1000LL * 1000LL ) != 0 )
1019
+ frac = td / (1000LL * 1000LL * 1000LL ) - 1 ;
1020
+ else
1021
+ frac = td / (1000LL * 1000LL * 1000LL );
1022
+
1023
+ if (frac < 0 ) {
1024
+ sign = -1 ;
1025
+
1026
+ // even fraction
1027
+ if ((- frac % 86400LL ) != 0 ) {
1028
+ out -> days = - frac / 86400LL + 1 ;
1029
+ frac += 86400LL * out -> days ;
1030
+ } else {
1031
+ frac = - frac ;
1032
+ }
1033
+ } else {
1034
+ sign = 1 ;
1035
+ out -> days = 0 ;
1036
+ }
1037
+
1038
+ if (frac >= 86400 ) {
1039
+ out -> days += frac / 86400LL ;
1040
+ frac -= out -> days * 86400LL ;
1041
+ }
1042
+
1043
+ if (frac >= 3600 ) {
1044
+ out -> hrs = frac / 3600LL ;
1045
+ frac -= out -> hrs * 3600LL ;
1046
+ } else {
1047
+ out -> hrs = 0 ;
1048
+ }
1049
+
1050
+ if (frac >= 60 ) {
1051
+ out -> min = frac / 60LL ;
1052
+ frac -= out -> min * 60LL ;
1053
+ } else {
1054
+ out -> min = 0 ;
1055
+ }
1056
+
1057
+ if (frac >= 0 ) {
1058
+ out -> sec = frac ;
1059
+ frac -= out -> sec ;
1060
+ } else {
1061
+ out -> sec = 0 ;
1062
+ }
1063
+
1064
+ sfrac = (out -> hrs * 3600LL + out -> min * 60LL
1065
+ + out -> sec ) * (1000LL * 1000LL * 1000LL );
1066
+
1067
+ if (sign < 0 )
1068
+ out -> days = - out -> days ;
1069
+
1070
+ ifrac = td - (out -> days * DAY_NS + sfrac );
1071
+
1072
+ if (ifrac != 0 ) {
1073
+ out -> ms = ifrac / (1000LL * 1000LL );
1074
+ ifrac -= out -> ms * 1000LL * 1000LL ;
1075
+ out -> us = ifrac / 1000LL ;
1076
+ ifrac -= out -> us * 1000LL ;
1077
+ out -> ns = ifrac ;
1078
+ } else {
1079
+ out -> ms = 0 ;
1080
+ out -> us = 0 ;
1081
+ out -> ns = 0 ;
1082
+ }
1083
+
1084
+ out -> seconds = out -> hrs * 3600 + out -> min * 60 + out -> sec ;
1085
+ out -> microseconds = out -> ms * 1000 + out -> us ;
1086
+ out -> nanoseconds = out -> ns ;
1087
+ break ;
1088
+
1089
+ default :
1090
+ PyErr_SetString (PyExc_RuntimeError ,
1091
+ "NumPy datetime metadata is corrupted with invalid "
1092
+ "base unit" );
1093
+ return -1 ;
1094
+ }
1095
+
1096
+ return 0 ;
1097
+ }
0 commit comments