date 3.5.1 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/date/date_core.c +293 -77
- data/ext/date/date_parse.c +14 -4
- data/ext/date/date_strptime.c +13 -13
- data/ext/date/extconf.rb +6 -0
- data/lib/date.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e3e5e30902faa5fe0f946df02df28a7d52b64e6a78d39e9b16ec9f0d88377646
|
|
4
|
+
data.tar.gz: 5a0c7a8ae91bbfd3a0fe6a152465217070ccbd7f5b5892c9657a865f47d6d492
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bb10bbaa46008e4af4c8ba566aafbf71c45e3fcecd80b783b2ae06a0334df66ba49d4435ae969fb24b79e6ab2f53e16c80e1ae6f7b54f46314f87f7747702e89
|
|
7
|
+
data.tar.gz: b130c6501519228151df6df25cedae7457be32ed3c6f118f331ade479f14ec9bd7f7148ef48575e199cf987c2398d1688ddb3e9f45d6b08a8d919294998bda11
|
data/ext/date/date_core.c
CHANGED
|
@@ -27,7 +27,7 @@ static VALUE eDateError;
|
|
|
27
27
|
static VALUE half_days_in_day, day_in_nanoseconds;
|
|
28
28
|
static double positive_inf, negative_inf;
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
/* used by deconstruct_keys */
|
|
31
31
|
static VALUE sym_year, sym_month, sym_day, sym_yday, sym_wday;
|
|
32
32
|
static VALUE sym_hour, sym_min, sym_sec, sym_sec_fraction, sym_zone;
|
|
33
33
|
|
|
@@ -452,11 +452,43 @@ do {\
|
|
|
452
452
|
static int c_valid_civil_p(int, int, int, double,
|
|
453
453
|
int *, int *, int *, int *);
|
|
454
454
|
|
|
455
|
+
/* Check if using pure Gregorian calendar (sg == -Infinity) */
|
|
456
|
+
#define c_gregorian_only_p(sg) (isinf(sg) && (sg) < 0)
|
|
457
|
+
|
|
458
|
+
/*
|
|
459
|
+
* Fast path macros for pure Gregorian calendar.
|
|
460
|
+
* Sets *rjd to the JD value, *ns to 1 (new style), and returns.
|
|
461
|
+
*/
|
|
462
|
+
#define GREGORIAN_JD_FAST_PATH_RET(sg, jd_expr, rjd, ns) \
|
|
463
|
+
if (c_gregorian_only_p(sg)) { \
|
|
464
|
+
*(rjd) = (jd_expr); \
|
|
465
|
+
*(ns) = 1; \
|
|
466
|
+
return 1; \
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
#define GREGORIAN_JD_FAST_PATH(sg, jd_expr, rjd, ns) \
|
|
470
|
+
if (c_gregorian_only_p(sg)) { \
|
|
471
|
+
*(rjd) = (jd_expr); \
|
|
472
|
+
*(ns) = 1; \
|
|
473
|
+
return; \
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/* Forward declarations for Neri-Schneider optimized functions */
|
|
477
|
+
static int c_gregorian_civil_to_jd(int y, int m, int d);
|
|
478
|
+
static void c_gregorian_jd_to_civil(int jd, int *ry, int *rm, int *rd);
|
|
479
|
+
static int c_gregorian_fdoy(int y);
|
|
480
|
+
static int c_gregorian_ldoy(int y);
|
|
481
|
+
static int c_gregorian_ldom_jd(int y, int m);
|
|
482
|
+
static int ns_jd_in_range(int jd);
|
|
483
|
+
|
|
455
484
|
static int
|
|
456
485
|
c_find_fdoy(int y, double sg, int *rjd, int *ns)
|
|
457
486
|
{
|
|
458
487
|
int d, rm, rd;
|
|
459
488
|
|
|
489
|
+
GREGORIAN_JD_FAST_PATH_RET(sg, c_gregorian_fdoy(y), rjd, ns);
|
|
490
|
+
|
|
491
|
+
/* Keep existing loop for Julian/reform period */
|
|
460
492
|
for (d = 1; d < 31; d++)
|
|
461
493
|
if (c_valid_civil_p(y, 1, d, sg, &rm, &rd, rjd, ns))
|
|
462
494
|
return 1;
|
|
@@ -468,6 +500,9 @@ c_find_ldoy(int y, double sg, int *rjd, int *ns)
|
|
|
468
500
|
{
|
|
469
501
|
int i, rm, rd;
|
|
470
502
|
|
|
503
|
+
GREGORIAN_JD_FAST_PATH_RET(sg, c_gregorian_ldoy(y), rjd, ns);
|
|
504
|
+
|
|
505
|
+
/* Keep existing loop for Julian/reform period */
|
|
471
506
|
for (i = 0; i < 30; i++)
|
|
472
507
|
if (c_valid_civil_p(y, 12, 31 - i, sg, &rm, &rd, rjd, ns))
|
|
473
508
|
return 1;
|
|
@@ -493,6 +528,9 @@ c_find_ldom(int y, int m, double sg, int *rjd, int *ns)
|
|
|
493
528
|
{
|
|
494
529
|
int i, rm, rd;
|
|
495
530
|
|
|
531
|
+
GREGORIAN_JD_FAST_PATH_RET(sg, c_gregorian_ldom_jd(y, m), rjd, ns);
|
|
532
|
+
|
|
533
|
+
/* Keep existing loop for Julian/reform period */
|
|
496
534
|
for (i = 0; i < 30; i++)
|
|
497
535
|
if (c_valid_civil_p(y, m, 31 - i, sg, &rm, &rd, rjd, ns))
|
|
498
536
|
return 1;
|
|
@@ -502,55 +540,69 @@ c_find_ldom(int y, int m, double sg, int *rjd, int *ns)
|
|
|
502
540
|
static void
|
|
503
541
|
c_civil_to_jd(int y, int m, int d, double sg, int *rjd, int *ns)
|
|
504
542
|
{
|
|
505
|
-
|
|
543
|
+
int jd;
|
|
544
|
+
|
|
545
|
+
GREGORIAN_JD_FAST_PATH(sg, c_gregorian_civil_to_jd(y, m, d), rjd, ns);
|
|
546
|
+
|
|
547
|
+
/* Calculate Gregorian JD using optimized algorithm */
|
|
548
|
+
jd = c_gregorian_civil_to_jd(y, m, d);
|
|
506
549
|
|
|
507
|
-
if (m <= 2) {
|
|
508
|
-
y -= 1;
|
|
509
|
-
m += 12;
|
|
510
|
-
}
|
|
511
|
-
a = floor(y / 100.0);
|
|
512
|
-
b = 2 - a + floor(a / 4.0);
|
|
513
|
-
jd = floor(365.25 * (y + 4716)) +
|
|
514
|
-
floor(30.6001 * (m + 1)) +
|
|
515
|
-
d + b - 1524;
|
|
516
550
|
if (jd < sg) {
|
|
517
|
-
|
|
551
|
+
/* Before Gregorian switchover - use Julian calendar */
|
|
552
|
+
int y2 = y, m2 = m;
|
|
553
|
+
if (m2 <= 2) {
|
|
554
|
+
y2 -= 1;
|
|
555
|
+
m2 += 12;
|
|
556
|
+
}
|
|
557
|
+
jd = (int)(floor(365.25 * (y2 + 4716)) +
|
|
558
|
+
floor(30.6001 * (m2 + 1)) +
|
|
559
|
+
d - 1524);
|
|
518
560
|
*ns = 0;
|
|
519
561
|
}
|
|
520
|
-
else
|
|
562
|
+
else {
|
|
521
563
|
*ns = 1;
|
|
564
|
+
}
|
|
522
565
|
|
|
523
|
-
*rjd =
|
|
566
|
+
*rjd = jd;
|
|
524
567
|
}
|
|
525
568
|
|
|
526
569
|
static void
|
|
527
570
|
c_jd_to_civil(int jd, double sg, int *ry, int *rm, int *rdom)
|
|
528
571
|
{
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
else {
|
|
534
|
-
x = floor((jd - 1867216.25) / 36524.25);
|
|
535
|
-
a = jd + 1 + x - floor(x / 4.0);
|
|
536
|
-
}
|
|
537
|
-
b = a + 1524;
|
|
538
|
-
c = floor((b - 122.1) / 365.25);
|
|
539
|
-
d = floor(365.25 * c);
|
|
540
|
-
e = floor((b - d) / 30.6001);
|
|
541
|
-
dom = b - d - floor(30.6001 * e);
|
|
542
|
-
if (e <= 13) {
|
|
543
|
-
m = e - 1;
|
|
544
|
-
y = c - 4716;
|
|
545
|
-
}
|
|
546
|
-
else {
|
|
547
|
-
m = e - 13;
|
|
548
|
-
y = c - 4715;
|
|
572
|
+
/* Fast path: pure Gregorian or date after switchover, within safe range */
|
|
573
|
+
if ((c_gregorian_only_p(sg) || jd >= sg) && ns_jd_in_range(jd)) {
|
|
574
|
+
c_gregorian_jd_to_civil(jd, ry, rm, rdom);
|
|
575
|
+
return;
|
|
549
576
|
}
|
|
550
577
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
578
|
+
/* Original algorithm for Julian calendar or extreme dates */
|
|
579
|
+
{
|
|
580
|
+
double x, a, b, c, d, e, y, m, dom;
|
|
581
|
+
|
|
582
|
+
if (jd < sg)
|
|
583
|
+
a = jd;
|
|
584
|
+
else {
|
|
585
|
+
x = floor((jd - 1867216.25) / 36524.25);
|
|
586
|
+
a = jd + 1 + x - floor(x / 4.0);
|
|
587
|
+
}
|
|
588
|
+
b = a + 1524;
|
|
589
|
+
c = floor((b - 122.1) / 365.25);
|
|
590
|
+
d = floor(365.25 * c);
|
|
591
|
+
e = floor((b - d) / 30.6001);
|
|
592
|
+
dom = b - d - floor(30.6001 * e);
|
|
593
|
+
if (e <= 13) {
|
|
594
|
+
m = e - 1;
|
|
595
|
+
y = c - 4716;
|
|
596
|
+
}
|
|
597
|
+
else {
|
|
598
|
+
m = e - 13;
|
|
599
|
+
y = c - 4715;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
*ry = (int)y;
|
|
603
|
+
*rm = (int)m;
|
|
604
|
+
*rdom = (int)dom;
|
|
605
|
+
}
|
|
554
606
|
}
|
|
555
607
|
|
|
556
608
|
static void
|
|
@@ -725,6 +777,147 @@ c_gregorian_last_day_of_month(int y, int m)
|
|
|
725
777
|
return monthtab[c_gregorian_leap_p(y) ? 1 : 0][m];
|
|
726
778
|
}
|
|
727
779
|
|
|
780
|
+
/*
|
|
781
|
+
* Neri-Schneider algorithm for optimized Gregorian date conversion.
|
|
782
|
+
* Reference: Neri & Schneider, "Euclidean Affine Functions and Applications
|
|
783
|
+
* to Calendar Algorithms", Software: Practice and Experience, 2023.
|
|
784
|
+
* https://arxiv.org/abs/2102.06959
|
|
785
|
+
*
|
|
786
|
+
* This algorithm provides ~2-3x speedup over traditional floating-point
|
|
787
|
+
* implementations by using pure integer arithmetic with multiplication
|
|
788
|
+
* and bit-shifts instead of expensive division operations.
|
|
789
|
+
*/
|
|
790
|
+
|
|
791
|
+
/* JDN of March 1, Year 0 in proleptic Gregorian calendar */
|
|
792
|
+
#define NS_EPOCH 1721120
|
|
793
|
+
|
|
794
|
+
/* Days in a 4-year cycle (3 normal years + 1 leap year) */
|
|
795
|
+
#define NS_DAYS_IN_4_YEARS 1461
|
|
796
|
+
|
|
797
|
+
/* Days in a 400-year Gregorian cycle (97 leap years in 400 years) */
|
|
798
|
+
#define NS_DAYS_IN_400_YEARS 146097
|
|
799
|
+
|
|
800
|
+
/* Years per century */
|
|
801
|
+
#define NS_YEARS_PER_CENTURY 100
|
|
802
|
+
|
|
803
|
+
/*
|
|
804
|
+
* Multiplier for extracting year within century using fixed-point arithmetic.
|
|
805
|
+
* This is ceil(2^32 / NS_DAYS_IN_4_YEARS) for the Euclidean affine function.
|
|
806
|
+
*/
|
|
807
|
+
#define NS_YEAR_MULTIPLIER 2939745
|
|
808
|
+
|
|
809
|
+
/*
|
|
810
|
+
* Coefficients for month calculation from day-of-year.
|
|
811
|
+
* Maps day-of-year to month using: month = (NS_MONTH_COEFF * doy + NS_MONTH_OFFSET) >> 16
|
|
812
|
+
*/
|
|
813
|
+
#define NS_MONTH_COEFF 2141
|
|
814
|
+
#define NS_MONTH_OFFSET 197913
|
|
815
|
+
|
|
816
|
+
/*
|
|
817
|
+
* Coefficients for civil date to JDN month contribution.
|
|
818
|
+
* Maps month to accumulated days: days = (NS_CIVIL_MONTH_COEFF * m - NS_CIVIL_MONTH_OFFSET) / 32
|
|
819
|
+
*/
|
|
820
|
+
#define NS_CIVIL_MONTH_COEFF 979
|
|
821
|
+
#define NS_CIVIL_MONTH_OFFSET 2919
|
|
822
|
+
#define NS_CIVIL_MONTH_DIVISOR 32
|
|
823
|
+
|
|
824
|
+
/* Days from March 1 to December 31 (for Jan/Feb year adjustment) */
|
|
825
|
+
#define NS_DAYS_BEFORE_NEW_YEAR 306
|
|
826
|
+
|
|
827
|
+
/*
|
|
828
|
+
* Safe bounds for Neri-Schneider algorithm to avoid integer overflow.
|
|
829
|
+
* These correspond to approximately years -1,000,000 to +1,000,000.
|
|
830
|
+
*/
|
|
831
|
+
#define NS_JD_MIN -364000000
|
|
832
|
+
#define NS_JD_MAX 538000000
|
|
833
|
+
|
|
834
|
+
inline static int
|
|
835
|
+
ns_jd_in_range(int jd)
|
|
836
|
+
{
|
|
837
|
+
return jd >= NS_JD_MIN && jd <= NS_JD_MAX;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/* Optimized: Gregorian date -> Julian Day Number */
|
|
841
|
+
static int
|
|
842
|
+
c_gregorian_civil_to_jd(int y, int m, int d)
|
|
843
|
+
{
|
|
844
|
+
/* Shift epoch to March 1 of year 0 (Jan/Feb belong to previous year) */
|
|
845
|
+
int j = (m < 3) ? 1 : 0;
|
|
846
|
+
int y0 = y - j;
|
|
847
|
+
int m0 = j ? m + 12 : m;
|
|
848
|
+
int d0 = d - 1;
|
|
849
|
+
|
|
850
|
+
/* Calculate year contribution with leap year correction */
|
|
851
|
+
int q1 = DIV(y0, NS_YEARS_PER_CENTURY);
|
|
852
|
+
int yc = DIV(NS_DAYS_IN_4_YEARS * y0, 4) - q1 + DIV(q1, 4);
|
|
853
|
+
|
|
854
|
+
/* Calculate month contribution using integer arithmetic */
|
|
855
|
+
int mc = (NS_CIVIL_MONTH_COEFF * m0 - NS_CIVIL_MONTH_OFFSET) / NS_CIVIL_MONTH_DIVISOR;
|
|
856
|
+
|
|
857
|
+
/* Combine and add epoch offset to get JDN */
|
|
858
|
+
return yc + mc + d0 + NS_EPOCH;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/* Optimized: Julian Day Number -> Gregorian date */
|
|
862
|
+
static void
|
|
863
|
+
c_gregorian_jd_to_civil(int jd, int *ry, int *rm, int *rd)
|
|
864
|
+
{
|
|
865
|
+
int r0, n1, q1, r1, n2, q2, r2, n3, q3, r3, y0, j;
|
|
866
|
+
uint64_t u2;
|
|
867
|
+
|
|
868
|
+
/* Convert JDN to rata die (March 1, Year 0 epoch) */
|
|
869
|
+
r0 = jd - NS_EPOCH;
|
|
870
|
+
|
|
871
|
+
/* Extract century and day within 400-year cycle */
|
|
872
|
+
/* Use Euclidean (floor) division for negative values */
|
|
873
|
+
n1 = 4 * r0 + 3;
|
|
874
|
+
q1 = DIV(n1, NS_DAYS_IN_400_YEARS);
|
|
875
|
+
r1 = MOD(n1, NS_DAYS_IN_400_YEARS) / 4;
|
|
876
|
+
|
|
877
|
+
/* Calculate year within century and day of year */
|
|
878
|
+
n2 = 4 * r1 + 3;
|
|
879
|
+
/* Use 64-bit arithmetic to avoid overflow */
|
|
880
|
+
u2 = (uint64_t)NS_YEAR_MULTIPLIER * (uint64_t)n2;
|
|
881
|
+
q2 = (int)(u2 >> 32);
|
|
882
|
+
r2 = (int)((uint32_t)u2 / NS_YEAR_MULTIPLIER / 4);
|
|
883
|
+
|
|
884
|
+
/* Calculate month and day using integer arithmetic */
|
|
885
|
+
n3 = NS_MONTH_COEFF * r2 + NS_MONTH_OFFSET;
|
|
886
|
+
q3 = n3 >> 16;
|
|
887
|
+
r3 = (n3 & 0xFFFF) / NS_MONTH_COEFF;
|
|
888
|
+
|
|
889
|
+
/* Combine century and year */
|
|
890
|
+
y0 = NS_YEARS_PER_CENTURY * q1 + q2;
|
|
891
|
+
|
|
892
|
+
/* Adjust for January/February (shift from fiscal year) */
|
|
893
|
+
j = (r2 >= NS_DAYS_BEFORE_NEW_YEAR) ? 1 : 0;
|
|
894
|
+
|
|
895
|
+
*ry = y0 + j;
|
|
896
|
+
*rm = j ? q3 - 12 : q3;
|
|
897
|
+
*rd = r3 + 1;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
/* O(1) first day of year for Gregorian calendar */
|
|
901
|
+
inline static int
|
|
902
|
+
c_gregorian_fdoy(int y)
|
|
903
|
+
{
|
|
904
|
+
return c_gregorian_civil_to_jd(y, 1, 1);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
/* O(1) last day of year for Gregorian calendar */
|
|
908
|
+
inline static int
|
|
909
|
+
c_gregorian_ldoy(int y)
|
|
910
|
+
{
|
|
911
|
+
return c_gregorian_civil_to_jd(y, 12, 31);
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
/* O(1) last day of month (JDN) for Gregorian calendar */
|
|
915
|
+
inline static int
|
|
916
|
+
c_gregorian_ldom_jd(int y, int m)
|
|
917
|
+
{
|
|
918
|
+
return c_gregorian_civil_to_jd(y, m, c_gregorian_last_day_of_month(y, m));
|
|
919
|
+
}
|
|
920
|
+
|
|
728
921
|
static int
|
|
729
922
|
c_valid_julian_p(int y, int m, int d, int *rm, int *rd)
|
|
730
923
|
{
|
|
@@ -799,12 +992,16 @@ c_valid_commercial_p(int y, int w, int d, double sg,
|
|
|
799
992
|
if (w < 0) {
|
|
800
993
|
int rjd2;
|
|
801
994
|
|
|
995
|
+
if (w < -53) return 0;
|
|
802
996
|
c_commercial_to_jd(y + 1, 1, 1, sg, &rjd2, &ns2);
|
|
803
997
|
c_jd_to_commercial(rjd2 + w * 7, sg, &ry2, &rw2, &rd2);
|
|
804
998
|
if (ry2 != y)
|
|
805
999
|
return 0;
|
|
806
1000
|
w = rw2;
|
|
807
1001
|
}
|
|
1002
|
+
else {
|
|
1003
|
+
if (w < 1 || 53 < w) return 0;
|
|
1004
|
+
}
|
|
808
1005
|
c_commercial_to_jd(y, w, d, sg, rjd, ns);
|
|
809
1006
|
c_jd_to_commercial(*rjd, sg, &ry2, rw, rd);
|
|
810
1007
|
if (y != ry2 || w != *rw || d != *rd)
|
|
@@ -2428,9 +2625,9 @@ offset_to_sec(VALUE vof, int *rof)
|
|
|
2428
2625
|
if (!FIXNUM_P(vn))
|
|
2429
2626
|
return 0;
|
|
2430
2627
|
n = FIX2LONG(vn);
|
|
2431
|
-
if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
|
|
2432
|
-
return 0;
|
|
2433
2628
|
}
|
|
2629
|
+
if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS)
|
|
2630
|
+
return 0;
|
|
2434
2631
|
*rof = (int)n;
|
|
2435
2632
|
return 1;
|
|
2436
2633
|
}
|
|
@@ -3002,34 +3199,66 @@ date_s_gregorian_leap_p(VALUE klass, VALUE y)
|
|
|
3002
3199
|
return f_boolcast(c_gregorian_leap_p(ry));
|
|
3003
3200
|
}
|
|
3004
3201
|
|
|
3202
|
+
#ifndef HAVE_RB_GC_MARK_MOVABLE
|
|
3203
|
+
#define rb_gc_mark_movable rb_gc_mark
|
|
3204
|
+
#else
|
|
3005
3205
|
static void
|
|
3006
|
-
|
|
3206
|
+
d_lite_gc_compact(void *ptr)
|
|
3007
3207
|
{
|
|
3008
3208
|
union DateData *dat = ptr;
|
|
3009
3209
|
if (simple_dat_p(dat))
|
|
3010
|
-
|
|
3210
|
+
dat->s.nth = rb_gc_location(dat->s.nth);
|
|
3011
3211
|
else {
|
|
3012
|
-
|
|
3013
|
-
|
|
3212
|
+
dat->c.nth = rb_gc_location(dat->c.nth);
|
|
3213
|
+
dat->c.sf = rb_gc_location(dat->c.sf);
|
|
3014
3214
|
}
|
|
3015
3215
|
}
|
|
3216
|
+
#endif
|
|
3016
3217
|
|
|
3017
|
-
static
|
|
3018
|
-
|
|
3218
|
+
static void
|
|
3219
|
+
d_lite_gc_mark(void *ptr)
|
|
3019
3220
|
{
|
|
3020
|
-
|
|
3021
|
-
|
|
3221
|
+
union DateData *dat = ptr;
|
|
3222
|
+
if (simple_dat_p(dat))
|
|
3223
|
+
rb_gc_mark_movable(dat->s.nth);
|
|
3224
|
+
else {
|
|
3225
|
+
rb_gc_mark_movable(dat->c.nth);
|
|
3226
|
+
rb_gc_mark_movable(dat->c.sf);
|
|
3227
|
+
}
|
|
3022
3228
|
}
|
|
3023
3229
|
|
|
3024
3230
|
#ifndef HAVE_RB_EXT_RACTOR_SAFE
|
|
3025
3231
|
# define RUBY_TYPED_FROZEN_SHAREABLE 0
|
|
3026
3232
|
#endif
|
|
3027
3233
|
|
|
3234
|
+
#if defined(RUBY_TYPED_EMBEDDABLE) || defined(HAVE_CONST_RUBY_TYPED_EMBEDDABLE)
|
|
3235
|
+
# define HAVE_RUBY_TYPED_EMBEDDABLE 1
|
|
3236
|
+
#else
|
|
3237
|
+
# define RUBY_TYPED_EMBEDDABLE 0
|
|
3238
|
+
#endif
|
|
3239
|
+
|
|
3240
|
+
static size_t
|
|
3241
|
+
d_lite_memsize(const void *ptr)
|
|
3242
|
+
{
|
|
3243
|
+
#ifdef HAVE_RUBY_TYPED_EMBEDDABLE
|
|
3244
|
+
return 0;
|
|
3245
|
+
#else
|
|
3246
|
+
return sizeof(union DateData);
|
|
3247
|
+
#endif
|
|
3248
|
+
}
|
|
3249
|
+
|
|
3028
3250
|
static const rb_data_type_t d_lite_type = {
|
|
3029
3251
|
"Date",
|
|
3030
|
-
{
|
|
3252
|
+
{
|
|
3253
|
+
d_lite_gc_mark,
|
|
3254
|
+
RUBY_TYPED_DEFAULT_FREE,
|
|
3255
|
+
d_lite_memsize,
|
|
3256
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
|
3257
|
+
d_lite_gc_compact,
|
|
3258
|
+
#endif
|
|
3259
|
+
},
|
|
3031
3260
|
0, 0,
|
|
3032
|
-
RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED|RUBY_TYPED_FROZEN_SHAREABLE,
|
|
3261
|
+
RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED|RUBY_TYPED_EMBEDDABLE|RUBY_TYPED_FROZEN_SHAREABLE,
|
|
3033
3262
|
};
|
|
3034
3263
|
|
|
3035
3264
|
inline static VALUE
|
|
@@ -3040,10 +3269,11 @@ d_simple_new_internal(VALUE klass,
|
|
|
3040
3269
|
unsigned flags)
|
|
3041
3270
|
{
|
|
3042
3271
|
struct SimpleDateData *dat;
|
|
3272
|
+
union DateData *u_dat;
|
|
3043
3273
|
VALUE obj;
|
|
3044
3274
|
|
|
3045
|
-
obj = TypedData_Make_Struct(klass,
|
|
3046
|
-
|
|
3275
|
+
obj = TypedData_Make_Struct(klass, union DateData, &d_lite_type, u_dat);
|
|
3276
|
+
dat = &u_dat->s;
|
|
3047
3277
|
set_to_simple(obj, dat, nth, jd, sg, y, m, d, flags);
|
|
3048
3278
|
|
|
3049
3279
|
assert(have_jd_p(dat) || have_civil_p(dat));
|
|
@@ -3061,10 +3291,11 @@ d_complex_new_internal(VALUE klass,
|
|
|
3061
3291
|
unsigned flags)
|
|
3062
3292
|
{
|
|
3063
3293
|
struct ComplexDateData *dat;
|
|
3294
|
+
union DateData *u_dat;
|
|
3064
3295
|
VALUE obj;
|
|
3065
3296
|
|
|
3066
|
-
obj = TypedData_Make_Struct(klass,
|
|
3067
|
-
|
|
3297
|
+
obj = TypedData_Make_Struct(klass, union DateData, &d_lite_type, u_dat);
|
|
3298
|
+
dat = &u_dat->c;
|
|
3068
3299
|
set_to_complex(obj, dat, nth, jd, df, sf, of, sg,
|
|
3069
3300
|
y, m, d, h, min, s, flags);
|
|
3070
3301
|
|
|
@@ -4322,7 +4553,8 @@ d_new_by_frags(VALUE klass, VALUE hash, VALUE sg)
|
|
|
4322
4553
|
}
|
|
4323
4554
|
|
|
4324
4555
|
VALUE date__strptime(const char *str, size_t slen,
|
|
4325
|
-
const char *fmt, size_t flen,
|
|
4556
|
+
const char *fmt, size_t flen,
|
|
4557
|
+
VALUE hash, rb_encoding *enc);
|
|
4326
4558
|
|
|
4327
4559
|
static VALUE
|
|
4328
4560
|
date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
|
|
@@ -4331,10 +4563,12 @@ date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
|
|
|
4331
4563
|
VALUE vstr, vfmt, hash;
|
|
4332
4564
|
const char *str, *fmt;
|
|
4333
4565
|
size_t slen, flen;
|
|
4566
|
+
rb_encoding *enc;
|
|
4334
4567
|
|
|
4335
4568
|
rb_scan_args(argc, argv, "11", &vstr, &vfmt);
|
|
4336
4569
|
|
|
4337
4570
|
StringValue(vstr);
|
|
4571
|
+
if (argc > 1) StringValue(vfmt);
|
|
4338
4572
|
if (!rb_enc_str_asciicompat_p(vstr))
|
|
4339
4573
|
rb_raise(rb_eArgError,
|
|
4340
4574
|
"string should have ASCII compatible encoding");
|
|
@@ -4343,34 +4577,18 @@ date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
|
|
|
4343
4577
|
if (argc < 2) {
|
|
4344
4578
|
fmt = default_fmt;
|
|
4345
4579
|
flen = strlen(default_fmt);
|
|
4580
|
+
enc = rb_enc_get(vstr);
|
|
4346
4581
|
}
|
|
4347
4582
|
else {
|
|
4348
|
-
StringValue(vfmt);
|
|
4349
4583
|
if (!rb_enc_str_asciicompat_p(vfmt))
|
|
4350
4584
|
rb_raise(rb_eArgError,
|
|
4351
4585
|
"format should have ASCII compatible encoding");
|
|
4586
|
+
enc = rb_enc_check(vstr, vfmt);
|
|
4352
4587
|
fmt = RSTRING_PTR(vfmt);
|
|
4353
4588
|
flen = RSTRING_LEN(vfmt);
|
|
4354
4589
|
}
|
|
4355
4590
|
hash = rb_hash_new();
|
|
4356
|
-
|
|
4357
|
-
return Qnil;
|
|
4358
|
-
|
|
4359
|
-
{
|
|
4360
|
-
VALUE zone = ref_hash("zone");
|
|
4361
|
-
VALUE left = ref_hash("leftover");
|
|
4362
|
-
|
|
4363
|
-
if (!NIL_P(zone)) {
|
|
4364
|
-
rb_enc_copy(zone, vstr);
|
|
4365
|
-
set_hash("zone", zone);
|
|
4366
|
-
}
|
|
4367
|
-
if (!NIL_P(left)) {
|
|
4368
|
-
rb_enc_copy(left, vstr);
|
|
4369
|
-
set_hash("leftover", left);
|
|
4370
|
-
}
|
|
4371
|
-
}
|
|
4372
|
-
|
|
4373
|
-
return hash;
|
|
4591
|
+
return date__strptime(str, slen, fmt, flen, hash, enc);
|
|
4374
4592
|
}
|
|
4375
4593
|
|
|
4376
4594
|
/*
|
|
@@ -5810,7 +6028,7 @@ dup_obj_with_new_start(VALUE obj, double sg)
|
|
|
5810
6028
|
|
|
5811
6029
|
/*
|
|
5812
6030
|
* call-seq:
|
|
5813
|
-
* new_start(start = Date::ITALY
|
|
6031
|
+
* new_start(start = Date::ITALY) -> new_date
|
|
5814
6032
|
*
|
|
5815
6033
|
* Returns a copy of +self+ with the given +start+ value:
|
|
5816
6034
|
*
|
|
@@ -7285,7 +7503,7 @@ strftimev(const char *fmt, VALUE self,
|
|
|
7285
7503
|
*
|
|
7286
7504
|
* Date.new(2001, 2, 3).asctime # => "Sat Feb 3 00:00:00 2001"
|
|
7287
7505
|
*
|
|
7288
|
-
* See {asctime}[https://
|
|
7506
|
+
* See {asctime}[https://man7.org/linux/man-pages/man3/asctime.3p.html].
|
|
7289
7507
|
*
|
|
7290
7508
|
*/
|
|
7291
7509
|
static VALUE
|
|
@@ -7611,8 +7829,6 @@ d_lite_marshal_load(VALUE self, VALUE a)
|
|
|
7611
7829
|
if (simple_dat_p(dat)) {
|
|
7612
7830
|
if (df || !f_zero_p(sf) || of) {
|
|
7613
7831
|
/* loading a fractional date; promote to complex */
|
|
7614
|
-
dat = ruby_xrealloc(dat, sizeof(struct ComplexDateData));
|
|
7615
|
-
RTYPEDDATA(self)->data = dat;
|
|
7616
7832
|
goto complex_data;
|
|
7617
7833
|
}
|
|
7618
7834
|
set_to_simple(self, &dat->s, nth, jd, sg, 0, 0, 0, HAVE_JD);
|
data/ext/date/date_parse.c
CHANGED
|
@@ -2325,6 +2325,16 @@ sec_fraction(VALUE f)
|
|
|
2325
2325
|
|
|
2326
2326
|
#define SNUM 14
|
|
2327
2327
|
|
|
2328
|
+
#ifndef rb_streql_lit
|
|
2329
|
+
static inline int
|
|
2330
|
+
rb_streql_cstr(VALUE str, const char *lit, size_t len)
|
|
2331
|
+
{
|
|
2332
|
+
if ((size_t)RSTRING_LEN(str) != len) return 0;
|
|
2333
|
+
return memcmp(RSTRING_PTR(str), lit, len) == 0;
|
|
2334
|
+
}
|
|
2335
|
+
#define rb_streql_lit(str, lit) rb_streql_cstr(str, lit, sizeof(lit "") - 1)
|
|
2336
|
+
#endif
|
|
2337
|
+
|
|
2328
2338
|
static int
|
|
2329
2339
|
iso8601_ext_datetime_cb(VALUE m, VALUE hash)
|
|
2330
2340
|
{
|
|
@@ -2339,14 +2349,14 @@ iso8601_ext_datetime_cb(VALUE m, VALUE hash)
|
|
|
2339
2349
|
|
|
2340
2350
|
if (!NIL_P(s[1])) {
|
|
2341
2351
|
if (!NIL_P(s[3])) set_hash("mday", str2num(s[3]));
|
|
2342
|
-
if (
|
|
2352
|
+
if (!rb_streql_lit(s[1], "-")) {
|
|
2343
2353
|
y = str2num(s[1]);
|
|
2344
2354
|
if (RSTRING_LEN(s[1]) < 4)
|
|
2345
2355
|
y = comp_year69(y);
|
|
2346
2356
|
set_hash("year", y);
|
|
2347
2357
|
}
|
|
2348
2358
|
if (NIL_P(s[2])) {
|
|
2349
|
-
if (
|
|
2359
|
+
if (!rb_streql_lit(s[1], "-"))
|
|
2350
2360
|
return 0;
|
|
2351
2361
|
}
|
|
2352
2362
|
else
|
|
@@ -2425,14 +2435,14 @@ iso8601_bas_datetime_cb(VALUE m, VALUE hash)
|
|
|
2425
2435
|
|
|
2426
2436
|
if (!NIL_P(s[3])) {
|
|
2427
2437
|
set_hash("mday", str2num(s[3]));
|
|
2428
|
-
if (
|
|
2438
|
+
if (!rb_streql_lit(s[1], "--")) {
|
|
2429
2439
|
y = str2num(s[1]);
|
|
2430
2440
|
if (RSTRING_LEN(s[1]) < 4)
|
|
2431
2441
|
y = comp_year69(y);
|
|
2432
2442
|
set_hash("year", y);
|
|
2433
2443
|
}
|
|
2434
2444
|
if (*RSTRING_PTR(s[2]) == '-') {
|
|
2435
|
-
if (
|
|
2445
|
+
if (!rb_streql_lit(s[1], "--"))
|
|
2436
2446
|
return 0;
|
|
2437
2447
|
}
|
|
2438
2448
|
else
|
data/ext/date/date_strptime.c
CHANGED
|
@@ -41,7 +41,6 @@ static const int ABBREVIATED_MONTH_NAME_LENGTH = 3;
|
|
|
41
41
|
|
|
42
42
|
#define f_match(r,s) rb_funcall(r, rb_intern("match"), 1, s)
|
|
43
43
|
#define f_aref(o,i) rb_funcall(o, rb_intern("[]"), 1, i)
|
|
44
|
-
#define f_end(o,i) rb_funcall(o, rb_intern("end"), 1, i)
|
|
45
44
|
|
|
46
45
|
#define issign(c) ((c) == '-' || (c) == '+')
|
|
47
46
|
|
|
@@ -144,7 +143,7 @@ valid_range_p(VALUE v, int a, int b)
|
|
|
144
143
|
do { \
|
|
145
144
|
size_t l; \
|
|
146
145
|
l = date__strptime_internal(&str[si], slen - si, \
|
|
147
|
-
fmt, sizeof fmt - 1, hash); \
|
|
146
|
+
fmt, sizeof fmt - 1, hash, enc); \
|
|
148
147
|
if (fail_p()) \
|
|
149
148
|
return 0; \
|
|
150
149
|
si += l; \
|
|
@@ -160,7 +159,8 @@ head_match_p(size_t len, const char *name, const char *str, size_t slen, size_t
|
|
|
160
159
|
|
|
161
160
|
static size_t
|
|
162
161
|
date__strptime_internal(const char *str, size_t slen,
|
|
163
|
-
const char *fmt, size_t flen,
|
|
162
|
+
const char *fmt, size_t flen,
|
|
163
|
+
VALUE hash, rb_encoding *enc)
|
|
164
164
|
{
|
|
165
165
|
size_t si, fi;
|
|
166
166
|
int c;
|
|
@@ -597,15 +597,14 @@ date__strptime_internal(const char *str, size_t slen,
|
|
|
597
597
|
|
|
598
598
|
b = rb_backref_get();
|
|
599
599
|
rb_match_busy(b);
|
|
600
|
-
m = f_match(pat,
|
|
600
|
+
m = f_match(pat, rb_enc_str_new(&str[si], slen - si, enc));
|
|
601
601
|
|
|
602
602
|
if (!NIL_P(m)) {
|
|
603
|
-
VALUE s,
|
|
603
|
+
VALUE s, o;
|
|
604
604
|
|
|
605
605
|
s = rb_reg_nth_match(1, m);
|
|
606
|
-
l = f_end(m, INT2FIX(0));
|
|
607
606
|
o = date_zone_to_diff(s);
|
|
608
|
-
si +=
|
|
607
|
+
si += RSTRING_LEN(s);
|
|
609
608
|
set_hash("zone", s);
|
|
610
609
|
set_hash("offset", o);
|
|
611
610
|
rb_backref_set(b);
|
|
@@ -654,23 +653,24 @@ date__strptime_internal(const char *str, size_t slen,
|
|
|
654
653
|
|
|
655
654
|
VALUE
|
|
656
655
|
date__strptime(const char *str, size_t slen,
|
|
657
|
-
const char *fmt, size_t flen,
|
|
656
|
+
const char *fmt, size_t flen,
|
|
657
|
+
VALUE hash, rb_encoding *enc)
|
|
658
658
|
{
|
|
659
659
|
size_t si;
|
|
660
660
|
VALUE cent, merid;
|
|
661
661
|
|
|
662
|
-
si = date__strptime_internal(str, slen, fmt, flen, hash);
|
|
662
|
+
si = date__strptime_internal(str, slen, fmt, flen, hash, enc);
|
|
663
|
+
|
|
664
|
+
if (fail_p())
|
|
665
|
+
return Qnil;
|
|
663
666
|
|
|
664
667
|
if (slen > si) {
|
|
665
668
|
VALUE s;
|
|
666
669
|
|
|
667
|
-
s =
|
|
670
|
+
s = rb_enc_str_new(&str[si], slen - si, enc);
|
|
668
671
|
set_hash("leftover", s);
|
|
669
672
|
}
|
|
670
673
|
|
|
671
|
-
if (fail_p())
|
|
672
|
-
return Qnil;
|
|
673
|
-
|
|
674
674
|
cent = del_hash("_cent");
|
|
675
675
|
if (!NIL_P(cent)) {
|
|
676
676
|
VALUE year;
|
data/ext/date/extconf.rb
CHANGED
|
@@ -3,6 +3,9 @@ require 'mkmf'
|
|
|
3
3
|
|
|
4
4
|
config_string("strict_warnflags") {|w| $warnflags += " #{w}"}
|
|
5
5
|
|
|
6
|
+
unless try_compile("", "", werror: true)
|
|
7
|
+
append_cflags("-Wno-default-const-init-field-unsafe")
|
|
8
|
+
end
|
|
6
9
|
append_cflags("-Wno-compound-token-split-by-macro") if RUBY_VERSION < "2.7."
|
|
7
10
|
have_func("rb_category_warn")
|
|
8
11
|
with_werror("", {:werror => true}) do |opt, |
|
|
@@ -10,4 +13,7 @@ with_werror("", {:werror => true}) do |opt, |
|
|
|
10
13
|
have_var("altzone", "time.h", opt)
|
|
11
14
|
end
|
|
12
15
|
|
|
16
|
+
have_func("rb_gc_mark_movable", "ruby.h") # RUBY_VERSION >= 2.7
|
|
17
|
+
have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3
|
|
18
|
+
|
|
13
19
|
create_makefile('date_core')
|
data/lib/date.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: date
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tadayoshi Funaba
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-10-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: The official date library for Ruby.
|
|
14
14
|
email:
|