@@ -712,19 +712,23 @@ void pandas_timedelta_to_timedeltastruct(npy_timedelta td,
712712 npy_int64 sfrac ;
713713 npy_int64 ifrac ;
714714 int sign ;
715- npy_int64 DAY_NS = 86400000000000LL ;
715+ npy_int64 per_day ;
716+ npy_int64 per_sec ;
716717
717718 /* Initialize the output to all zeros */
718719 memset (out , 0 , sizeof (pandas_timedeltastruct ));
719720
720721 switch (base ) {
721722 case NPY_FR_ns :
722723
724+ per_day = 86400000000000LL ;
725+ per_sec = 1000LL * 1000LL * 1000LL ;
726+
723727 // put frac in seconds
724- if (td < 0 && td % ( 1000LL * 1000LL * 1000LL ) != 0 )
725- frac = td / ( 1000LL * 1000LL * 1000LL ) - 1 ;
728+ if (td < 0 && td % per_sec != 0 )
729+ frac = td / per_sec - 1 ;
726730 else
727- frac = td / ( 1000LL * 1000LL * 1000LL ) ;
731+ frac = td / per_sec ;
728732
729733 if (frac < 0 ) {
730734 sign = -1 ;
@@ -768,12 +772,12 @@ void pandas_timedelta_to_timedeltastruct(npy_timedelta td,
768772 }
769773
770774 sfrac = (out -> hrs * 3600LL + out -> min * 60LL
771- + out -> sec ) * ( 1000LL * 1000LL * 1000LL ) ;
775+ + out -> sec ) * per_sec ;
772776
773777 if (sign < 0 )
774778 out -> days = - out -> days ;
775779
776- ifrac = td - (out -> days * DAY_NS + sfrac );
780+ ifrac = td - (out -> days * per_day + sfrac );
777781
778782 if (ifrac != 0 ) {
779783 out -> ms = ifrac / (1000LL * 1000LL );
@@ -786,17 +790,233 @@ void pandas_timedelta_to_timedeltastruct(npy_timedelta td,
786790 out -> us = 0 ;
787791 out -> ns = 0 ;
788792 }
793+ break ;
794+
795+ case NPY_FR_us :
796+
797+ per_day = 86400000000LL ;
798+ per_sec = 1000LL * 1000LL ;
799+
800+ // put frac in seconds
801+ if (td < 0 && td % per_sec != 0 )
802+ frac = td / per_sec - 1 ;
803+ else
804+ frac = td / per_sec ;
805+
806+ if (frac < 0 ) {
807+ sign = -1 ;
808+
809+ // even fraction
810+ if ((- frac % 86400LL ) != 0 ) {
811+ out -> days = - frac / 86400LL + 1 ;
812+ frac += 86400LL * out -> days ;
813+ } else {
814+ frac = - frac ;
815+ }
816+ } else {
817+ sign = 1 ;
818+ out -> days = 0 ;
819+ }
820+
821+ if (frac >= 86400 ) {
822+ out -> days += frac / 86400LL ;
823+ frac -= out -> days * 86400LL ;
824+ }
825+
826+ if (frac >= 3600 ) {
827+ out -> hrs = frac / 3600LL ;
828+ frac -= out -> hrs * 3600LL ;
829+ } else {
830+ out -> hrs = 0 ;
831+ }
832+
833+ if (frac >= 60 ) {
834+ out -> min = frac / 60LL ;
835+ frac -= out -> min * 60LL ;
836+ } else {
837+ out -> min = 0 ;
838+ }
839+
840+ if (frac >= 0 ) {
841+ out -> sec = frac ;
842+ frac -= out -> sec ;
843+ } else {
844+ out -> sec = 0 ;
845+ }
846+
847+ sfrac = (out -> hrs * 3600LL + out -> min * 60LL
848+ + out -> sec ) * per_sec ;
849+
850+ if (sign < 0 )
851+ out -> days = - out -> days ;
852+
853+ ifrac = td - (out -> days * per_day + sfrac );
854+
855+ if (ifrac != 0 ) {
856+ out -> ms = ifrac / 1000LL ;
857+ ifrac -= out -> ms * 1000LL ;
858+ out -> us = ifrac / 1L ;
859+ ifrac -= out -> us * 1L ;
860+ out -> ns = ifrac ;
861+ } else {
862+ out -> ms = 0 ;
863+ out -> us = 0 ;
864+ out -> ns = 0 ;
865+ }
866+ break ;
867+
868+ case NPY_FR_ms :
869+
870+ per_day = 86400000LL ;
871+ per_sec = 1000LL ;
872+
873+ // put frac in seconds
874+ if (td < 0 && td % per_sec != 0 )
875+ frac = td / per_sec - 1 ;
876+ else
877+ frac = td / per_sec ;
878+
879+ if (frac < 0 ) {
880+ sign = -1 ;
881+
882+ // even fraction
883+ if ((- frac % 86400LL ) != 0 ) {
884+ out -> days = - frac / 86400LL + 1 ;
885+ frac += 86400LL * out -> days ;
886+ } else {
887+ frac = - frac ;
888+ }
889+ } else {
890+ sign = 1 ;
891+ out -> days = 0 ;
892+ }
893+
894+ if (frac >= 86400 ) {
895+ out -> days += frac / 86400LL ;
896+ frac -= out -> days * 86400LL ;
897+ }
898+
899+ if (frac >= 3600 ) {
900+ out -> hrs = frac / 3600LL ;
901+ frac -= out -> hrs * 3600LL ;
902+ } else {
903+ out -> hrs = 0 ;
904+ }
905+
906+ if (frac >= 60 ) {
907+ out -> min = frac / 60LL ;
908+ frac -= out -> min * 60LL ;
909+ } else {
910+ out -> min = 0 ;
911+ }
912+
913+ if (frac >= 0 ) {
914+ out -> sec = frac ;
915+ frac -= out -> sec ;
916+ } else {
917+ out -> sec = 0 ;
918+ }
919+
920+ sfrac = (out -> hrs * 3600LL + out -> min * 60LL
921+ + out -> sec ) * per_sec ;
922+
923+ if (sign < 0 )
924+ out -> days = - out -> days ;
925+
926+ ifrac = td - (out -> days * per_day + sfrac );
927+
928+ if (ifrac != 0 ) {
929+ out -> ms = ifrac ;
930+ out -> us = 0 ;
931+ out -> ns = 0 ;
932+ } else {
933+ out -> ms = 0 ;
934+ out -> us = 0 ;
935+ out -> ns = 0 ;
936+ }
937+ break ;
938+
939+ case NPY_FR_s :
940+ // special case where we can simplify many expressions bc per_sec=1
941+
942+ per_day = 86400000LL ;
943+ per_sec = 1L ;
944+
945+ // put frac in seconds
946+ if (td < 0 && td % per_sec != 0 )
947+ frac = td / per_sec - 1 ;
948+ else
949+ frac = td / per_sec ;
950+
951+ if (frac < 0 ) {
952+ sign = -1 ;
789953
790- out -> seconds = out -> hrs * 3600 + out -> min * 60 + out -> sec ;
791- out -> microseconds = out -> ms * 1000 + out -> us ;
792- out -> nanoseconds = out -> ns ;
954+ // even fraction
955+ if ((- frac % 86400LL ) != 0 ) {
956+ out -> days = - frac / 86400LL + 1 ;
957+ frac += 86400LL * out -> days ;
958+ } else {
959+ frac = - frac ;
960+ }
961+ } else {
962+ sign = 1 ;
963+ out -> days = 0 ;
964+ }
965+
966+ if (frac >= 86400 ) {
967+ out -> days += frac / 86400LL ;
968+ frac -= out -> days * 86400LL ;
969+ }
970+
971+ if (frac >= 3600 ) {
972+ out -> hrs = frac / 3600LL ;
973+ frac -= out -> hrs * 3600LL ;
974+ } else {
975+ out -> hrs = 0 ;
976+ }
977+
978+ if (frac >= 60 ) {
979+ out -> min = frac / 60LL ;
980+ frac -= out -> min * 60LL ;
981+ } else {
982+ out -> min = 0 ;
983+ }
984+
985+ if (frac >= 0 ) {
986+ out -> sec = frac ;
987+ frac -= out -> sec ;
988+ } else {
989+ out -> sec = 0 ;
990+ }
991+
992+ sfrac = (out -> hrs * 3600LL + out -> min * 60LL
993+ + out -> sec ) * per_sec ;
994+
995+ if (sign < 0 )
996+ out -> days = - out -> days ;
997+
998+ ifrac = td - (out -> days * per_day + sfrac );
999+
1000+ if (ifrac != 0 ) {
1001+ out -> ms = 0 ;
1002+ out -> us = 0 ;
1003+ out -> ns = 0 ;
1004+ } else {
1005+ out -> ms = 0 ;
1006+ out -> us = 0 ;
1007+ out -> ns = 0 ;
1008+ }
7931009 break ;
7941010
7951011 default :
7961012 PyErr_SetString (PyExc_RuntimeError ,
7971013 "NumPy timedelta metadata is corrupted with "
7981014 "invalid base unit" );
7991015 }
1016+
1017+ out -> seconds = out -> hrs * 3600 + out -> min * 60 + out -> sec ;
1018+ out -> microseconds = out -> ms * 1000 + out -> us ;
1019+ out -> nanoseconds = out -> ns ;
8001020}
8011021
8021022
0 commit comments