Skip to content

Commit 2d16dd2

Browse files
committedMar 12, 2018
work-around JODA considering 'missing' (reform) dates as invalid
... somehow naively assumed its re-calculating with the DateTime ctor
1 parent 3615ebb commit 2d16dd2

File tree

4 files changed

+46
-11
lines changed

4 files changed

+46
-11
lines changed
 

Diff for: ‎core/src/main/java/org/jruby/ext/date/RubyDate.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ private void initialize(final ThreadContext context, IRubyObject arg, IRubyObjec
226226
}
227227

228228
static final int DAY_IN_SECONDS = 86_400; // 24 * 60 * 60
229-
private static final int DAY_MS = 86_400_000; // 24 * 60 * 60 * 1000
229+
static final int DAY_MS = 86_400_000; // 24 * 60 * 60 * 1000
230230
private static RubyFixnum DAY_MS_CACHE;
231231

232232
private long initMillis(final ThreadContext context, IRubyObject ajd) {

Diff for: ‎core/src/main/java/org/jruby/ext/date/RubyDateTime.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public RubyDateTime(Ruby runtime, long millis, Chronology chronology) {
9494
super(runtime, getDateTime(runtime), new DateTime(millis, chronology));
9595
}
9696

97-
private RubyDateTime(ThreadContext context, RubyClass klass, IRubyObject ajd, int off, long start) {
97+
RubyDateTime(ThreadContext context, RubyClass klass, IRubyObject ajd, int off, long start) {
9898
super(context, klass, ajd, off, start);
9999
}
100100

Diff for: ‎core/src/main/java/org/jruby/ext/date/TimeExt.java

+28-9
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,6 @@ public static RubyDateTime to_datetime(ThreadContext context, IRubyObject self)
6565
final RubyTime time = (RubyTime) self;
6666
DateTime dt = ((RubyTime) self).getDateTime();
6767

68-
final int off = dt.getZone().getOffset(dt.getMillis()) / 1000;
69-
70-
int year = dt.getYear(); if (year <= 0) year--; // JODA's Julian chronology (no year 0)
71-
dt = new DateTime(
72-
year, dt.getMonthOfYear(), dt.getDayOfMonth(),
73-
dt.getHourOfDay(), dt.getMinuteOfHour(), dt.getSecondOfMinute(),
74-
dt.getMillisOfSecond(), getChronology(context, ITALY, dt.getZone())
75-
);
76-
7768
long subMillisNum = 0, subMillisDen = 1;
7869
if (time.getNSec() != 0) {
7970
IRubyObject subMillis = RubyRational.newRationalCanonicalize(context, time.getNSec(), 1_000_000);
@@ -86,7 +77,35 @@ public static RubyDateTime to_datetime(ThreadContext context, IRubyObject self)
8677
}
8778
}
8879

80+
final int off = dt.getZone().getOffset(dt.getMillis()) / 1000;
81+
82+
int year = dt.getYear(); if (year <= 0) year--; // JODA's Julian chronology (no year 0)
83+
84+
if (year == 1582) { // take the "slow" path - JODA isn't adjusting for missing (reform) dates
85+
return calcAjdFromCivil(context, dt, off, subMillisNum, subMillisDen);
86+
}
87+
88+
dt = new DateTime(
89+
year, dt.getMonthOfYear(), dt.getDayOfMonth(),
90+
dt.getHourOfDay(), dt.getMinuteOfHour(), dt.getSecondOfMinute(),
91+
dt.getMillisOfSecond(), getChronology(context, ITALY, dt.getZone())
92+
);
93+
8994
return new RubyDateTime(context.runtime, getDateTime(context.runtime), dt, off, ITALY, subMillisNum, subMillisDen);
9095
}
9196

97+
private static RubyDateTime calcAjdFromCivil(ThreadContext context, final DateTime dt, final int off,
98+
final long subMillisNum, final long subMillisDen) {
99+
final Ruby runtime = context.runtime;
100+
101+
long jd = civil_to_jd(dt.getYear(), dt.getMonthOfYear(), dt.getDayOfMonth(), ITALY);
102+
RubyNumeric fr = timeToDayFraction(context, dt.getHourOfDay(), dt.getMinuteOfHour(), dt.getSecondOfMinute());
103+
104+
final RubyNumeric ajd = jd_to_ajd(context, jd, fr, off);
105+
RubyDateTime dateTime = new RubyDateTime(context, getDateTime(runtime), ajd, off, ITALY);
106+
dateTime.dt = dateTime.dt.withMillisOfSecond(dt.getMillisOfSecond());
107+
dateTime.subMillisNum = subMillisNum; dateTime.subMillisDen = subMillisDen;
108+
return dateTime;
109+
}
110+
92111
}

Diff for: ‎test/jruby/test_date.rb

+16
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,20 @@ def test_to_datetime
590590
assert_equal dt, time.to_datetime
591591
end
592592

593+
def test_to_datetime_reform
594+
time = Time.utc(1582, 10, 15, 1, 2, 3)
595+
dt = time.to_datetime
596+
assert_equal [1582, 10, 15, 1, 2, 3], [ dt.year, dt.month, dt.day, dt.hour, dt.min, dt.sec ]
597+
598+
utc_time = Time.utc(1582, 10, 14, 1, 2, 3, 45 + Rational(6789, 10_000))
599+
dt = utc_time.to_datetime
600+
assert_equal DateTime::ITALY, dt.start
601+
assert_equal [1582, 10, 24, 1, 2, 3], [ dt.year, dt.month, dt.day, dt.hour, dt.min, dt.sec ]
602+
time = dt.to_time
603+
assert_equal [1582, 10, 24], [ time.year, time.month, time.day ]
604+
assert utc_time != time # no round-trip possible
605+
end
606+
593607
def test_to_time_roundtrip # based on AR-JDBC testing
594608
time = Time.utc(3, 12, 31, 23, 58, 59)
595609
time2 = time.to_datetime.to_time # '0004-01-01 00:56:43 +0057' in < 9.2
@@ -610,6 +624,7 @@ def test_to_date
610624
assert_equal 0, date.send(:hour)
611625
assert_equal 0, date.send(:minute)
612626
assert_equal 0, date.send(:second)
627+
assert_equal Date::ITALY, date.start
613628

614629
date = dt.to_time.to_date
615630
assert_equal 2012, date.year
@@ -618,6 +633,7 @@ def test_to_date
618633
assert_equal 0, date.send(:hour)
619634
assert_equal 0, date.send(:minute)
620635
assert_equal 0, date.send(:second)
636+
assert_equal Date::ITALY, date.start
621637

622638
dt = DateTime.new(1008, 12, 9, 10, 40, 00, '+11:00')
623639
date = dt.to_date

0 commit comments

Comments
 (0)
Please sign in to comment.