深入学习java源码之Date.before()与Date.clone()

深入学习java源码之Date.before()与Date.clone()

类 Date 表示特定的瞬间,精确到毫秒。

在 JDK 1.1 之前,类 Date 有两个其他的函数。它允许把日期解释为年、月、日、小时、分钟和秒值。它也允许格式化和分析日期字符串。不过,这些函数的 API 不易于实现国际化。从 JDK 1.1 开始,应该使用 Calendar 类实现日期和时间字段之间转换,使用 DateFormat 类来格式化和分析日期字符串。Date 中的相应方法已废弃。

尽管 Date 类打算反映协调世界时 (UTC),但无法做到如此准确,这取决于 Java 虚拟机的主机环境。当前几乎所有操作系统都假定 1 天 = 24 × 60 × 60 = 86400 秒。但对于 UTC,大约每一两年出现一次额外的一秒,称为“闰秒”。闰秒始终作为当天的最后一秒增加,并且始终在 12 月 31 日或 6 月 30 日增加。例如,1995 年的最后一分钟是 61 秒,因为增加了闰秒。大多数计算机时钟不是特别的准确,因此不能反映闰秒的差别。

一些计算机标准是按照格林威治标准时 (GMT) 定义的,格林威治标准时和世界时 (UT) 是相等的。GMT 是标准的“民间”名称;UT 是相同标准的“科学”名称。UTC 和 UT 的区别是:UTC 是基于原子时钟的,UT 是基于天体观察的,两者在实际应用中难分轩轾。因为地球的旋转不是均匀的(它以复杂的方式减速和加速),所以 UT 始终不是均匀地流过。闰秒是根据需要引入 UTC 的,以便把 UTC 保持在 UT1 的 0.9 秒之内,UT1 是应用了某些更正的 UT 版本。

fastTime:当前时间的毫秒表示(从1970.1.1开始算)

Date():用当前时间的毫秒数来初始化fastTime;

public Date() {
        this(System.currentTimeMillis());
    }
public Date(long date) {
        fastTime = date;
    }

clone() :返回该Date对象的一个’副本’(虽然返回是Object,不过可以转成Date);

clone方法是用来复制一个对象。不同于“=”。

对于值类型的数据是可以通过“=”来实现复制的。但是对于引用类型的对象,“=”只能复制其内存地址,使对象的引用指向同一个对象,而不会创建新的对象。clone则可以创建与原来对象相同的对象。举个例子:

Car c1 = new Car();
Car c2 = c1;

这两句事实上只创建了一个对象。只不过c1和c2指向了同一个对象。二者指向的还是同一块内存,所以任何一个引用对内存的操作都直接反映到另一个引用上。

Car c1 = new Car();
Car c2 = c1.clone();

那么就有了两个对象,而且这两个对象的内容是一样的。(所有的属性值相同)

浅拷贝方式,也就是它并不会把对象所有属性全部拷贝一份,而是有选择性的拷贝,拷贝规则如下:

1、基本类型

如果变量是基本类型,则拷贝其值,比如:int、float、long等。

2、String字符串

这个比较特殊,拷贝的是地址,是个引用,但是在修改的时候,它会从字符串池(String Pool)中重新生成新的字符串,原有的字符串对象保持不变,此处可以认为String是个基本类型。

3、对象

如果变量时一个实例对象,则拷贝地址引用,也就是说此时新拷贝出的对象与原有对象共享该实例变量,不受访问权限的限制。这在Java中很疯狂,因为它突破了访问权限的定义,一个private修饰的变量,竟然可以被两个实例对象访问。

关于clone方法的浅拷贝的一个demo,可以看出虽然是两个不同的ShallowCopy对象,但是对于他们的非基本数据类型的成员变量是属于同一个引用。因此是浅拷贝

import java.util.Date;

