private static RubyTime createTime(IRubyObject recv, IRubyObject[] args, boolean gmt) { Ruby runtime = recv.getRuntime(); int len = ARG_SIZE; Boolean isDst = null; DateTimeZone dtz; if (gmt) { dtz = DateTimeZone.UTC; } else if (args.length == 10 && args[9] instanceof RubyString) { dtz = getTimeZone(runtime, ((RubyString) args[9]).toString()); } else { dtz = getLocalTimeZone(runtime); } if (args.length == 10) { if (args[8] instanceof RubyBoolean) { isDst = ((RubyBoolean) args[8]).isTrue(); } args = new IRubyObject[] { args[5], args[4], args[3], args[2], args[1], args[0], runtime.getNil() }; } else { // MRI accepts additional wday argument which appears to be ignored. len = args.length; if (len < ARG_SIZE) { IRubyObject[] newArgs = new IRubyObject[ARG_SIZE]; System.arraycopy(args, 0, newArgs, 0, args.length); for (int i = len; i < ARG_SIZE; i++) { newArgs[i] = runtime.getNil(); } args = newArgs; len = ARG_SIZE; } } if (args[0] instanceof RubyString) { args[0] = RubyNumeric.str2inum(runtime, (RubyString) args[0], 10, false); } int year = (int) RubyNumeric.num2long(args[0]); int month = 1; if (len > 1) { if (!args[1].isNil()) { IRubyObject tmp = args[1].checkStringType(); if (!tmp.isNil()) { String monthString = tmp.toString().toLowerCase(); Integer monthInt = MONTHS_MAP.get(monthString); if (monthInt != null) { month = monthInt; } else { try { month = Integer.parseInt(monthString); } catch (NumberFormatException nfExcptn) { throw runtime.newArgumentError("Argument out of range."); } } } else { month = (int) RubyNumeric.num2long(args[1]); } } if (1 > month || month > 12) { throw runtime.newArgumentError("Argument out of range: for month: " + month); } } int[] int_args = {1, 0, 0, 0, 0, 0}; for (int i = 0; int_args.length >= i + 2; i++) { if (!args[i + 2].isNil()) { if (!(args[i + 2] instanceof RubyNumeric)) { args[i + 2] = args[i + 2].callMethod(runtime.getCurrentContext(), "to_i"); } long value = RubyNumeric.num2long(args[i + 2]); if (time_min[i] > value || value > time_max[i]) { throw runtime.newArgumentError("argument out of range."); } int_args[i] = (int) value; } } if (!runtime.is1_9()) { if (0 <= year && year < 39) { year += 2000; } else if (69 <= year && year < 139) { year += 1900; } } DateTime dt; // set up with min values and then add to allow rolling over try { dt = new DateTime(year, 1, 1, 0, 0, 0, 0, DateTimeZone.UTC); dt = dt.plusMonths(month - 1) .plusDays(int_args[0] - 1) .plusHours(int_args[1]) .plusMinutes(int_args[2]) .plusSeconds(int_args[3]); if (runtime.is1_9() && !args[5].isNil()) { double millis = RubyFloat.num2dbl(args[5]); int int_millis = (int) (millis * 1000) % 1000; dt = dt.plusMillis(int_millis); } dt = dt.withZoneRetainFields(dtz); // we might need to perform a DST correction if (isDst != null) { // the instant at which we will ask dtz what the difference between DST and // standard time is long offsetCalculationInstant = dt.getMillis(); // if we might be moving this time from !DST -> DST, the offset is assumed // to be the same as it was just before we last moved from DST -> !DST if (dtz.isStandardOffset(dt.getMillis())) { offsetCalculationInstant = dtz.previousTransition(offsetCalculationInstant); } int offset = dtz.getStandardOffset(offsetCalculationInstant) - dtz.getOffset(offsetCalculationInstant); if (!isDst && !dtz.isStandardOffset(dt.getMillis())) { dt = dt.minusMillis(offset); } if (isDst && dtz.isStandardOffset(dt.getMillis())) { dt = dt.plusMillis(offset); } } } catch (org.joda.time.IllegalFieldValueException e) { throw runtime.newArgumentError("time out of range"); } RubyTime time = new RubyTime(runtime, (RubyClass) recv, dt); // Ignores usec if 8 args (for compatibility with parsedate) or if not supplied. if (args.length != 8 && !args[6].isNil()) { int usec = int_args[4] % 1000; int msec = int_args[4] / 1000; if (int_args[4] < 0) { msec -= 1; usec += 1000; } time.dt = dt.withMillis(dt.getMillis() + msec); time.setUSec(usec); } time.callInit(IRubyObject.NULL_ARRAY, Block.NULL_BLOCK); return time; }
@SuppressWarnings("fallthrough") @JRubyMethod(name = "read", optional = 2) @Override public IRubyObject read(IRubyObject[] args) { checkReadable(); ByteList buf = null; int length = 0; int oldLength = 0; RubyString originalString = null; switch (args.length) { case 2: originalString = args[1].convertToString(); // must let original string know we're modifying, so shared buffers aren't damaged originalString.modify(); buf = originalString.getByteList(); case 1: if (!args[0].isNil()) { length = RubyNumeric.fix2int(args[0]); oldLength = length; if (length < 0) { throw getRuntime().newArgumentError("negative length " + length + " given"); } if (length > 0 && isEndOfString()) { data.eof = true; if (buf != null) buf.setRealSize(0); return getRuntime().getNil(); } else if (data.eof) { if (buf != null) buf.setRealSize(0); return getRuntime().getNil(); } break; } case 0: oldLength = -1; length = data.internal.getByteList().length(); if (length <= data.pos) { data.eof = true; if (buf == null) { buf = new ByteList(); } else { buf.setRealSize(0); } return makeString(getRuntime(), buf); } else { length -= data.pos; } break; default: getRuntime().newArgumentError(args.length, 0); } if (buf == null) { int internalLength = data.internal.getByteList().length(); if (internalLength > 0) { if (internalLength >= data.pos + length) { buf = new ByteList(data.internal.getByteList(), (int) data.pos, length); } else { int rest = (int) (data.internal.getByteList().length() - data.pos); if (length > rest) length = rest; buf = new ByteList(data.internal.getByteList(), (int) data.pos, length); } } } else { int rest = (int) (data.internal.getByteList().length() - data.pos); if (length > rest) length = rest; // Yow...this is still ugly byte[] target = buf.getUnsafeBytes(); if (target.length > length) { System.arraycopy( data.internal.getByteList().getUnsafeBytes(), (int) data.pos, target, 0, length); buf.setBegin(0); buf.setRealSize(length); } else { target = new byte[length]; System.arraycopy( data.internal.getByteList().getUnsafeBytes(), (int) data.pos, target, 0, length); buf.setBegin(0); buf.setRealSize(length); buf.setUnsafeBytes(target); } } if (buf == null) { if (!data.eof) buf = new ByteList(); length = 0; } else { length = buf.length(); data.pos += length; } if (oldLength < 0 || oldLength > length) data.eof = true; return originalString != null ? originalString : makeString(getRuntime(), buf); }