Skip to content

Commit

Permalink
Move Time#new logic into #initialize as in MRI. Fixes #5125.
Browse files Browse the repository at this point in the history
  • Loading branch information
headius committed Apr 11, 2018
1 parent cc93db8 commit fd83bda
Showing 1 changed file with 64 additions and 65 deletions.
129 changes: 64 additions & 65 deletions core/src/main/java/org/jruby/RubyTime.java
Expand Up @@ -52,7 +52,6 @@
import org.jruby.runtime.Block;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.JavaSites.TimeSites;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
Expand All @@ -65,7 +64,6 @@

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
Expand Down Expand Up @@ -391,34 +389,7 @@ public RubyTime(Ruby runtime, RubyClass rubyClass, DateTime dt) {
private static ObjectAllocator TIME_ALLOCATOR = new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
DateTimeZone dtz = getLocalTimeZone(runtime);
long msecs;
long nsecs;
POSIX posix = runtime.getPosix();
if (posix.isNative()) {
// FIXME: we should have a pure Java fallback in jnr-posix and Windows is missing gettimeofday impl
try {
Timeval tv = posix.allocateTimeval();
posix.gettimeofday(tv);

long secs = tv.sec();
long usecs = tv.usec();

msecs = secs * 1000 + (usecs / 1000);
nsecs = usecs % 1000 * 1000;
} catch (RaiseException notImplementedError) {
msecs = System.currentTimeMillis();
nsecs = 0;
}
} else {
msecs = System.currentTimeMillis();
nsecs = 0;
}
DateTime dt = new DateTime(msecs, dtz);
RubyTime rt = new RubyTime(runtime, klass, dt);
rt.setNSec(nsecs);

return rt;
return new RubyTime(runtime, klass);
}
};

Expand Down Expand Up @@ -1051,11 +1022,6 @@ public RubyObject mdump() {
return string;
}

@JRubyMethod(visibility = PRIVATE)
public IRubyObject initialize(Block block) {
return this;
}

@JRubyMethod(optional = 1)
public RubyTime round(ThreadContext context, IRubyObject[] args) {
int ndigits = args.length == 0 ? 0 : RubyNumeric.num2int(args[0]);
Expand Down Expand Up @@ -1169,8 +1135,6 @@ public static IRubyObject at(ThreadContext context, IRubyObject recv, IRubyObjec
time.setNSec(nanosecs);
}

time.getMetaClass().getBaseCallSite(RubyClass.CS_IDX_INITIALIZE).call(context, recv, time);

return time;
}

Expand Down Expand Up @@ -1210,27 +1174,50 @@ public static IRubyObject at(ThreadContext context, IRubyObject recv, IRubyObjec
time.setNSec(nanosecs % 1000000);
time.dt = time.dt.withMillis(millisecs + nanosecOverflow);

time.getMetaClass().getBaseCallSite(RubyClass.CS_IDX_INITIALIZE).call(context, recv, time);

return time;
}

@JRubyMethod(name = {"local", "mktime"}, required = 1, optional = 9, meta = true)
public static RubyTime local(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
return createTime(context, (RubyClass) recv, args, false, false);
return ((RubyTime) ((RubyClass) recv).allocate()).initTime(context, args, false, false);
}

public static RubyTime new_local(IRubyObject recv, IRubyObject[] args) {
return createTime(recv.getRuntime().getCurrentContext(), (RubyClass) recv, args, false, false);
}
@JRubyMethod(name = "initialize", optional = 7, visibility = PRIVATE)
public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
Ruby runtime = context.runtime;

@JRubyMethod(name = "new", optional = 7, meta = true)
public static IRubyObject new19(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
if (args.length == 0) return newInstance(context, recv);
if (args.length == 0) {
DateTimeZone dtz = getLocalTimeZone(runtime);
long msecs;
long nsecs;
POSIX posix = runtime.getPosix();
if (posix.isNative()) {
// FIXME: we should have a pure Java fallback in jnr-posix and Windows is missing gettimeofday impl
try {
Timeval tv = posix.allocateTimeval();
posix.gettimeofday(tv);

if (args.length == 7) {
Ruby runtime = context.getRuntime();
long secs = tv.sec();
long usecs = tv.usec();

msecs = secs * 1000 + (usecs / 1000);
nsecs = usecs % 1000 * 1000;
} catch (RaiseException notImplementedError) {
msecs = System.currentTimeMillis();
nsecs = 0;
}
} else {
msecs = System.currentTimeMillis();
nsecs = 0;
}
DateTime dt = new DateTime(msecs, dtz);
this.dt = dt;
this.setNSec(nsecs);

return context.nil;
}

if (args.length == 7) {
// 7th argument can be the symbol :dst instead of an offset, so needs to be special cased
final RubySymbol dstSymbol = RubySymbol.newSymbol(runtime, "dst");
boolean receivedDstSymbolAsArgument = (args[6].op_equal(context, dstSymbol)).isTrue();
Expand All @@ -1249,17 +1236,13 @@ public static IRubyObject new19(ThreadContext context, IRubyObject recv, IRubyOb
isDst, // is DST?
args[6] }; // UTC offset
}
return createTime(context, (RubyClass) recv, args, false, true);
}

return initTime(context, args, false, true);
}