public class ShallowCopy implements Cloneable {
    private Date begin;
    public Date getBegin(){
        return this.begin;
    }
    public void setBegin(Date d){
        this.begin = d;
    }
    public Object clone(){
        Object obj = null;
        try{
            obj = super.clone();
        }catch(CloneNotSupportedException ex){
            ex.printStackTrace();
        }
        return obj;
    }
    public static void main(String[] args) {
        Date date = new Date(10000L);
        ShallowCopy copy = new ShallowCopy();
        copy.setBegin(date);
        ShallowCopy copy2 = (ShallowCopy) copy.clone();
        System.out.println(copy.getBegin() + "\n" 
                        + copy2.getBegin() + "\n" + 
                         (copy == copy2));
        date.setTime(100000000L);;
        System.out.println(copy.getBegin() + "\n" 
                + copy2.getBegin() + "\n" + 
                 (copy == copy2));
    }
//    Thu Jan 01 08:00:10 CST 1970
//    Thu Jan 01 08:00:10 CST 1970
//    false
//    Fri Jan 02 11:46:40 CST 1970
//    Fri Jan 02 11:46:40 CST 1970
//    false
}

相比深拷贝,拷贝对象的同时,又进行了对成员对象进行了深拷贝。

import java.util.Date;

public class DeepCopy implements Cloneable{
    private Date begin;
    public Date getBegin(){
        return this.begin;
    }
    public void setBegin(Date d){
        this.begin = d;
    }
    public Object clone(){
        DeepCopy obj = null;
        try{
            obj = (DeepCopy)super.clone();
        }catch(CloneNotSupportedException e){
            e.printStackTrace();
        }
        obj.setBegin((Date)this.getBegin().clone());
        return obj;
    }
    public static void main(String[] args) {
        Date date = new Date(10000L);
        DeepCopy copy = new DeepCopy();
        copy.setBegin(date);
        DeepCopy copy2 = (DeepCopy) copy.clone();
        System.out.println(copy.getBegin() + "\n" 
                        + copy2.getBegin() + "\n" + 
                         (copy == copy2));
        date.setTime(100000000L);
        System.out.println(copy.getBegin() + "\n" 
                + copy2.getBegin() + "\n" + 
                 (copy == copy2));
    }
//    Thu Jan 01 08:00:10 CST 1970
//    Thu Jan 01 08:00:10 CST 1970
//    false
//    Fri Jan 02 11:46:40 CST 1970
//    Thu Jan 01 08:00:10 CST 1970
//    false
}

before(Date when)/after(Date when):与when比较是早(before)还是晚(after)(相当于小于号和大于号)。

compareTo(Date anotherDate):定义比较两个Date对象的规则(通过fastTime值的大小)

 

案例:计算星期几

package com.cnten.common.utils;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DateUtil {

	public static Date getLastWeekMonday(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(getThisWeekMonday(date));
		cal.add(Calendar.DATE, -7);
		return cal.getTime();
	}
 
	public static Date getLastWeekFriday(Date date)
	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(getThisWeekMonday(date));
		cal.add(Calendar.DATE, -3);
		return cal.getTime();
	}
	
	public static String getLastWeekFridayStr(Date date)
	{
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Calendar cal = Calendar.getInstance();
		cal.setTime(getThisWeekMonday(date));
		cal.add(Calendar.DATE, -3);
		return sdf.format(cal.getTime());
	}
	
	public static String getLastWeekMondayStr(Date date)
	{
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Calendar cal = Calendar.getInstance();
		cal.setTime(getThisWeekMonday(date));
		cal.add(Calendar.DATE, -7);
		return sdf.format(cal.getTime());
	}
	
	public static Date getThisWeekMonday(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		// 获得当前日期是一个星期的第几天
		int dayWeek = cal.get(Calendar.DAY_OF_WEEK);
		if (1 == dayWeek) {
			cal.add(Calendar.DAY_OF_MONTH, -1);
		}
		// 设置一个星期的第一天,按中国的习惯一个星期的第一天是星期一
		cal.setFirstDayOfWeek(Calendar.MONDAY);
		// 获得当前日期是一个星期的第几天
		int day = cal.get(Calendar.DAY_OF_WEEK);
		// 根据日历的规则,给当前日期减去星期几与一个星期第一天的差值
		cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);
		return cal.getTime();
	}
}
               Date now = new Date();
		//判断本周是星期几:1是星期日、2是星期一、3是星期二、4是星期三、5是星期四、6是星期五、7是星期六
		int weekDay = DateUtil.getDayofweek(now);
		//上周一日期
		String lastMonday = DateUtil.getWeekDayOfDate(now, -7);
		//上周二日期
		String lastThuesDay = DateUtil.getWeekDayOfDate(now, -6);
		//上周三
		String lastWednesday = DateUtil.getWeekDayOfDate(now, -5);
		//上周四日期
		String lastThursDay = DateUtil.getWeekDayOfDate(now, -4);
		//上周五
		String lastFriDay = DateUtil.getWeekDayOfDate(now, -3);
	    //本周周一
		String thisMonday = DateUtil.getThisWeekMondayStr(now);
		//本周周二
		String thisThuesDay = DateUtil.getWeekDayOfDate(now, 1);
		//本周三
		String thisWednesday = DateUtil.getWeekDayOfDate(now, 2);
		//本周四
		String thisThursDay = DateUtil.getWeekDayOfDate(now, 3);
		//本周五
		String thisFriDay = DateUtil.getWeekDayOfDate(now, 4);
		List<LinkedHashMap<String, Object>>  allDataList = new ArrayList<LinkedHashMap<String, Object>>();

 

