@@ -562,6 +562,17 @@ void pandas_datetime_to_datetimestruct(npy_datetime val, PANDAS_DATETIMEUNIT fr,
562562 convert_datetime_to_datetimestruct (& meta , val , result );
563563}
564564
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+
565576PANDAS_DATETIMEUNIT get_datetime64_unit (PyObject * obj ) {
566577 return (PANDAS_DATETIMEUNIT )((PyDatetimeScalarObject * )obj )-> obmeta .base ;
567578}
@@ -980,3 +991,107 @@ int convert_datetime_to_datetimestruct(pandas_datetime_metadata *meta,
980991
981992 return 0 ;
982993}
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