@@ -498,6 +498,27 @@ npy_datetime npy_datetimestruct_to_datetime(NPY_DATETIMEUNIT base,
498
498
return ret ;
499
499
}
500
500
501
+ /*
502
+ * Port numpy#13188 https://github.com/numpy/numpy/pull/13188/
503
+ *
504
+ * Computes the python `ret, d = divmod(d, unit)`.
505
+ *
506
+ * Note that GCC is smart enough at -O2 to eliminate the `if(*d < 0)` branch
507
+ * for subsequent calls to this command - it is able to deduce that `*d >= 0`.
508
+ */
509
+ npy_int64 extract_unit (npy_datetime * d , npy_datetime unit ) {
510
+ assert (unit > 0 );
511
+ npy_int64 div = * d / unit ;
512
+ npy_int64 mod = * d % unit ;
513
+ if (mod < 0 ) {
514
+ mod += unit ;
515
+ div -= 1 ;
516
+ }
517
+ assert (mod >= 0 );
518
+ * d = mod ;
519
+ return div ;
520
+ }
521
+
501
522
/*
502
523
* Converts a datetime based on the given metadata into a datetimestruct
503
524
*/
@@ -522,13 +543,8 @@ void pandas_datetime_to_datetimestruct(npy_datetime dt,
522
543
break ;
523
544
524
545
case NPY_FR_M :
525
- if (dt >= 0 ) {
526
- out -> year = 1970 + dt / 12 ;
527
- out -> month = dt % 12 + 1 ;
528
- } else {
529
- out -> year = 1969 + (dt + 1 ) / 12 ;
530
- out -> month = 12 + (dt + 1 ) % 12 ;
531
- }
546
+ out -> year = 1970 + extract_unit (& dt , 12 );
547
+ out -> month = dt + 1 ;
532
548
break ;
533
549
534
550
case NPY_FR_W :
@@ -543,167 +559,105 @@ void pandas_datetime_to_datetimestruct(npy_datetime dt,
543
559
case NPY_FR_h :
544
560
perday = 24LL ;
545
561
546
- if (dt >= 0 ) {
547
- set_datetimestruct_days (dt / perday , out );
548
- dt = dt % perday ;
549
- } else {
550
- set_datetimestruct_days (
551
- dt / perday - (dt % perday == 0 ? 0 : 1 ), out );
552
- dt = (perday - 1 ) + (dt + 1 ) % perday ;
553
- }
562
+ set_datetimestruct_days (extract_unit (& dt , perday ), out );
554
563
out -> hour = dt ;
555
564
break ;
556
565
557
566
case NPY_FR_m :
558
567
perday = 24LL * 60 ;
559
568
560
- if (dt >= 0 ) {
561
- set_datetimestruct_days (dt / perday , out );
562
- dt = dt % perday ;
563
- } else {
564
- set_datetimestruct_days (
565
- dt / perday - (dt % perday == 0 ? 0 : 1 ), out );
566
- dt = (perday - 1 ) + (dt + 1 ) % perday ;
567
- }
568
- out -> hour = dt / 60 ;
569
- out -> min = dt % 60 ;
569
+ set_datetimestruct_days (extract_unit (& dt , perday ), out );
570
+ out -> hour = (int )extract_unit (& dt , 60 );
571
+ out -> min = (int )dt ;
570
572
break ;
571
573
572
574
case NPY_FR_s :
573
575
perday = 24LL * 60 * 60 ;
574
576
575
- if (dt >= 0 ) {
576
- set_datetimestruct_days (dt / perday , out );
577
- dt = dt % perday ;
578
- } else {
579
- set_datetimestruct_days (
580
- dt / perday - (dt % perday == 0 ? 0 : 1 ), out );
581
- dt = (perday - 1 ) + (dt + 1 ) % perday ;
582
- }
583
- out -> hour = dt / (60 * 60 );
584
- out -> min = (dt / 60 ) % 60 ;
585
- out -> sec = dt % 60 ;
577
+ set_datetimestruct_days (extract_unit (& dt , perday ), out );
578
+ out -> hour = (int )extract_unit (& dt , 60 * 60 );
579
+ out -> min = (int )extract_unit (& dt , 60 );
580
+ out -> sec = (int )dt ;
586
581
break ;
587
582
588
583
case NPY_FR_ms :
589
584
perday = 24LL * 60 * 60 * 1000 ;
590
585
591
- if (dt >= 0 ) {
592
- set_datetimestruct_days (dt / perday , out );
593
- dt = dt % perday ;
594
- } else {
595
- set_datetimestruct_days (
596
- dt / perday - (dt % perday == 0 ? 0 : 1 ), out );
597
- dt = (perday - 1 ) + (dt + 1 ) % perday ;
598
- }
599
- out -> hour = dt / (60 * 60 * 1000LL );
600
- out -> min = (dt / (60 * 1000LL )) % 60 ;
601
- out -> sec = (dt / 1000LL ) % 60 ;
602
- out -> us = (dt % 1000LL ) * 1000 ;
586
+ set_datetimestruct_days (extract_unit (& dt , perday ), out );
587
+ out -> hour = (int )extract_unit (& dt , 1000LL * 60 * 60 );
588
+ out -> min = (int )extract_unit (& dt , 1000LL * 60 );
589
+ out -> sec = (int )extract_unit (& dt , 1000LL );
590
+ out -> us = (int )(dt * 1000 );
603
591
break ;
604
592
605
593
case NPY_FR_us :
606
594
perday = 24LL * 60LL * 60LL * 1000LL * 1000LL ;
607
595
608
- if (dt >= 0 ) {
609
- set_datetimestruct_days (dt / perday , out );
610
- dt = dt % perday ;
611
- } else {
612
- set_datetimestruct_days (
613
- dt / perday - (dt % perday == 0 ? 0 : 1 ), out );
614
- dt = (perday - 1 ) + (dt + 1 ) % perday ;
615
- }
616
- out -> hour = dt / (60 * 60 * 1000000LL );
617
- out -> min = (dt / (60 * 1000000LL )) % 60 ;
618
- out -> sec = (dt / 1000000LL ) % 60 ;
619
- out -> us = dt % 1000000LL ;
596
+ set_datetimestruct_days (extract_unit (& dt , perday ), out );
597
+ out -> hour = (int )extract_unit (& dt , 1000LL * 1000 * 60 * 60 );
598
+ out -> min = (int )extract_unit (& dt , 1000LL * 1000 * 60 );
599
+ out -> sec = (int )extract_unit (& dt , 1000LL * 1000 );
600
+ out -> us = (int )dt ;
620
601
break ;
621
602
622
603
case NPY_FR_ns :
623
604
perday = 24LL * 60LL * 60LL * 1000LL * 1000LL * 1000LL ;
624
605
625
- if (dt >= 0 ) {
626
- set_datetimestruct_days (dt / perday , out );
627
- dt = dt % perday ;
628
- } else {
629
- set_datetimestruct_days (
630
- dt / perday - (dt % perday == 0 ? 0 : 1 ), out );
631
- dt = (perday - 1 ) + (dt + 1 ) % perday ;
632
- }
633
- out -> hour = dt / (60 * 60 * 1000000000LL );
634
- out -> min = (dt / (60 * 1000000000LL )) % 60 ;
635
- out -> sec = (dt / 1000000000LL ) % 60 ;
636
- out -> us = (dt / 1000LL ) % 1000000LL ;
637
- out -> ps = (dt % 1000LL ) * 1000 ;
606
+ set_datetimestruct_days (extract_unit (& dt , perday ), out );
607
+ out -> hour = (int )extract_unit (& dt , 1000LL * 1000 * 1000 * 60 * 60 );
608
+ out -> min = (int )extract_unit (& dt , 1000LL * 1000 * 1000 * 60 );
609
+ out -> sec = (int )extract_unit (& dt , 1000LL * 1000 * 1000 );
610
+ out -> us = (int )extract_unit (& dt , 1000LL );
611
+ out -> ps = (int )(dt * 1000 );
638
612
break ;
639
613
640
614
case NPY_FR_ps :
641
615
perday = 24LL * 60 * 60 * 1000 * 1000 * 1000 * 1000 ;
642
616
643
- if (dt >= 0 ) {
644
- set_datetimestruct_days (dt / perday , out );
645
- dt = dt % perday ;
646
- } else {
647
- set_datetimestruct_days (
648
- dt / perday - (dt % perday == 0 ? 0 : 1 ), out );
649
- dt = (perday - 1 ) + (dt + 1 ) % perday ;
650
- }
651
- out -> hour = dt / (60 * 60 * 1000000000000LL );
652
- out -> min = (dt / (60 * 1000000000000LL )) % 60 ;
653
- out -> sec = (dt / 1000000000000LL ) % 60 ;
654
- out -> us = (dt / 1000000LL ) % 1000000LL ;
655
- out -> ps = dt % 1000000LL ;
617
+ set_datetimestruct_days (extract_unit (& dt , perday ), out );
618
+ out -> hour = (int )extract_unit (& dt , 1000LL * 1000 * 1000 * 60 * 60 );
619
+ out -> min = (int )extract_unit (& dt , 1000LL * 1000 * 1000 * 60 );
620
+ out -> sec = (int )extract_unit (& dt , 1000LL * 1000 * 1000 );
621
+ out -> us = (int )extract_unit (& dt , 1000LL );
622
+ out -> ps = (int )(dt * 1000 );
656
623
break ;
657
624
658
625
case NPY_FR_fs :
659
626
/* entire range is only +- 2.6 hours */
660
- if (dt >= 0 ) {
661
- out -> hour = dt / (60 * 60 * 1000000000000000LL );
662
- out -> min = (dt / (60 * 1000000000000000LL )) % 60 ;
663
- out -> sec = (dt / 1000000000000000LL ) % 60 ;
664
- out -> us = (dt / 1000000000LL ) % 1000000LL ;
665
- out -> ps = (dt / 1000LL ) % 1000000LL ;
666
- out -> as = (dt % 1000LL ) * 1000 ;
667
- } else {
668
- npy_datetime minutes ;
669
-
670
- minutes = dt / (60 * 1000000000000000LL );
671
- dt = dt % (60 * 1000000000000000LL );
672
- if (dt < 0 ) {
673
- dt += (60 * 1000000000000000LL );
674
- -- minutes ;
675
- }
676
- /* Offset the negative minutes */
677
- add_minutes_to_datetimestruct (out , minutes );
678
- out -> sec = (dt / 1000000000000000LL ) % 60 ;
679
- out -> us = (dt / 1000000000LL ) % 1000000LL ;
680
- out -> ps = (dt / 1000LL ) % 1000000LL ;
681
- out -> as = (dt % 1000LL ) * 1000 ;
627
+ out -> hour = (int )extract_unit (& dt , 1000LL * 1000 * 1000 * 1000 *
628
+ 1000 * 60 * 60 );
629
+ if (out -> hour < 0 ) {
630
+ out -> year = 1969 ;
631
+ out -> month = 12 ;
632
+ out -> day = 31 ;
633
+ out -> hour += 24 ;
634
+ assert (out -> hour >= 0 );
682
635
}
636
+ out -> min = (int )extract_unit (& dt , 1000LL * 1000 * 1000 * 1000 *
637
+ 1000 * 60 );
638
+ out -> sec = (int )extract_unit (& dt , 1000LL * 1000 * 1000 * 1000 *
639
+ 1000 );
640
+ out -> us = (int )extract_unit (& dt , 1000LL * 1000 * 1000 );
641
+ out -> ps = (int )extract_unit (& dt , 1000LL );
642
+ out -> as = (int )(dt * 1000 );
683
643
break ;
684
644
685
645
case NPY_FR_as :
686
646
/* entire range is only +- 9.2 seconds */
687
- if (dt >= 0 ) {
688
- out -> sec = (dt / 1000000000000000000LL ) % 60 ;
689
- out -> us = (dt / 1000000000000LL ) % 1000000LL ;
690
- out -> ps = (dt / 1000000LL ) % 1000000LL ;
691
- out -> as = dt % 1000000LL ;
692
- } else {
693
- npy_datetime seconds ;
694
-
695
- seconds = dt / 1000000000000000000LL ;
696
- dt = dt % 1000000000000000000LL ;
697
- if (dt < 0 ) {
698
- dt += 1000000000000000000LL ;
699
- -- seconds ;
700
- }
701
- /* Offset the negative seconds */
702
- add_seconds_to_datetimestruct (out , seconds );
703
- out -> us = (dt / 1000000000000LL ) % 1000000LL ;
704
- out -> ps = (dt / 1000000LL ) % 1000000LL ;
705
- out -> as = dt % 1000000LL ;
647
+ out -> sec = (int )extract_unit (& dt , 1000LL * 1000 * 1000 * 1000 *
648
+ 1000 * 1000 );
649
+ if (out -> sec < 0 ) {
650
+ out -> year = 1969 ;
651
+ out -> month = 12 ;
652
+ out -> day = 31 ;
653
+ out -> hour = 23 ;
654
+ out -> min = 59 ;
655
+ out -> sec += 60 ;
656
+ assert (out -> sec >= 0 );
706
657
}
658
+ out -> us = (int )extract_unit (& dt , 1000LL * 1000 * 1000 * 1000 );
659
+ out -> ps = (int )extract_unit (& dt , 1000LL * 1000 );
660
+ out -> as = (int )dt ;
707
661
break ;
708
662
709
663
default :
0 commit comments