java源码

Modifier and TypeMethod and Description
booleanafter(Date when)

测试此日期是否在指定日期之后。

booleanbefore(Date when)

测试此日期是否在指定日期之前。

Objectclone()

返回此对象的副本。

intcompareTo(Date anotherDate)

比较两个日期进行订购。

booleanequals(Object obj)

比较两个日期来平等。

static Datefrom(Instant instant)

Instant对象获取一个 Date的实例。

intgetDate()已弃用

截至JDK 1.1版,由Calendar.get(Calendar.DAY_OF_MONTH)

intgetDay()已弃用

截至JDK 1.1版,由Calendar.get(Calendar.DAY_OF_WEEK)

intgetHours()已弃用

截至JDK 1.1版,由Calendar.get(Calendar.HOUR_OF_DAY)

intgetMinutes()已弃用

截至JDK 1.1版,由Calendar.get(Calendar.MINUTE)取代。

intgetMonth()已弃用

截至JDK 1.1版,由Calendar.get(Calendar.MONTH)取代。

intgetSeconds()已弃用

截至JDK 1.1版,由Calendar.get(Calendar.SECOND)

longgetTime()

返回自1970年1月1日以来,由此 Date对象表示的00:00:00 GMT的毫秒 数 。

intgetTimezoneOffset()已弃用