@JRubyMethod(name = {"utc", "gm"}, required = 1, optional = 9, meta = true)
public static RubyTime utc(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
return createTime(context, (RubyClass) recv, args, true, false);
}

public static RubyTime new_utc(IRubyObject recv, IRubyObject[] args) {
return createTime(recv.getRuntime().getCurrentContext(), (RubyClass) recv, args, true, false);
return ((RubyTime) ((RubyClass) recv).allocate()).initTime(context, args, true, false);
}

@JRubyMethod(name = "_load", meta = true)
Expand Down Expand Up @@ -1412,7 +1395,7 @@ protected static RubyTime s_mload(IRubyObject recv, RubyTime time, IRubyObject f

private static final int ARG_SIZE = 7;

private static RubyTime createTime(ThreadContext context, RubyClass klass, IRubyObject[] args, boolean gmt, boolean utcOffset) {
private RubyTime initTime(ThreadContext context, IRubyObject[] args, boolean gmt, boolean utcOffset) {
Ruby runtime = context.runtime;
int len = ARG_SIZE;
boolean isDst = false;
Expand Down Expand Up @@ -1548,17 +1531,16 @@ private static RubyTime createTime(ThreadContext context, RubyClass klass, IRuby
throw runtime.newArgumentError("time out of range");
}

RubyTime time = new RubyTime(runtime, klass, dt);
// Ignores usec if 8 args (for compatibility with parse-date) or if not supplied.
if (args.length != 8 && args[6] != context.nil) {
if (args[6] instanceof RubyRational) {
RubyRational nsec = (RubyRational) ((RubyRational) args[6]).op_mul(context, runtime.newFixnum(1000));
long tmpNanos = (long) nsec.getDoubleValue(context);
time.dt = dt.withMillis(dt.getMillis() + (tmpNanos / 1_000_000));
dt = dt.withMillis(dt.getMillis() + (tmpNanos / 1_000_000));
nanos = tmpNanos % 1_000_000;
} else if (args[6] instanceof RubyFloat) {
double micros = ((RubyFloat) args[6]).getDoubleValue();
time.dt = dt.withMillis(dt.getMillis() + (long) (micros / 1000));
dt = dt.withMillis(dt.getMillis() + (long) (micros / 1000));
nanos = (long) Math.rint((micros * 1000) % 1_000_000);
} else {
int usec = int_args[4] % 1000;
Expand All @@ -1568,19 +1550,36 @@ private static RubyTime createTime(ThreadContext context, RubyClass klass, IRuby
msec -= 1;
usec += 1000;
}
time.dt = dt.withMillis(dt.getMillis() + msec);
time.setUSec(usec);
dt = dt.withMillis(dt.getMillis() + msec);
this.setUSec(usec);
}
}

if (nanos != 0) time.setNSec(nanos);
this.dt = dt;

time.callInit(IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
time.setIsTzRelative(setTzRelative);
return time;
if (nanos != 0) this.setNSec(nanos);

this.setIsTzRelative(setTzRelative);

return this;
}

private static TimeSites sites(ThreadContext context) {
return context.sites.Time;
}

@Deprecated
public static RubyTime new_local(IRubyObject recv, IRubyObject[] args) {
return ((RubyTime) ((RubyClass) recv).allocate()).initTime(recv.getRuntime().getCurrentContext(), args, false, false);
}

@Deprecated
public static RubyTime new_utc(IRubyObject recv, IRubyObject[] args) {
return ((RubyTime) ((RubyClass) recv).allocate()).initTime(recv.getRuntime().getCurrentContext(), args, true, false);
}

@Deprecated
public static IRubyObject new19(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
return ((RubyClass) recv).allocate().callMethod(context, "initialize", args);
}
}

0 comments on commit fd83bda

Please sign in to comment.