Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: b69aa17d35c1
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 25cc7a0ee029
Choose a head ref
  • 2 commits
  • 7 files changed
  • 1 contributor

Commits on Mar 26, 2018

  1. Copy the full SHA
    247a183 View commit details
  2. [fix] make sure we account for fractional part on jd/ordinal/civil etc.

    resolves GH-5110 ... (another follow-up on date.rb refactoring #5076)
    kares committed Mar 26, 2018
    Copy the full SHA
    25cc7a0 View commit details
5 changes: 5 additions & 0 deletions core/src/main/java/org/jruby/RubyBignum.java
Original file line number Diff line number Diff line change
@@ -1057,6 +1057,11 @@ public final boolean isZero() {
return value.equals(BigInteger.ZERO);
}

@Override
public IRubyObject nonzero_p(ThreadContext context) {
return isZero() ? context.nil : this;
}

public static void marshalTo(RubyBignum bignum, MarshalStream output) throws IOException {
output.registerLinkTarget(bignum);

5 changes: 5 additions & 0 deletions core/src/main/java/org/jruby/RubyFixnum.java
Original file line number Diff line number Diff line change
@@ -1273,6 +1273,11 @@ public final boolean isZero() {
return value == 0;
}

@Override
public IRubyObject nonzero_p(ThreadContext context) {
return isZero() ? context.nil : this;
}

@Override
final boolean isOne() {
return value == 1;
5 changes: 5 additions & 0 deletions core/src/main/java/org/jruby/RubyFloat.java
Original file line number Diff line number Diff line change
@@ -722,6 +722,11 @@ public final boolean isZero() {
return value == 0.0;
}

@Override
public IRubyObject nonzero_p(ThreadContext context) {
return isZero() ? context.nil : this;
}

/**
* MRI: flo_truncate
*/
5 changes: 5 additions & 0 deletions core/src/main/java/org/jruby/RubyRational.java
Original file line number Diff line number Diff line change
@@ -432,6 +432,11 @@ public final boolean isZero() {
return num.isZero();
}

@Override
public IRubyObject nonzero_p(ThreadContext context) {
return isZero() ? context.nil : this;
}

@Override
public IRubyObject isNegative(ThreadContext context) {
return context.runtime.newBoolean(signum() < 0);
55 changes: 39 additions & 16 deletions core/src/main/java/org/jruby/ext/date/RubyDate.java
Original file line number Diff line number Diff line change
@@ -176,6 +176,12 @@ public RubyDate(Ruby runtime, long millis, Chronology chronology) {
this(context, klass, ajd, getChronology(context, start, off), off, start);
}

RubyDate(ThreadContext context, RubyClass klass, IRubyObject ajd, long[] rest, int off, long start) {
this(context, klass, ajd, getChronology(context, start, off), off, start);

if (rest[0] != 0) adjustWithDayFraction(context, this.dt, rest);
}

private RubyDate(ThreadContext context, RubyClass klass, IRubyObject ajd, Chronology chronology, int off, long start) {
super(context.runtime, klass);

@@ -399,18 +405,21 @@ static DateTime civilImpl(ThreadContext context, IRubyObject year, IRubyObject m
@JRubyMethod(name = "civil", alias = "new", meta = true)
public static RubyDate civil(ThreadContext context, IRubyObject self, IRubyObject year, IRubyObject month, IRubyObject mday) {
// return civil(context, self, new IRubyObject[] { year, month, mday, RubyFixnum.newFixnum(context.runtime, ITALY) });
return new RubyDate(context.runtime, (RubyClass) self, civilImpl(context, year, month, mday, ITALY));
return civilImpl(context, (RubyClass) self, year, month, mday, ITALY);
}

static DateTime civilImpl(ThreadContext context, IRubyObject year, IRubyObject month, IRubyObject mday, final long sg) {
private static RubyDate civilImpl(ThreadContext context, RubyClass klass,
IRubyObject year, IRubyObject month, IRubyObject mday, final long sg) {
final int y = (sg > 0) ? getYear(year) : year.convertToInteger().getIntValue();
final int m = getMonth(month);
final long[] rest = new long[] { 0, 1 };
final int d = (int) getDay(context, mday, rest);

DateTime dt = civilDate(context, y, m ,d, getChronology(context, sg, 0));
if (rest[0] != 0) dt = adjustWithDayFraction(context, dt, rest);
return dt;

RubyDate date = new RubyDate(context.runtime, klass, dt, 0, sg);
if (rest[0] != 0) date.adjustWithDayFraction(context, dt, rest);
return date;
}

@JRubyMethod(name = "civil", alias = "new", meta = true, optional = 4) // 4 args case
@@ -428,9 +437,7 @@ public static RubyDate civil(ThreadContext context, IRubyObject self, IRubyObjec

final long sg = val2sg(context, args[3]);

RubyDate date = new RubyDate(context.runtime, (RubyClass) self, civilImpl(context, args[0], args[1], args[2], sg));
date.start = sg;
return date;
return civilImpl(context, (RubyClass) self, args[0], args[1], args[2], sg);
}

static DateTime civilDate(ThreadContext context, final int y, final int m, final int d, final Chronology chronology) {
@@ -539,12 +546,10 @@ private static RubyDate jdImpl(ThreadContext context, IRubyObject self, IRubyObj
long jdi = getDay(context, jd, rest);
RubyNumeric ajd = jd_to_ajd(context, jdi);

RubyDate date = new RubyDate(context, (RubyClass) self, ajd, 0, sg);
if (rest[0] != 0) date.dt = adjustWithDayFraction(context, date.dt, rest);
return date;
return new RubyDate(context, (RubyClass) self, ajd, rest, 0, sg);
}

static DateTime adjustWithDayFraction(ThreadContext context, DateTime dt, final long[] rest) {
private void adjustWithDayFraction(ThreadContext context, DateTime dt, final long[] rest) {
final RubyFixnum zero = RubyFixnum.zero(context.runtime);
int ival;

@@ -558,9 +563,22 @@ static DateTime adjustWithDayFraction(ThreadContext context, DateTime dt, final
if (rest[0] != 0) {
ival = getSecond(context, zero, rest);
dt = dt.plusSeconds(ival);

final long r0 = rest[0], r1 = rest[1];
if (r0 != 0) {
long millis = ( 1000 * r0 ) / r1;
dt = dt.plusMillis((int) millis);

subMillisNum = ((1000 * r0) - (millis * r1));
subMillisDen = r1;
long gcd = i_gcd(subMillisNum, subMillisDen);
subMillisNum = subMillisNum / gcd;
subMillisDen = subMillisDen / gcd;
}
}
}
return dt;

this.dt = dt;
}

@JRubyMethod(name = "valid_jd?", meta = true)
@@ -597,11 +615,13 @@ public static RubyDate ordinal(ThreadContext context, IRubyObject self, IRubyObj
IRubyObject year = (len > 0) ? args[0] : RubyFixnum.newFixnum(context.runtime, -4712);
IRubyObject day = (len > 1) ? args[1] : RubyFixnum.newFixnum(context.runtime, 1);

Long jd = validOrdinalImpl(year, day, sg);
final long[] rest = new long[] { 0, 1 };
final int d = (int) getDay(context, day, rest);
Long jd = validOrdinalImpl(year, d, sg);
if (jd == null) {
throw context.runtime.newArgumentError("invalid date");
}
return new RubyDate(context, (RubyClass) self, jd_to_ajd(context, jd), 0, sg);
return new RubyDate(context, (RubyClass) self, jd_to_ajd(context, jd), rest, 0, sg);
}

@JRubyMethod(name = "valid_ordinal?", meta = true, required = 2, optional = 1)
@@ -612,9 +632,12 @@ public static IRubyObject valid_ordinal_p(ThreadContext context, IRubyObject sel
}

static Long validOrdinalImpl(IRubyObject year, IRubyObject day, final long sg) {
return validOrdinalImpl(year, day.convertToInteger().getIntValue(), sg);
}

private static Long validOrdinalImpl(IRubyObject year, int day, final long sg) {
final int y = year.convertToInteger().getIntValue();
int d = day.convertToInteger().getIntValue();
return DateUtils._valid_ordinal_p(y, d, sg);
return DateUtils._valid_ordinal_p(y, day, sg);
}

@Deprecated // NOTE: should go away once no date.rb is using it
10 changes: 6 additions & 4 deletions core/src/main/java/org/jruby/ext/date/RubyDateTime.java
Original file line number Diff line number Diff line change
@@ -99,6 +99,10 @@ public RubyDateTime(Ruby runtime, long millis, Chronology chronology) {
super(context, klass, ajd, off, start);
}

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

private RubyDateTime(Ruby runtime, RubyClass klass, DateTime dt, int off) {
super(runtime, klass);

@@ -229,7 +233,7 @@ static long getDay(ThreadContext context, IRubyObject day, final long[] rest) {
if (!(day instanceof RubyInteger) && day instanceof RubyNumeric) { // Rational|Float
RubyRational rat = ((RubyNumeric) day).convertToRational();
long num = rat.getNumerator().getLongValue();
int den = rat.getDenominator().getIntValue();
long den = rat.getDenominator().getLongValue();
rest[0] = (num - d * den); rest[1] = den;
}

@@ -343,9 +347,7 @@ public static RubyDateTime jd(ThreadContext context, IRubyObject self, IRubyObje
if (len > 5) sg = val2sg(context, args[5]);

RubyNumeric ajd = jd_to_ajd(context, jd, fr, off);
RubyDateTime dateTime = new RubyDateTime(context, (RubyClass) self, ajd, off, sg);
if (rest[0] != 0) dateTime.dt = adjustWithDayFraction(context, dateTime.dt, rest);
return dateTime;
return new RubyDateTime(context, (RubyClass) self, ajd, rest, off, sg);
}

/**
29 changes: 29 additions & 0 deletions test/jruby/test_date.rb
Original file line number Diff line number Diff line change
@@ -752,4 +752,33 @@ def test_jd_day_fraction
assert_equal '2018-03-18T23:00:01+00:00', dt.to_s
end

def test_jd_sec_fraction
jd = (86400 * DateTime.new(1970, 1, 1).jd + Time.utc(2018, 3, 25, 23).to_i)/86400r + 1/864000r
dt = DateTime.jd(jd)
assert_equal '2018-03-25T23:00:00+00:00', dt.to_s
#assert_equal 1r/10, dt.sec_fraction

dt = Date.jd(jd)
assert_equal '2018-03-25', dt.to_s
assert_equal 1r/10, dt.send(:sec_fraction)
end

def test_ordinal_sec_fraction
dt = Date.ordinal 2018, 111r/3 + 3/(864_000r * 1000)
assert_equal '2018-02-06', dt.to_s
assert_equal 3r/10_000, dt.send(:sec_fraction)
end

def test_commercial_sec_fraction
dt = Date.ordinal 2018, 221r/3 + 4/(864_000r * 10)
assert_equal '2018-03-14', dt.to_s
assert_equal 4r/100, dt.send(:sec_fraction)
end

def test_civil_sec_fraction
dt = Date.civil 2018, 11, 22r/3 + 3/(864_000 * 10_000r)
assert_equal '2018-11-07', dt.to_s
assert_equal 3r/100_000, dt.send(:sec_fraction)
end

end