java.util.Date.java Source code

Java tutorial

Introduction

Here is the source code for java.util.Date.java

Source

/*
 * 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.JsDate;

import java.io.Serializable;

/**
 * Represents a date and time.
 */
public class Date implements Cloneable, Comparable<Date>, Serializable {

    /**
     * Encapsulates static data to avoid Date itself having a static initializer.
     */
    private static class StringData {
        public static final String[] DAYS = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

        public static final String[] MONTHS = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
                "Oct", "Nov", "Dec" };
    }

    public static long parse(String s) {
        double parsed = JsDate.parse(s);
        if (Double.isNaN(parsed)) {
            throw new IllegalArgumentException();
        }
        return (long) parsed;
    }

    // CHECKSTYLE_OFF: Matching the spec.
    public static long UTC(int year, int month, int date, int hrs, int min, int sec) {
        return (long) JsDate.UTC(year + 1900, month, date, hrs, min, sec, 0);
    }

    // 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);
        }
    }

    /**
     * Package private factory for JSNI use, to allow cheap creation of dates from
     * doubles.
     */
    static Date createFrom(double milliseconds) {
        return new Date(milliseconds, false);
    }

    /**
     * JavaScript Date instance.
     */
    private final JsDate jsdate;

    public Date() {
        jsdate = JsDate.create();
    }

    public Date(int year, int month, int date) {
        this(year, month, date, 0, 0, 0);
    }

    public Date(int year, int month, int date, int hrs, int min) {
        this(year, month, date, hrs, min, 0);
    }

    public Date(int year, int month, int date, int hrs, int min, int sec) {
        jsdate = JsDate.create();
        jsdate.setFullYear(year + 1900, month, date);
        jsdate.setHours(hrs, min, sec, 0);
        fixDaylightSavings(hrs);
    }

    public Date(long date) {
        jsdate = JsDate.create(date);
    }

    public Date(String date) {
        this(Date.parse(date));
    }

    /**
     * For use by {@link #createFrom(double)}, should inline away.
     */
    Date(double milliseconds, boolean dummyArgForOverloadResolution) {
        jsdate = JsDate.create(milliseconds);
    }

    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) {
        return Long.signum(getTime() - other.getTime());
    }

    @Override
    public boolean equals(Object obj) {
        return ((obj instanceof Date) && (getTime() == ((Date) obj).getTime()));
    }

    public int getDate() {
        return jsdate.getDate();
    }

    public int getDay() {
        return jsdate.getDay();
    }

    public int getHours() {
        return jsdate.getHours();
    }

    public int getMinutes() {
        return jsdate.getMinutes();
    }

    public int getMonth() {
        return jsdate.getMonth();
    }

    public int getSeconds() {
        return jsdate.getSeconds();
    }

    public long getTime() {
        return (long) jsdate.getTime();
    }

    public int getTimezoneOffset() {
        return jsdate.getTimezoneOffset();
    }

    public int getYear() {
        return jsdate.getFullYear() - 1900;
    }

    @Override
    public int hashCode() {
        long time = getTime();
        return (int) (time ^ (time >>> 32));
    }

    public void setDate(int date) {
        int hours = jsdate.getHours();
        jsdate.setDate(date);
        fixDaylightSavings(hours);
    }

    public void setHours(int hours) {
        jsdate.setHours(hours);
        fixDaylightSavings(hours);
    }

    public void setMinutes(int minutes) {
        int hours = getHours() + minutes / 60;
        jsdate.setMinutes(minutes);
        fixDaylightSavings(hours);
    }

    public void setMonth(int month) {
        int hours = jsdate.getHours();
        jsdate.setMonth(month);
        fixDaylightSavings(hours);
    }

    public void setSeconds(int seconds) {
        int hours = getHours() + seconds / (60 * 60);
        jsdate.setSeconds(seconds);
        fixDaylightSavings(hours);
    }

    public void setTime(long time) {
        jsdate.setTime(time);
    }

    public void setYear(int year) {
        int hours = jsdate.getHours();
        jsdate.setFullYear(year + 1900);
        fixDaylightSavings(hours);
    }

    public String toGMTString() {
        return jsdate.getUTCDate() + " " + StringData.MONTHS[jsdate.getUTCMonth()] + " " + jsdate.getUTCFullYear()
                + " " + padTwo(jsdate.getUTCHours()) + ":" + padTwo(jsdate.getUTCMinutes()) + ":"
                + padTwo(jsdate.getUTCSeconds()) + " GMT";
    }

    public String toLocaleString() {
        return jsdate.toLocaleString();
    }

    @Override
    public String toString() {
        // Compute timezone offset. The value that getTimezoneOffset returns is
        // backwards for the transformation that we want.
        int offset = -jsdate.getTimezoneOffset();
        String hourOffset = ((offset >= 0) ? "+" : "") + (offset / 60);
        String minuteOffset = padTwo(Math.abs(offset) % 60);

        return StringData.DAYS[jsdate.getDay()] + " " + StringData.MONTHS[jsdate.getMonth()] + " "
                + padTwo(jsdate.getDate()) + " " + padTwo(jsdate.getHours()) + ":" + padTwo(jsdate.getMinutes())
                + ":" + padTwo(jsdate.getSeconds()) + " GMT" + hourOffset + minuteOffset + " "
                + jsdate.getFullYear();
    }

    /*
     * 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.
     */
    private void fixDaylightSavings(int hours) {
        if ((jsdate.getHours() % 24) != (hours % 24)) {
            JsDate copy = JsDate.create(jsdate.getTime());
            copy.setDate(copy.getDate() + 1);
            int timeDiff = jsdate.getTimezoneOffset() - copy.getTimezoneOffset();

            // If the time zone offset is changing, advance the hours and
            // minutes from the initially requested time by the change amount
            if (timeDiff > 0) {
                int timeDiffHours = timeDiff / 60;
                int timeDiffMinutes = timeDiff % 60;
                int day = jsdate.getDate();
                int badHours = jsdate.getHours();
                if (badHours + timeDiffHours >= 24) {
                    day++;
                }
                JsDate newTime = JsDate.create(jsdate.getFullYear(), jsdate.getMonth(), day, hours + timeDiffHours,
                        jsdate.getMinutes() + timeDiffMinutes, jsdate.getSeconds(), jsdate.getMilliseconds());
                jsdate.setTime(newTime.getTime());
            }
        }
    }
}