0
***** END LICENSE BLOCK *****/
0
-import java.text.SimpleDateFormat;
0
-import java.util.Calendar;
0
-import java.util.GregorianCalendar;
0
import java.util.Locale;
0
import java.util.TimeZone;
0
import java.util.regex.Matcher;
0
@@ -56,16 +53,24 @@ import org.jruby.runtime.builtin.IRubyObject;
0
import org.jruby.util.RubyDateFormat;
0
import org.jruby.util.ByteList;
0
+import org.joda.time.DateTime;
0
+import org.joda.time.DateTimeZone;
0
+import org.joda.time.format.DateTimeFormat;
0
+import org.joda.time.format.DateTimeFormatter;
0
* @author chadfowler, jpetersen
0
public class RubyTime extends RubyObject {
0
public static final String UTC = "UTC";
0
+ private final static DateTimeFormatter ONE_DAY_CTIME_FORMATTER = DateTimeFormat.forPattern("EEE MMM d HH:mm:ss yyyy");
0
+ private final static DateTimeFormatter TWO_DAY_CTIME_FORMATTER = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss yyyy");
0
- private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("-", Locale.US);
0
+ private final static DateTimeFormatter TO_S_FORMATTER = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss Z yyyy");
0
+ private final static DateTimeFormatter TO_S_UTC_FORMATTER = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss 'UTC' yyyy");
0
// There are two different popular TZ formats: legacy (AST+3:00:00, GMT-3), and
0
// newer one (US/Pacific, America/Los_Angeles). This pattern is to detect
0
@@ -76,13 +81,13 @@ public class RubyTime extends RubyObject {
0
private static final ByteList TZ_STRING = ByteList.create("TZ");
0
- public static
TimeZone getLocalTimeZone(Ruby runtime) {
0
+ public static
DateTimeZone getLocalTimeZone(Ruby runtime) {
0
// TODO: cache the RubyString "TZ" so it doesn't need to be recreated for each call?
0
RubyString tzVar = runtime.newString(TZ_STRING);
0
RubyHash h = ((RubyHash)runtime.getObject().fastGetConstant("ENV"));
0
IRubyObject tz = h.op_aref(tzVar);
0
if (tz == null || ! (tz instanceof RubyString)) {
0
- return
TimeZone.getDefault();
0
+ return
DateTimeZone.getDefault();
0
String zone = tz.toString();
0
@@ -108,7 +113,9 @@ public class RubyTime extends RubyObject {
0
- return TimeZone.getTimeZone(zone);
0
+ zone = zone.replaceAll("GMT","Etc/GMT");
0
+ return DateTimeZone.forTimeZone(TimeZone.getTimeZone(zone));
0
@@ -116,17 +123,15 @@ public class RubyTime extends RubyObject {
0
super(runtime, rubyClass);
0
- public RubyTime(Ruby runtime, RubyClass rubyClass,
Calendar cal) {
0
+ public RubyTime(Ruby runtime, RubyClass rubyClass,
DateTime dt) {
0
super(runtime, rubyClass);
0
private static ObjectAllocator TIME_ALLOCATOR = new ObjectAllocator() {
0
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
0
- RubyTime instance = new RubyTime(runtime, klass);
0
- Calendar cal = Calendar.getInstance(getLocalTimeZone(runtime));
0
- instance.setJavaCalendar(cal);
0
+ DateTime dt = new DateTime(getLocalTimeZone(runtime));
0
+ return new RubyTime(runtime, klass, dt);
0
@@ -149,28 +154,20 @@ public class RubyTime extends RubyObject {
0
- public void updateCal(Calendar calendar) {
0
- calendar.setTimeZone(cal.getTimeZone());
0
- calendar.setTimeInMillis(getTimeInMillis());
0
+ public void updateCal(DateTime dt) {
0
protected long getTimeInMillis() {
0
- return
cal.getTimeInMillis(); // For JDK 1.4 we can use "cal.getTimeInMillis()"
0
+ return
dt.getMillis(); // For JDK 1.4 we can use "cal.getTimeInMillis()"
0
public static RubyTime newTime(Ruby runtime, long milliseconds) {
0
- Calendar cal = Calendar.getInstance();
0
- RubyTime time = new RubyTime(runtime, runtime.getTime(), cal);
0
- cal.setTimeInMillis(milliseconds);
0
+ return newTime(runtime, new DateTime(milliseconds));
0
- public static RubyTime newTime(Ruby runtime, Calendar cal) {
0
- RubyTime time = new RubyTime(runtime, runtime.getTime(), cal);
0
+ public static RubyTime newTime(Ruby runtime, DateTime dt) {
0
+ return new RubyTime(runtime, runtime.getTime(), dt);
0
@JRubyMethod(name = "initialize_copy", required = 1)
0
@@ -181,7 +178,8 @@ public class RubyTime extends RubyObject {
0
RubyTime originalTime = (RubyTime) original;
0
- cal = (Calendar)(originalTime.cal.clone());
0
+ // We can just use dt, since it is immutable
0
usec = originalTime.usec;
0
@@ -189,51 +187,42 @@ public class RubyTime extends RubyObject {
0
@JRubyMethod(name = "succ")
0
public RubyTime succ() {
0
- Calendar newCal = (Calendar)cal.clone();
0
- newCal.add(Calendar.SECOND,1);
0
- return newTime(getRuntime(),newCal);
0
+ return newTime(getRuntime(),dt.plusSeconds(1));
0
@JRubyMethod(name = {"gmtime", "utc"})
0
public RubyTime gmtime() {
0
-
cal.setTimeZone(TimeZone.getTimeZone(UTC));
0
+
dt = new DateTime(dt.getMillis()).withZone(DateTimeZone.UTC);
0
@JRubyMethod(name = "localtime")
0
public RubyTime localtime() {
0
- long dump = cal.getTimeInMillis();
0
- cal = Calendar.getInstance(getLocalTimeZone(getRuntime()));
0
- cal.setTimeInMillis(dump);
0
+ dt = dt.withZone(getLocalTimeZone(getRuntime()));
0
@JRubyMethod(name = {"gmt?", "utc?", "gmtime?"})
0
public RubyBoolean gmt() {
0
- return getRuntime().newBoolean(
cal.getTimeZone().getID().equals(UTC));
0
+ return getRuntime().newBoolean(
dt.getZone().getID().equals("UTC"));
0
@JRubyMethod(name = {"getgm", "getutc"})
0
public RubyTime getgm() {
0
- Calendar newCal = (Calendar)cal.clone();
0
- newCal.setTimeZone(TimeZone.getTimeZone(UTC));
0
- return newTime(getRuntime(), newCal);
0
+ return newTime(getRuntime(), dt.withZone(DateTimeZone.UTC));
0
@JRubyMethod(name = "getlocal")
0
public RubyTime getlocal() {
0
- Calendar newCal = (Calendar)cal.clone();
0
- newCal.setTimeZone(getLocalTimeZone(getRuntime()));
0
- return newTime(getRuntime(), newCal);
0
+ return newTime(getRuntime(), dt.withZone(getLocalTimeZone(getRuntime())));
0
@JRubyMethod(name = "strftime", required = 1)
0
public RubyString strftime(IRubyObject format) {
0
final RubyDateFormat rubyDateFormat = new RubyDateFormat("-", Locale.US);
0
- rubyDateFormat.setCalendar(cal);
0
rubyDateFormat.applyPattern(format.toString());
0
- String result = rubyDateFormat.format(cal.getTime());
0
+ rubyDateFormat.setDateTime(dt);
0
+ String result = rubyDateFormat.format(null);
0
return getRuntime().newString(result);
0
@@ -301,9 +290,7 @@ public class RubyTime extends RubyObject {
0
RubyTime newTime = new RubyTime(getRuntime(), getMetaClass());
0
- newTime.cal = Calendar.getInstance();
0
- newTime.cal.setTimeZone(cal.getTimeZone());
0
- newTime.cal.setTime(new Date(time));
0
+ newTime.dt = new DateTime(time).withZone(dt.getZone());
0
newTime.setUSec(micro);
0
@@ -325,9 +312,7 @@ public class RubyTime extends RubyObject {
0
RubyTime newTime = new RubyTime(getRuntime(), getMetaClass());
0
- newTime.cal = Calendar.getInstance();
0
- newTime.cal.setTimeZone(cal.getTimeZone());
0
- newTime.cal.setTime(new Date(time));
0
+ newTime.dt = new DateTime(time).withZone(dt.getZone());
0
newTime.setUSec(micro);
0
@@ -388,26 +373,27 @@ public class RubyTime extends RubyObject {
0
@JRubyMethod(name = {"asctime", "ctime"})
0
public RubyString asctime() {
0
- simpleDateFormat.setCalendar(cal);
0
- if (cal.get(Calendar.DAY_OF_MONTH) < 10) {
0
- simpleDateFormat.applyPattern("EEE MMM d HH:mm:ss yyyy");
0
+ DateTimeFormatter simpleDateFormat;
0
+ if (dt.getDayOfMonth() < 10) {
0
+ simpleDateFormat = ONE_DAY_CTIME_FORMATTER;
0
- simpleDateFormat
.applyPattern("EEE MMM dd HH:mm:ss yyyy");
0
+ simpleDateFormat
= TWO_DAY_CTIME_FORMATTER;
0
- String result = simpleDateFormat.format(cal.getTime());
0
+ String result = simpleDateFormat.print(dt);
0
return getRuntime().newString(result);
0
@JRubyMethod(name = {"to_s", "inspect"})
0
public IRubyObject to_s() {
0
- simpleDateFormat.setCalendar(cal);
0
- if (cal.getTimeZone().getID().equals(UTC)) {
0
- simpleDateFormat.applyPattern("EEE MMM dd HH:mm:ss 'UTC' yyyy");
0
+ DateTimeFormatter simpleDateFormat;
0
+ if (dt.getZone().equals(DateTimeZone.UTC)) {
0
+ simpleDateFormat = TO_S_UTC_FORMATTER;
0
- simpleDateFormat
.applyPattern("EEE MMM dd HH:mm:ss Z yyyy");
0
+ simpleDateFormat
= TO_S_FORMATTER;
0
- String result = simpleDateFormat.format(cal.getTime());
0
+ String result = simpleDateFormat.print(dt);
0
return getRuntime().newString(result);
0
@@ -432,14 +418,14 @@ public class RubyTime extends RubyObject {
0
@JRubyMethod(name = {"usec", "tv_usec"})
0
public RubyInteger usec() {
0
- return getRuntime().newFixnum(
cal.get(Calendar.MILLISECOND) * 1000 + getUSec());
0
+ return getRuntime().newFixnum(
dt.getMillisOfSecond() * 1000 + getUSec());
0
public void setMicroseconds(long mic) {
0
long millis = getTimeInMillis() % 1000;
0
long withoutMillis = getTimeInMillis() - millis;
0
withoutMillis += (mic / 1000);
0
-
cal.setTimeInMillis(withoutMillis);
0
+
dt = dt.withMillis(withoutMillis);
0
@@ -449,81 +435,81 @@ public class RubyTime extends RubyObject {
0
@JRubyMethod(name = "sec")
0
public RubyInteger sec() {
0
- return getRuntime().newFixnum(
cal.get(Calendar.SECOND));
0
+ return getRuntime().newFixnum(
dt.getSecondOfMinute());
0
@JRubyMethod(name = "min")
0
public RubyInteger min() {
0
- return getRuntime().newFixnum(
cal.get(Calendar.MINUTE));
0
+ return getRuntime().newFixnum(
dt.getMinuteOfHour());
0
@JRubyMethod(name = "hour")
0
public RubyInteger hour() {
0
- return getRuntime().newFixnum(
cal.get(Calendar.HOUR_OF_DAY));
0
+ return getRuntime().newFixnum(
dt.getHourOfDay());
0
@JRubyMethod(name = {"mday", "day"})
0
public RubyInteger mday() {
0
- return getRuntime().newFixnum(
cal.get(Calendar.DAY_OF_MONTH));
0
+ return getRuntime().newFixnum(
dt.getDayOfMonth());
0
@JRubyMethod(name = {"month", "mon"})
0
public RubyInteger month() {
0
- return getRuntime().newFixnum(
cal.get(Calendar.MONTH) + 1);
0
+ return getRuntime().newFixnum(
dt.getMonthOfYear());
0
@JRubyMethod(name = "year")
0
public RubyInteger year() {
0
- return getRuntime().newFixnum(
cal.get(Calendar.YEAR));
0
+ return getRuntime().newFixnum(
dt.getYear());
0
@JRubyMethod(name = "wday")
0
public RubyInteger wday() {
0
- return getRuntime().newFixnum(
cal.get(Calendar.DAY_OF_WEEK) - 1);
0
+ return getRuntime().newFixnum(
(dt.getDayOfWeek()%7));
0
@JRubyMethod(name = "yday")
0
public RubyInteger yday() {
0
- return getRuntime().newFixnum(
cal.get(Calendar.DAY_OF_YEAR));
0
+ return getRuntime().newFixnum(
dt.getDayOfYear());
0
@JRubyMethod(name = {"gmt_offset", "gmtoff", "utc_offset"})
0
public RubyInteger gmt_offset() {
0
- int offset = cal.get(Calendar.ZONE_OFFSET);
0
- if (isdst().isTrue()) {
0
- offset += cal.get(Calendar.DST_OFFSET);
0
+ int offset = dt.getZone().getOffsetFromLocal(dt.getMillis());
0
return getRuntime().newFixnum((int)(offset/1000));
0
@JRubyMethod(name = {"isdst", "dst?"})
0
public RubyBoolean isdst() {
0
- return getRuntime().newBoolean(
cal.getTimeZone().inDaylightTime(cal.getTime()));
0
+ return getRuntime().newBoolean(
!dt.getZone().isStandardOffset(dt.getMillis()));
0
@JRubyMethod(name = "zone")
0
public RubyString zone() {
0
- return getRuntime().newString(cal.getTimeZone().getDisplayName(cal.get(Calendar.DST_OFFSET) != 0, TimeZone.SHORT));
0
+ String zone = dt.getZone().getShortName(dt.getMillis());
0
+ if(zone.equals("+00:00")) {
0
+ return getRuntime().newString(zone);
0
- public void setJavaCalendar(Calendar cal) {
0
+ public void setDateTime(DateTime dt) {
0
- public Calendar getJavaCalendar() {
0
+ public DateTime getDateTime() {
0
public Date getJavaDate() {
0
- return this.
cal.getTime();
0
+ return this.
dt.toDate();
0
@JRubyMethod(name = "hash")
0
public RubyFixnum hash() {
0
// modified to match how hash is calculated in 1.8.2
0
- return getRuntime().newFixnum((int)(((
cal.getTimeInMillis() / 1000) ^ microseconds()) << 1) >> 1);
0
+ return getRuntime().newFixnum((int)(((
dt.getMillis() / 1000) ^ microseconds()) << 1) >> 1);
0
@JRubyMethod(name = "_dump", optional = 1, frame = true)
0
@@ -535,18 +521,18 @@ public class RubyTime extends RubyObject {
0
public RubyObject mdump(final IRubyObject[] args) {
0
RubyTime obj = (RubyTime)args[0];
0
-
Calendar calendar = obj.gmtime().cal;
0
+
DateTime dt = obj.gmtime().dt;
0
byte dumpValue[] = new byte[8];
0
- (calendar.get(Calendar.YEAR)-1900) << 14 |
0
- calendar.get(Calendar.MONTH) << 10 |
0
- calendar.get(Calendar.DAY_OF_MONTH) << 5 |
0
- calendar.get(Calendar.HOUR_OF_DAY);
0
+ (dt.getYear()-1900) << 14 |
0
+ dt.getMonthOfYear() << 10 |
0
+ dt.getDayOfMonth() << 5 |
0
- calendar.get(Calendar.MINUTE) << 26 |
0
- calendar.get(Calendar.SECOND) << 20 |
0
- calendar.get(Calendar.MILLISECOND);
0
+ dt.getMinuteOfHour() << 26 |
0
+ dt.getSecondOfMinute() << 20 |
0
+ dt.getMillisOfSecond();
0
for(int i = 0; i < 4; i++) {
0
dumpValue[i] = (byte)(pe & 0xFF);
0
@@ -568,10 +554,7 @@ public class RubyTime extends RubyObject {
0
public static IRubyObject s_new(IRubyObject recv, IRubyObject[] args, Block block) {
0
Ruby runtime = recv.getRuntime();
0
- RubyTime time = new RubyTime(runtime, (RubyClass) recv);
0
- GregorianCalendar cal = new GregorianCalendar();
0
- cal.setTime(new Date());
0
- time.setJavaCalendar(cal);
0
+ RubyTime time = new RubyTime(runtime, (RubyClass) recv, new DateTime());
0
time.callInit(args,block);
0
@@ -587,12 +570,11 @@ public class RubyTime extends RubyObject {
0
public static IRubyObject at(IRubyObject recv, IRubyObject[] args) {
0
Ruby runtime = recv.getRuntime();
0
- Calendar cal = Calendar.getInstance(getLocalTimeZone(runtime));
0
- RubyTime time = new RubyTime(runtime, (RubyClass) recv, cal);
0
+ RubyTime time = new RubyTime(runtime, (RubyClass) recv, new DateTime(getLocalTimeZone(runtime)));
0
if (args[0] instanceof RubyTime) {
0
RubyTime other = (RubyTime) args[0];
0
time.setUSec(other.getUSec());
0
long seconds = RubyNumeric.num2long(args[0]);
0
@@ -616,7 +598,7 @@ public class RubyTime extends RubyObject {
0
time.setUSec(microsecs);
0
-
cal.setTimeInMillis(seconds * 1000 + millisecs);
0
+
time.dt = time.dt.withMillis(seconds * 1000 + millisecs);
0
time.callInit(IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
0
@@ -641,9 +623,9 @@ public class RubyTime extends RubyObject {
0
protected static RubyTime s_mload(IRubyObject recv, RubyTime time, IRubyObject from) {
0
Ruby runtime = recv.getRuntime();
0
- Calendar calendar = Calendar.getInstance();
0
- calendar.setTimeZone(TimeZone.getTimeZone(RubyTime.UTC));
0
+ DateTime dt = new DateTime(DateTimeZone.UTC);
0
byte[] fromAsBytes = null;
0
fromAsBytes = from.convertToString().getBytes();
0
if(fromAsBytes.length != 8) {
0
@@ -658,18 +640,18 @@ public class RubyTime extends RubyObject {
0
s |= ((int)fromAsBytes[i] & 0xFF) << (8 * (i - 4));
0
if ((p & (1<<31)) == 0) {
0
-
calendar.setTimeInMillis(p * 1000L + s);
0
+
dt = dt.withMillis(p * 1000L + s);
0
- calendar.set(Calendar.YEAR, ((p >>> 14) & 0xFFFF) + 1900);
0
- calendar.set(Calendar.MONTH, ((p >>> 10) & 0xF));
0
- calendar.set(Calendar.DAY_OF_MONTH, ((p >>> 5) & 0x1F));
0
- calendar.set(Calendar.HOUR_OF_DAY, (p & 0x1F));
0
- calendar.set(Calendar.MINUTE, ((s >>> 26) & 0x3F));
0
- calendar.set(Calendar.SECOND, ((s >>> 20) & 0x3F));
0
- calendar.set(Calendar.MILLISECOND, (s & 0xFFFFF));
0
+ dt = dt.withYear(((p >>> 14) & 0xFFFF) + 1900);
0
+ dt = dt.withMonthOfYear(((p >>> 10) & 0xF));
0
+ dt = dt.withDayOfMonth(((p >>> 5) & 0x1F));
0
+ dt = dt.withHourOfDay((p & 0x1F));
0
+ dt = dt.withMinuteOfHour(((s >>> 26) & 0x3F));
0
+ dt = dt.withSecondOfMinute(((s >>> 20) & 0x3F));
0
+ dt = dt.withMillisOfSecond((s & 0xFFFFF));
0
- time.set
JavaCalendar(calendar);
0
@@ -706,7 +688,7 @@ public class RubyTime extends RubyObject {
0
int year = (int) RubyNumeric.num2long(args[0]);
0
if (!args[1].isNil()) {
0
@@ -714,22 +696,22 @@ public class RubyTime extends RubyObject {
0
for (int i = 0; i < 12; i++) {
0
if (months[i].equalsIgnoreCase(args[1].toString())) {
0
- month = Integer.parseInt(args[1].toString())
- 1;
0
+ month = Integer.parseInt(args[1].toString())
;
0
} catch (NumberFormatException nfExcptn) {
0
throw runtime.newArgumentError("Argument out of range.");
0
- month = (int)RubyNumeric.num2long(args[1])
- 1;
0
+ month = (int)RubyNumeric.num2long(args[1])
;
0
- if (0 > month || month > 11) {
0
- throw runtime.newArgumentError("Argument out of range.");
0
+ if (1 > month || month > 12) {
0
+ throw runtime.newArgumentError("Argument out of range: for month: " + month);
0
@@ -754,30 +736,35 @@ public class RubyTime extends RubyObject {
0
+
DateTime dt = new DateTime();
0
-
cal = Calendar.getInstance(TimeZone.getTimeZone(RubyTime.UTC)); 0
+
dt = dt.withZone(DateTimeZone.UTC);0
-
cal = Calendar.getInstance(RubyTime.getLocalTimeZone(runtime));
0
+
dt = dt.withZone(getLocalTimeZone(runtime));
0
- cal.set(year, month, int_args[0], int_args[1], int_args[2], int_args[3]);
0
- cal.set(Calendar.MILLISECOND, 0);
0
- RubyTime time = new RubyTime(runtime, (RubyClass) recv, cal);
0
+ dt = dt.withDate(year, month, int_args[0])
0
+ .withHourOfDay(int_args[1])
0
+ .withMinuteOfHour(int_args[2])
0
+ .withSecondOfMinute(int_args[3])
0
+ .withMillisOfSecond(0);
0
+ RubyTime time = new RubyTime(runtime, (RubyClass) recv, dt);
0
// Ignores usec if 8 args (for compatibility with parsedate) or if not supplied.
0
if (args.length != 8 && !args[6].isNil()) {
0
int usec = int_args[4] % 1000;
0
int msec = int_args[4] / 1000;
0
-
cal.add(Calendar.MILLISECOND, msec);
0
+
time.dt = dt.withMillis(dt.getMillis()+msec);
0
// Restrict to time_t for compatibility
0
- long seconds =
cal.getTimeInMillis() / 1000;
0
+ long seconds =
dt.getMillis() / 1000;
0
if (seconds > Integer.MAX_VALUE || seconds < Integer.MIN_VALUE) {
0
throw runtime.newArgumentError("time out of range");