自JDK 1.1版起,由-(Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / (60 * 1000)取代。

intgetYear()已弃用

从JDK 1.1版开始,由Calendar.get(Calendar.YEAR) - 1900

inthashCode()

返回此对象的哈希码值。

static longparse(String s)已弃用

从JDK 1.1版开始,由DateFormat.parse(String s)

voidsetDate(int date)已弃用

从JDK 1.1版开始,由Calendar.set(Calendar.DAY_OF_MONTH, int date)

voidsetHours(int hours)已弃用

从JDK 1.1版开始,由Calendar.set(Calendar.HOUR_OF_DAY, int hours)

voidsetMinutes(int minutes)已弃用

从JDK 1.1版开始,由Calendar.set(Calendar.MINUTE, int minutes)

voidsetMonth(int month)已弃用

从JDK 1.1版开始,由Calendar.set(Calendar.MONTH, int month)

voidsetSeconds(int seconds)已弃用

从JDK 1.1版起,由Calendar.set(Calendar.SECOND, int seconds)取代。

voidsetTime(long time)

设置此 Date对象以表示1970年1月1日00:00:00 GMT后的 time毫秒的时间点。

voidsetYear(int year)已弃用

截至JDK 1.1版,由Calendar.set(Calendar.YEAR, year + 1900)取代。

StringtoGMTString()已弃用

截至JDK 1.1版,由DateFormat.format(Date date) ,使用GMT TimeZone

InstanttoInstant()

将此 Date对象转换为 Instant

StringtoLocaleString()已弃用

从JDK 1.1版开始,由DateFormat.format(Date date)替换。

StringtoString()

将此 Date对象转换为 String的形式:

static longUTC(int year, int month, int date, int hrs, int min, int sec)已弃用

截至JDK 1.1版,由Calendar.set(year + 1900, month, date, hrs, min, sec)GregorianCalendar(year + 1900, month, date, hrs, min, sec) ,使用UTC TimeZone ,其次是Calendar.getTime().getTime()

package java.util;

import java.text.DateFormat;
import java.time.LocalDate;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.lang.ref.SoftReference;
import java.time.Instant;
import sun.util.calendar.BaseCalendar;
import sun.util.calendar.CalendarDate;
import sun.util.calendar.CalendarSystem;
import sun.util.calendar.CalendarUtils;
import sun.util.calendar.Era;
import sun.util.calendar.Gregorian;
import sun.util.calendar.ZoneInfo;

public class Date
    implements java.io.Serializable, Cloneable, Comparable<Date>
{
    private static final BaseCalendar gcal =
                                CalendarSystem.getGregorianCalendar();
    private static BaseCalendar jcal;

    private transient long fastTime;

    private transient BaseCalendar.Date cdate;

    private static int defaultCenturyStart;
	
    private static final long serialVersionUID = 7523967970034938905L;	
	
    public Date() {
        this(System.currentTimeMillis());
    }	
	
    public Date(long date) {
        fastTime = date;
    }	
	
    @Deprecated
    public Date(int year, int month, int date) {
        this(year, month, date, 0, 0, 0);
    }	

    @Deprecated
    public Date(int year, int month, int date, int hrs, int min) {
        this(year, month, date, hrs, min, 0);
    }
	
    @Deprecated
    public Date(int year, int month, int date, int hrs, int min, int sec) {
        int y = year + 1900;
        // month is 0-based. So we have to normalize month to support Long.MAX_VALUE.
        if (month >= 12) {
            y += month / 12;
            month %= 12;
        } else if (month < 0) {
            y += CalendarUtils.floorDivide(month, 12);
            month = CalendarUtils.mod(month, 12);
        }
        BaseCalendar cal = getCalendarSystem(y);
        cdate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.getDefaultRef());
        cdate.setNormalizedDate(y, month + 1, date).setTimeOfDay(hrs, min, sec, 0);
        getTimeImpl();
        cdate = null;
    }	
	
    @Deprecated
    public Date(String s) {
        this(parse(s));
    }	
	
    public Object clone() {
        Date d = null;
        try {
            d = (Date)super.clone();
            if (cdate != null) {
                d.cdate = (BaseCalendar.Date) cdate.clone();
            }
        } catch (CloneNotSupportedException e) {} // Won't happen
        return d;
    }	
	
    @Deprecated
    public static long UTC(int year, int month, int date,
                           int hrs, int min, int sec) {
        int y = year + 1900;
        // month is 0-based. So we have to normalize month to support Long.MAX_VALUE.
        if (month >= 12) {
            y += month / 12;
            month %= 12;
        } else if (month < 0) {
            y += CalendarUtils.floorDivide(month, 12);
            month = CalendarUtils.mod(month, 12);
        }
        int m = month + 1;
        BaseCalendar cal = getCalendarSystem(y);
        BaseCalendar.Date udate = (BaseCalendar.Date) cal.newCalendarDate(null);
        udate.setNormalizedDate(y, m, date).setTimeOfDay(hrs, min, sec, 0);

        // Use a Date instance to perform normalization. Its fastTime
        // is the UTC value after the normalization.
        Date d = new Date(0);
        d.normalize(udate);
        return d.fastTime;
    }	
	
    @Deprecated
    public static long parse(String s) {
        int year = Integer.MIN_VALUE;
        int mon = -1;
        int mday = -1;
        int hour = -1;
        int min = -1;
        int sec = -1;
        int millis = -1;
        int c = -1;
        int i = 0;
        int n = -1;
        int wst = -1;
        int tzoffset = -1;
        int prevc = 0;
    syntax:
        {
            if (s == null)
                break syntax;
            int limit = s.length();
            while (i < limit) {
                c = s.charAt(i);
                i++;
                if (c <= ' ' || c == ',')
                    continue;
                if (c == '(') { // skip comments
                    int depth = 1;
                    while (i < limit) {
                        c = s.charAt(i);
                        i++;
                        if (c == '(') depth++;
                        else if (c == ')')
                            if (--depth <= 0)
                                break;
                    }
                    continue;
                }
                if ('0' <= c && c <= '9') {
                    n = c - '0';
                    while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') {
                        n = n * 10 + c - '0';
                        i++;
                    }
                    if (prevc == '+' || prevc == '-' && year != Integer.MIN_VALUE) {
                        // timezone offset
                        if (n < 24)
                            n = n * 60; // EG. "GMT-3"
                        else
                            n = n % 100 + n / 100 * 60; // eg "GMT-0430"
                        if (prevc == '+')   // plus means east of GMT
                            n = -n;
                        if (tzoffset != 0 && tzoffset != -1)
                            break syntax;
                        tzoffset = n;
                    } else if (n >= 70)
                        if (year != Integer.MIN_VALUE)
                            break syntax;
                        else if (c <= ' ' || c == ',' || c == '/' || i >= limit)
                            // year = n < 1900 ? n : n - 1900;
                            year = n;
                        else
                            break syntax;
                    else if (c == ':')
                        if (hour < 0)
                            hour = (byte) n;
                        else if (min < 0)
                            min = (byte) n;
                        else
                            break syntax;
                    else if (c == '/')
                        if (mon < 0)
                            mon = (byte) (n - 1);
                        else if (mday < 0)
                            mday = (byte) n;
                        else
                            break syntax;
                    else if (i < limit && c != ',' && c > ' ' && c != '-')
                        break syntax;
                    else if (hour >= 0 && min < 0)
                        min = (byte) n;
                    else if (min >= 0 && sec < 0)
                        sec = (byte) n;
                    else if (mday < 0)
                        mday = (byte) n;
                    // Handle two-digit years < 70 (70-99 handled above).
                    else if (year == Integer.MIN_VALUE && mon >= 0 && mday >= 0)
                        year = n;
                    else
                        break syntax;
                    prevc = 0;
                } else if (c == '/' || c == ':' || c == '+' || c == '-')
                    prevc = c;
                else {
                    int st = i - 1;
                    while (i < limit) {
                        c = s.charAt(i);
                        if (!('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'))
                            break;
                        i++;
                    }
                    if (i <= st + 1)
                        break syntax;
                    int k;
                    for (k = wtb.length; --k >= 0;)
                        if (wtb[k].regionMatches(true, 0, s, st, i - st)) {
                            int action = ttb[k];
                            if (action != 0) {
                                if (action == 1) {  // pm
                                    if (hour > 12 || hour < 1)
                                        break syntax;
                                    else if (hour < 12)
                                        hour += 12;
                                } else if (action == 14) {  // am
                                    if (hour > 12 || hour < 1)
                                        break syntax;
                                    else if (hour == 12)
                                        hour = 0;
                                } else if (action <= 13) {  // month!
                                    if (mon < 0)
                                        mon = (byte) (action - 2);
                                    else
                                        break syntax;
                                } else {
                                    tzoffset = action - 10000;
                                }
                            }
                            break;
                        }
                    if (k < 0)
                        break syntax;
                    prevc = 0;
                }
            }
            if (year == Integer.MIN_VALUE || mon < 0 || mday < 0)
                break syntax;
            // Parse 2-digit years within the correct default century.
            if (year < 100) {
                synchronized (Date.class) {
                    if (defaultCenturyStart == 0) {
                        defaultCenturyStart = gcal.getCalendarDate().getYear() - 80;
                    }
                }
                year += (defaultCenturyStart / 100) * 100;
                if (year < defaultCenturyStart) year += 100;
            }
            if (sec < 0)
                sec = 0;
            if (min < 0)
                min = 0;
            if (hour < 0)
                hour = 0;
            BaseCalendar cal = getCalendarSystem(year);
            if (tzoffset == -1)  { // no time zone specified, have to use local
                BaseCalendar.Date ldate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.getDefaultRef());
                ldate.setDate(year, mon + 1, mday);
                ldate.setTimeOfDay(hour, min, sec, 0);
                return cal.getTime(ldate);
            }
            BaseCalendar.Date udate = (BaseCalendar.Date) cal.newCalendarDate(null); // no time zone
            udate.setDate(year, mon + 1, mday);
            udate.setTimeOfDay(hour, min, sec, 0);
            return cal.getTime(udate) + tzoffset * (60 * 1000);
        }
        // syntax error
        throw new IllegalArgumentException();
    }
    private final static String wtb[] = {
        "am", "pm",
        "monday", "tuesday", "wednesday", "thursday", "friday",
        "saturday", "sunday",
        "january", "february", "march", "april", "may", "june",
        "july", "august", "september", "october", "november", "december",
        "gmt", "ut", "utc", "est", "edt", "cst", "cdt",
        "mst", "mdt", "pst", "pdt"
    };
    private final static int ttb[] = {
        14, 1, 0, 0, 0, 0, 0, 0, 0,
        2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
        10000 + 0, 10000 + 0, 10000 + 0,    // GMT/UT/UTC
        10000 + 5 * 60, 10000 + 4 * 60,     // EST/EDT
        10000 + 6 * 60, 10000 + 5 * 60,     // CST/CDT
        10000 + 7 * 60, 10000 + 6 * 60,     // MST/MDT
        10000 + 8 * 60, 10000 + 7 * 60      // PST/PDT
    };	
	
    @Deprecated
    public int getYear() {
        return normalize().getYear() - 1900;
    }	
	
    @Deprecated
    public void setYear(int year) {
        getCalendarDate().setNormalizedYear(year + 1900);
    }	
	
    @Deprecated
    public int getMonth() {
        return normalize().getMonth() - 1; // adjust 1-based to 0-based
    }	
	
    @Deprecated
    public void setMonth(int month) {
        int y = 0;
        if (month >= 12) {
            y = month / 12;
            month %= 12;
        } else if (month < 0) {
            y = CalendarUtils.floorDivide(month, 12);
            month = CalendarUtils.mod(month, 12);
        }
        BaseCalendar.Date d = getCalendarDate();
        if (y != 0) {
            d.setNormalizedYear(d.getNormalizedYear() + y);
        }
        d.setMonth(month + 1); // adjust 0-based to 1-based month numbering
    }	
	
    @Deprecated
    public int getDate() {
        return normalize().getDayOfMonth();
    }	
	
    @Deprecated
    public void setDate(int date) {
        getCalendarDate().setDayOfMonth(date);
    }	
	
    @Deprecated
    public int getDay() {
        return normalize().getDayOfWeek() - BaseCalendar.SUNDAY;
    }	
	
    @Deprecated
    public int getHours() {
        return normalize().getHours();
    }

    @Deprecated
    public void setHours(int hours) {
        getCalendarDate().setHours(hours);
    }

    @Deprecated
    public int getMinutes() {
        return normalize().getMinutes();
    }

    @Deprecated
    public void setMinutes(int minutes) {
        getCalendarDate().setMinutes(minutes);
    }

    @Deprecated
    public int getSeconds() {
        return normalize().getSeconds();
    }

    @Deprecated
    public void setSeconds(int seconds) {
        getCalendarDate().setSeconds(seconds);
    }

    public long getTime() {
        return getTimeImpl();
    }

    private final long getTimeImpl() {
        if (cdate != null && !cdate.isNormalized()) {
            normalize();
        }
        return fastTime;
    }

    public void setTime(long time) {
        fastTime = time;
        cdate = null;
    }

    public boolean before(Date when) {
        return getMillisOf(this) < getMillisOf(when);
    }
	
    public boolean after(Date when) {
        return getMillisOf(this) > getMillisOf(when);
    }	
	
    public boolean equals(Object obj) {
        return obj instanceof Date && getTime() == ((Date) obj).getTime();
    }

    static final long getMillisOf(Date date) {
        if (date.cdate == null || date.cdate.isNormalized()) {
            return date.fastTime;
        }
        BaseCalendar.Date d = (BaseCalendar.Date) date.cdate.clone();
        return gcal.getTime(d);
    }

    public int compareTo(Date anotherDate) {
        long thisTime = getMillisOf(this);
        long anotherTime = getMillisOf(anotherDate);
        return (thisTime<anotherTime ? -1 : (thisTime==anotherTime ? 0 : 1));
    }

    public int hashCode() {
        long ht = this.getTime();
        return (int) ht ^ (int) (ht >> 32);
    }

    public String toString() {
        // "EEE MMM dd HH:mm:ss zzz yyyy";
        BaseCalendar.Date date = normalize();
        StringBuilder sb = new StringBuilder(28);
        int index = date.getDayOfWeek();
        if (index == BaseCalendar.SUNDAY) {
            index = 8;
        }
        convertToAbbr(sb, wtb[index]).append(' ');                        // EEE
        convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' ');  // MMM
        CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd

        CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');   // HH
        CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
        CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
        TimeZone zi = date.getZone();
        if (zi != null) {
            sb.append(zi.getDisplayName(date.isDaylightTime(), TimeZone.SHORT, Locale.US)); // zzz
        } else {
            sb.append("GMT");
        }
        sb.append(' ').append(date.getYear());  // yyyy
        return sb.toString();
    }

    private static final StringBuilder convertToAbbr(StringBuilder sb, String name) {
        sb.append(Character.toUpperCase(name.charAt(0)));
        sb.append(name.charAt(1)).append(name.charAt(2));
        return sb;
    }

    @Deprecated
    public String toLocaleString() {
        DateFormat formatter = DateFormat.getDateTimeInstance();
        return formatter.format(this);
    }

    @Deprecated
    public String toGMTString() {
        // d MMM yyyy HH:mm:ss 'GMT'
        long t = getTime();
        BaseCalendar cal = getCalendarSystem(t);
        BaseCalendar.Date date =
            (BaseCalendar.Date) cal.getCalendarDate(getTime(), (TimeZone)null);
        StringBuilder sb = new StringBuilder(32);
        CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 1).append(' '); // d
        convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' ');  // MMM
        sb.append(date.getYear()).append(' ');                            // yyyy
        CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');      // HH
        CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':');    // mm
        CalendarUtils.sprintf0d(sb, date.getSeconds(), 2);                // ss
        sb.append(" GMT");                                                // ' GMT'
        return sb.toString();
    }

    @Deprecated
    public int getTimezoneOffset() {
        int zoneOffset;
        if (cdate == null) {
            TimeZone tz = TimeZone.getDefaultRef();
            if (tz instanceof ZoneInfo) {
                zoneOffset = ((ZoneInfo)tz).getOffsets(fastTime, null);
            } else {
                zoneOffset = tz.getOffset(fastTime);
            }
        } else {
            normalize();
            zoneOffset = cdate.getZoneOffset();
        }
        return -zoneOffset/60000;  // convert to minutes
    }

    private final BaseCalendar.Date getCalendarDate() {
        if (cdate == null) {
            BaseCalendar cal = getCalendarSystem(fastTime);
            cdate = (BaseCalendar.Date) cal.getCalendarDate(fastTime,
                                                            TimeZone.getDefaultRef());
        }
        return cdate;
    }

    private final BaseCalendar.Date normalize() {
        if (cdate == null) {
            BaseCalendar cal = getCalendarSystem(fastTime);
            cdate = (BaseCalendar.Date) cal.getCalendarDate(fastTime,
                                                            TimeZone.getDefaultRef());
            return cdate;
        }

        // Normalize cdate with the TimeZone in cdate first. This is
        // required for the compatible behavior.
        if (!cdate.isNormalized()) {
            cdate = normalize(cdate);
        }

        // If the default TimeZone has changed, then recalculate the
        // fields with the new TimeZone.
        TimeZone tz = TimeZone.getDefaultRef();
        if (tz != cdate.getZone()) {
            cdate.setZone(tz);
            CalendarSystem cal = getCalendarSystem(cdate);
            cal.getCalendarDate(fastTime, cdate);
        }
        return cdate;
    }

    // fastTime and the returned data are in sync upon return.
    private final BaseCalendar.Date normalize(BaseCalendar.Date date) {
        int y = date.getNormalizedYear();
        int m = date.getMonth();
        int d = date.getDayOfMonth();
        int hh = date.getHours();
        int mm = date.getMinutes();
        int ss = date.getSeconds();
        int ms = date.getMillis();
        TimeZone tz = date.getZone();

        // If the specified year can't be handled using a long value
        // in milliseconds, GregorianCalendar is used for full
        // compatibility with underflow and overflow. This is required
        // by some JCK tests. The limits are based max year values -
        // years that can be represented by max values of d, hh, mm,
        // ss and ms. Also, let GregorianCalendar handle the default
        // cutover year so that we don't need to worry about the
        // transition here.
        if (y == 1582 || y > 280000000 || y < -280000000) {
            if (tz == null) {
                tz = TimeZone.getTimeZone("GMT");
            }
            GregorianCalendar gc = new GregorianCalendar(tz);
            gc.clear();
            gc.set(GregorianCalendar.MILLISECOND, ms);
            gc.set(y, m-1, d, hh, mm, ss);
            fastTime = gc.getTimeInMillis();
            BaseCalendar cal = getCalendarSystem(fastTime);
            date = (BaseCalendar.Date) cal.getCalendarDate(fastTime, tz);
            return date;
        }

        BaseCalendar cal = getCalendarSystem(y);
        if (cal != getCalendarSystem(date)) {
            date = (BaseCalendar.Date) cal.newCalendarDate(tz);
            date.setNormalizedDate(y, m, d).setTimeOfDay(hh, mm, ss, ms);
        }
        // Perform the GregorianCalendar-style normalization.
        fastTime = cal.getTime(date);

        // In case the normalized date requires the other calendar
        // system, we need to recalculate it using the other one.
        BaseCalendar ncal = getCalendarSystem(fastTime);
        if (ncal != cal) {
            date = (BaseCalendar.Date) ncal.newCalendarDate(tz);
            date.setNormalizedDate(y, m, d).setTimeOfDay(hh, mm, ss, ms);
            fastTime = ncal.getTime(date);
        }
        return date;
    }
	
    private static final BaseCalendar getCalendarSystem(int year) {
        if (year >= 1582) {
            return gcal;
        }
        return getJulianCalendar();
    }

    private static final BaseCalendar getCalendarSystem(long utc) {
        // Quickly check if the time stamp given by `utc' is the Epoch
        // or later. If it's before 1970, we convert the cutover to
        // local time to compare.
        if (utc >= 0
            || utc >= GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER
                        - TimeZone.getDefaultRef().getOffset(utc)) {
            return gcal;
        }
        return getJulianCalendar();
    }

    private static final BaseCalendar getCalendarSystem(BaseCalendar.Date cdate) {
        if (jcal == null) {
            return gcal;
        }
        if (cdate.getEra() != null) {
            return jcal;
        }
        return gcal;
    }

    synchronized private static final BaseCalendar getJulianCalendar() {
        if (jcal == null) {
            jcal = (BaseCalendar) CalendarSystem.forName("julian");
        }
        return jcal;
    }

    /**
     * Save the state of this object to a stream (i.e., serialize it).
     *
     * @serialData The value returned by <code>getTime()</code>
     *             is emitted (long).  This represents the offset from
     *             January 1, 1970, 00:00:00 GMT in milliseconds.
     */
    private void writeObject(ObjectOutputStream s)
         throws IOException
    {
        s.writeLong(getTimeImpl());
    }

    /**
     * Reconstitute this object from a stream (i.e., deserialize it).
     */
    private void readObject(ObjectInputStream s)
         throws IOException, ClassNotFoundException
    {
        fastTime = s.readLong();
    }	
	
    public static Date from(Instant instant) {
        try {
            return new Date(instant.toEpochMilli());
        } catch (ArithmeticException ex) {
            throw new IllegalArgumentException(ex);
        }
    }	
	
    public Instant toInstant() {
        return Instant.ofEpochMilli(getTime());
    }
}	

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wespten

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值