blob: 918b5d25446c128cf93c873d9b8b2bdf14a06731 [file] [log] [blame]
/*
* Copyright 2007 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package java.util;
import com.google.gwt.core.client.JavaScriptObject;
import java.io.Serializable;
/**
* Represents a date and time.
*/
public class Date implements Cloneable, Comparable<Date>, Serializable {
/**
* Used only by toString().
*/
private static final String[] DAYS = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
/**
* Used only by toString().
*/
private static final String[] MONTHS = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
public static long parse(String s) {
long d = (long) parse0(s);
if (d != -1) {
return d;
} else {
throw new IllegalArgumentException();
}
}
// CHECKSTYLE_OFF: Matching the spec.
public static long UTC(int year, int month, int date, int hrs,
int min, int sec) {
return (long) utc0(year, month, date, hrs, min, sec);
}
// CHECKSTYLE_ON
/**
* Ensure a number is displayed with two digits.
*
* @return a two-character base 10 representation of the number
*/
protected static String padTwo(int number) {
if (number < 10) {
return "0" + number;
} else {
return String.valueOf(number);
}
}
/**
* Return the names for the days of the week as specified by the Date
* specification.
*/
@SuppressWarnings("unused") // called by JSNI
private static String dayToString(int day) {
return DAYS[day];
}
/**
* Return the names for the months of the year as specified by the Date
* specification.
*/
@SuppressWarnings("unused") // called by JSNI
private static String monthToString(int month) {
return MONTHS[month];
}
private static native double parse0(String s) /*-{
var d = Date.parse(s);
return isNaN(d) ? -1 : d;
}-*/;
/**
* Throw an exception if jsdate is not an object.
*
* @param val
*/
@SuppressWarnings("unused") // called by JSNI
private static void throwJsDateException(String val) {
throw new IllegalStateException("jsdate is " + val);
}
private static native double utc0(int year, int month, int date, int hrs,
int min, int sec) /*-{
return Date.UTC(year + 1900, month, date, hrs, min, sec);
}-*/;
/**
* JavaScript Date instance.
*/
@SuppressWarnings("unused") // used from JSNI
private JavaScriptObject jsdate;
public Date() {
init();
}
public Date(int year, int month, int date) {
init(year, month, date, 0, 0, 0);
}
public Date(int year, int month, int date, int hrs, int min) {
init(year, month, date, hrs, min, 0);
}
public Date(int year, int month, int date, int hrs, int min, int sec) {
init(year, month, date, hrs, min, sec);
}
public Date(long date) {
init(date);
}
public Date(String date) {
init(Date.parse(date));
}
public boolean after(Date when) {
return getTime() > when.getTime();
}
public boolean before(Date when) {
return getTime() < when.getTime();
}
public Object clone() {
return new Date(getTime());
}
public int compareTo(Date other) {
long thisTime = getTime();
long otherTime = other.getTime();
if (thisTime < otherTime) {
return -1;
} else if (thisTime > otherTime) {
return 1;
} else {
return 0;
}
}
@Override
public boolean equals(Object obj) {
return ((obj instanceof Date) && (getTime() == ((Date) obj).getTime()));
}
public native int getDate() /*-{
this.@java.util.Date::checkJsDate()();
return this.@java.util.Date::jsdate.getDate();
}-*/;
public native int getDay() /*-{
this.@java.util.Date::checkJsDate()();
return this.@java.util.Date::jsdate.getDay();
}-*/;
public native int getHours() /*-{
this.@java.util.Date::checkJsDate()();
return this.@java.util.Date::jsdate.getHours();
}-*/;
public native int getMinutes() /*-{
this.@java.util.Date::checkJsDate()();
return this.@java.util.Date::jsdate.getMinutes();
}-*/;
public native int getMonth() /*-{
this.@java.util.Date::checkJsDate()();
return this.@java.util.Date::jsdate.getMonth();
}-*/;
public native int getSeconds() /*-{
this.@java.util.Date::checkJsDate()();
return this.@java.util.Date::jsdate.getSeconds();
}-*/;
public long getTime() {
return (long) getTime0();
}
public native int getTimezoneOffset() /*-{
this.@java.util.Date::checkJsDate()();
return this.@java.util.Date::jsdate.getTimezoneOffset();
}-*/;
public native int getYear() /*-{
this.@java.util.Date::checkJsDate()();
return this.@java.util.Date::jsdate.getFullYear() - 1900;
}-*/;
@Override
public int hashCode() {
return (int) (this.getTime() ^ (this.getTime() >>> 32));
}
public native void setDate(int date) /*-{
this.@java.util.Date::checkJsDate()();
var hours = this.@java.util.Date::jsdate.getHours()
this.@java.util.Date::jsdate.setDate(date);
this.@java.util.Date::fixDaylightSavings(I)(hours);
}-*/;
public native void setHours(int hours) /*-{
this.@java.util.Date::checkJsDate()();
this.@java.util.Date::jsdate.setHours(hours);
this.@java.util.Date::fixDaylightSavings(I)(hours);
}-*/;
public native void setMinutes(int minutes) /*-{
this.@java.util.Date::checkJsDate()();
var hours = this.@java.util.Date::jsdate.getHours() + minutes / 60;
this.@java.util.Date::jsdate.setMinutes(minutes);
this.@java.util.Date::fixDaylightSavings(I)(hours);
}-*/;
public native void setMonth(int month) /*-{
this.@java.util.Date::checkJsDate()();
var hours = this.@java.util.Date::jsdate.getHours();
this.@java.util.Date::jsdate.setMonth(month);
this.@java.util.Date::fixDaylightSavings(I)(hours);
}-*/;
public native void setSeconds(int seconds) /*-{
this.@java.util.Date::checkJsDate()();
var hours = this.@java.util.Date::jsdate.getHours() + seconds / (60 * 60);
this.@java.util.Date::jsdate.setSeconds(seconds);
this.@java.util.Date::fixDaylightSavings(I)(hours);
}-*/;
public void setTime(long time) {
setTime0(time);
}
public native void setYear(int year) /*-{
this.@java.util.Date::checkJsDate()();
var hours = this.@java.util.Date::jsdate.getHours()
this.@java.util.Date::jsdate.setFullYear(year + 1900);
this.@java.util.Date::fixDaylightSavings(I)(hours);
}-*/;
public native String toGMTString() /*-{
this.@java.util.Date::checkJsDate()();
var d = this.@java.util.Date::jsdate;
var padTwo = @java.util.Date::padTwo(I);
var month =
@java.util.Date::monthToString(I)(this.@java.util.Date::jsdate.getUTCMonth());
return d.getUTCDate() + " " +
month + " " +
d.getUTCFullYear() + " " +
padTwo(d.getUTCHours()) + ":" +
padTwo(d.getUTCMinutes()) + ":" +
padTwo(d.getUTCSeconds()) +
" GMT";
}-*/;
public native String toLocaleString() /*-{
this.@java.util.Date::checkJsDate()();
return this.@java.util.Date::jsdate.toLocaleString();
}-*/;
@Override
public native String toString() /*-{
this.@java.util.Date::checkJsDate()();
var d = this.@java.util.Date::jsdate;
var padTwo = @java.util.Date::padTwo(I);
var day =
@java.util.Date::dayToString(I)(d.getDay());
var month =
@java.util.Date::monthToString(I)(d.getMonth());
// Compute timezone offset. The value that getTimezoneOffset returns is
// backwards for the transformation that we want.
var offset = -d.getTimezoneOffset();
var hourOffset = String((offset >= 0) ?
"+" + Math.floor(offset / 60) : Math.ceil(offset / 60));
var minuteOffset = padTwo(Math.abs(offset) % 60);
return day + " " + month + " " +
padTwo(d.getDate()) + " " +
padTwo(d.getHours()) + ":" +
padTwo(d.getMinutes()) + ":" +
padTwo(d.getSeconds()) +
" GMT" + hourOffset + minuteOffset +
+ " " + d.getFullYear();
}-*/;
/**
* Check that jsdate is valid and throw an exception if not.
*/
@SuppressWarnings("unused") // called by JSNI
private native void checkJsDate() /*-{
if (!this.@java.util.Date::jsdate
|| typeof this.@java.util.Date::jsdate != "object") {
@java.util.Date::throwJsDateException(Ljava/lang/String;)(""
+ this.@java.util.Date::jsdate);
}
}-*/;
/*
* Some browsers have the following behavior:
*
* // Assume a U.S. time zone with daylight savings
* // Set a non-existent time: 2:00 am Sunday March 8, 2009
* var date = new Date(2009, 2, 8, 2, 0, 0);
* var hours = date.getHours(); // returns 1
*
* The equivalent Java code will return 3. To compensate, we determine the
* amount of daylight savings adjustment by comparing the time zone offsets
* for the requested time and a time one day later, and add the adjustment to
* the hours and minutes of the requested time.
*/
/**
* Detects if the requested time falls into a non-existent time range due to
* local time advancing into daylight savings time. If so, push the requested
* time forward out of the non-existent range.
*/
@SuppressWarnings("unused") // called by JSNI
private native void fixDaylightSavings(int hours) /*-{
if ((this.@java.util.Date::jsdate.getHours() % 24) != (hours % 24)) {
// Find the change in time zone offset between the current
// time and the same time the following day
var d = new Date();
d.setTime(this.@java.util.Date::jsdate.getTime());
var noff = d.getTimezoneOffset();
d.setDate(d.getDate() + 1);
var loff = d.getTimezoneOffset();
var timeDiff = noff - loff;
// If the time zone offset is changing, advance the hours and
// minutes from the initially requested time by the change amount
if (timeDiff > 0) {
var year = this.@java.util.Date::jsdate.getYear() + 1900;
var month = this.@java.util.Date::jsdate.getMonth();
var day = this.@java.util.Date::jsdate.getDate();
var badHours = this.@java.util.Date::jsdate.getHours();
var minute = this.@java.util.Date::jsdate.getMinutes();
var second = this.@java.util.Date::jsdate.getSeconds();
if (badHours + timeDiff / 60 >= 24) {
day++;
}
var newTime = new Date(year, month, day,
hours + timeDiff / 60,
minute + timeDiff % 60, second);
this.@java.util.Date::jsdate.setTime(newTime.getTime());
}
}
}-*/;
private native double getTime0() /*-{
this.@java.util.Date::checkJsDate()();
return this.@java.util.Date::jsdate.getTime();
}-*/;
private native void init() /*-{
this.@java.util.Date::jsdate = new Date();
}-*/;
private native void init(double date) /*-{
this.@java.util.Date::jsdate = new Date(date);
}-*/;
private native void init(int year, int month, int date, int hrs, int min,
int sec) /*-{
this.@java.util.Date::jsdate = new Date();
this.@java.util.Date::checkJsDate()();
this.@java.util.Date::jsdate.setFullYear(year + 1900, month, date);
this.@java.util.Date::jsdate.setHours(hrs, min, sec, 0);
// Set the expected hour.
this.@java.util.Date::fixDaylightSavings(I)(hrs);
}-*/;
private native void setTime0(double time) /*-{
this.@java.util.Date::checkJsDate()();
this.@java.util.Date::jsdate.setTime(time);
}-*/;
}