Skip to content

Commit

Permalink
work-around JODA considering 'missing' (reform) dates as invalid
Browse files Browse the repository at this point in the history
... somehow naively assumed its re-calculating with the DateTime ctor
  • Loading branch information
kares committed Mar 12, 2018
1 parent 3615ebb commit 2d16dd2
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 11 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ext/date/RubyDate.java
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ private void initialize(final ThreadContext context, IRubyObject arg, IRubyObjec
}

static final int DAY_IN_SECONDS = 86_400; // 24 * 60 * 60
private static final int DAY_MS = 86_400_000; // 24 * 60 * 60 * 1000
static final int DAY_MS = 86_400_000; // 24 * 60 * 60 * 1000
private static RubyFixnum DAY_MS_CACHE;

private long initMillis(final ThreadContext context, IRubyObject ajd) {
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ext/date/RubyDateTime.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public RubyDateTime(Ruby runtime, long millis, Chronology chronology) {
super(runtime, getDateTime(runtime), new DateTime(millis, chronology));
}

private RubyDateTime(ThreadContext context, RubyClass klass, IRubyObject ajd, int off, long start) {
RubyDateTime(ThreadContext context, RubyClass klass, IRubyObject ajd, int off, long start) {
super(context, klass, ajd, off, start);
}

Expand Down
37 changes: 28 additions & 9 deletions core/src/main/java/org/jruby/ext/date/TimeExt.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,6 @@ public static RubyDateTime to_datetime(ThreadContext context, IRubyObject self)
final RubyTime time = (RubyTime) self;
DateTime dt = ((RubyTime) self).getDateTime();

final int off = dt.getZone().getOffset(dt.getMillis()) / 1000;

int year = dt.getYear(); if (year <= 0) year--; // JODA's Julian chronology (no year 0)
dt = new DateTime(
year, dt.getMonthOfYear(), dt.getDayOfMonth(),
dt.getHourOfDay(), dt.getMinuteOfHour(), dt.getSecondOfMinute(),
dt.getMillisOfSecond(), getChronology(context, ITALY, dt.getZone())
);

long subMillisNum = 0, subMillisDen = 1;
if (time.getNSec() != 0) {
IRubyObject subMillis = RubyRational.newRationalCanonicalize(context, time.getNSec(), 1_000_000);
Expand All @@ -86,7 +77,35 @@ public static RubyDateTime to_datetime(ThreadContext context, IRubyObject self)
}
}

final int off = dt.getZone().getOffset(dt.getMillis()) / 1000;

int year = dt.getYear(); if (year <= 0) year--; // JODA's Julian chronology (no year 0)

if (year == 1582) { // take the "slow" path - JODA isn't adjusting for missing (reform) dates
return calcAjdFromCivil(context, dt, off, subMillisNum, subMillisDen);
}

dt = new DateTime(
year, dt.getMonthOfYear(), dt.getDayOfMonth(),
dt.getHourOfDay(), dt.getMinuteOfHour(), dt.getSecondOfMinute(),
dt.getMillisOfSecond(), getChronology(context, ITALY, dt.getZone())
);

return new RubyDateTime(context.runtime, getDateTime(context.runtime), dt, off, ITALY, subMillisNum, subMillisDen);
}

private static RubyDateTime calcAjdFromCivil(ThreadContext context, final DateTime dt, final int off,
final long subMillisNum, final long subMillisDen) {
final Ruby runtime = context.runtime;

long jd = civil_to_jd(dt.getYear(), dt.getMonthOfYear(), dt.getDayOfMonth(), ITALY);
RubyNumeric fr = timeToDayFraction(context, dt.getHourOfDay(), dt.getMinuteOfHour(), dt.getSecondOfMinute());

final RubyNumeric ajd = jd_to_ajd(context, jd, fr, off);
RubyDateTime dateTime = new RubyDateTime(context, getDateTime(runtime), ajd, off, ITALY);
dateTime.dt = dateTime.dt.withMillisOfSecond(dt.getMillisOfSecond());
dateTime.subMillisNum = subMillisNum; dateTime.subMillisDen = subMillisDen;
return dateTime;
}

}
16 changes: 16 additions & 0 deletions test/jruby/test_date.rb
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,20 @@ def test_to_datetime
assert_equal dt, time.to_datetime
end

def test_to_datetime_reform
time = Time.utc(1582, 10, 15, 1, 2, 3)
dt = time.to_datetime
assert_equal [1582, 10, 15, 1, 2, 3], [ dt.year, dt.month, dt.day, dt.hour, dt.min, dt.sec ]

utc_time = Time.utc(1582, 10, 14, 1, 2, 3, 45 + Rational(6789, 10_000))
dt = utc_time.to_datetime
assert_equal DateTime::ITALY, dt.start
assert_equal [1582, 10, 24, 1, 2, 3], [ dt.year, dt.month, dt.day, dt.hour, dt.min, dt.sec ]
time = dt.to_time
assert_equal [1582, 10, 24], [ time.year, time.month, time.day ]
assert utc_time != time # no round-trip possible
end

def test_to_time_roundtrip # based on AR-JDBC testing
time = Time.utc(3, 12, 31, 23, 58, 59)
time2 = time.to_datetime.to_time # '0004-01-01 00:56:43 +0057' in < 9.2
Expand All @@ -610,6 +624,7 @@ def test_to_date
assert_equal 0, date.send(:hour)
assert_equal 0, date.send(:minute)
assert_equal 0, date.send(:second)
assert_equal Date::ITALY, date.start

date = dt.to_time.to_date
assert_equal 2012, date.year
Expand All @@ -618,6 +633,7 @@ def test_to_date
assert_equal 0, date.send(:hour)
assert_equal 0, date.send(:minute)
assert_equal 0, date.send(:second)
assert_equal Date::ITALY, date.start

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

0 comments on commit 2d16dd2

Please sign in to comment.