JDK源码阅读-------自学笔记(十三)(java.text.DateFormat和SimpleDateFormat类)

时间相关类总图

                                     

  • Date是学习的核心类,表示时间
  • DateFormat用于对日期的字符串转化
  • Calendar对于日期的转化,年月日对象的转化,日期表示和运算的时候使用
  • Calendar实现类SimpleDateFormat和Calendar的GergorianCalendar

时间在计算机中的表示

  • 时间是一维的,只有前后之分
  • 计算机标准纪元,1970年1月1日 00:00:00,每走一个毫秒为一个单位 (科普:由于早期的计算机存储单位比较小,32位能表示的最长时间是68年,从1970年开始的话,加上68.1,实际最终到2038年01月19日03时14分07秒,便会到达最大时间,过了这个时间点,所有32位操作系统时间便会变为 10000000 00000000 00000000 00000000,算下来也就是1901年12月13日20时45分52秒,这样便会出现时间回归的现象,很多软件便会运行异常了。时间回归的现象相信随着64为操作系统的产生逐渐得到解决,因为用64位操作系统可以表示到 292,277,026,596年12月4日15时30分08秒,相信我们的N代子孙,哪怕地球毁灭那天都不用愁不够用了,因为这个时间已经是千亿年以后了。)
  • 获取当前时刻的毫秒值
    1  long currentTimeMillis = System.currentTimeMillis();
    View Code

实战

  • 创建一个日期对象,包是java.util.Date
    1  Date date = new Date();
    View Code

     

  • 源码解析

                                

this(System.currentTimeMillis());相当于创建有参构造函数,并且赋值为当前毫秒值为对象的默认时间,相当于下边的构造方法

1  public Date(long date) {
2         fastTime = date;
3  }
View Code

测试

1         Date date = new Date(System.currentTimeMillis());
2 
3         Date date1 = new Date();
4 
5         System.out.println(date.getTime()==date1.getTime());
View Code

常用方法

  • boolean after(Date when) 测试此日期是否在指定日期之后 核心思维:由于日期存储了当前时间的毫秒数,所以比较日期前后,可以使用getTime()的结果来进行比较得出

源码解析

  • 源码
     1 /*
     2      * If cdate is null, then fastTime indicates the time in millis.
     3      * If cdate.isNormalized() is true, then fastTime and cdate are in
     4      * synch. Otherwise, fastTime is ignored, and cdate indicates the
     5      * time.
     6      */
     7     private transient BaseCalendar.Date cdate;
     8 
     9     /**
    10      * Tests if this date is after the specified date.
    11      *
    12      * @param   when   a date.
    13      * @return  <code>true</code> if and only if the instant represented
    14      *          by this <tt>Date</tt> object is strictly later than the
    15      *          instant represented by <tt>when</tt>;
    16      *          <code>false</code> otherwise.
    17      * @exception NullPointerException if <code>when</code> is null.
    18      */
    19     public boolean after(Date when) {
    20         return getMillisOf(this) > getMillisOf(when);
    21     }
    22 
    23 
    24     /**
    25      * Returns the millisecond value of this <code>Date</code> object
    26      * without affecting its internal state.
    27      */
    28     static final long getMillisOf(Date date) {
    29         if (date.cdate == null || date.cdate.isNormalized()) {
    30             return date.fastTime;
    31         }
    32         BaseCalendar.Date d = (BaseCalendar.Date) date.cdate.clone();
    33         return gcal.getTime(d);
    34     }
    View Code
  • 解析

        核心就是getMillisOf(Date date)这个方法之间的互相比较,getMillisOf(this) > getMillisOf(when)第一个this的对象的毫秒值是否大于when对象的毫秒追,是的话this对象的时间就晚于when的时间,即when对象的时间在this对象的时间之后.

测试

1         Date date = new Date(2000);
2 
3         Date date1 = new Date();
4 
5         System.out.println(date1.after(date));
View Code
  • booleanbefore(Date when) 测试此日期是否在指定日期之前。

源码解析

  • 源码
     1     /*
     2      * If cdate is null, then fastTime indicates the time in millis.
     3      * If cdate.isNormalized() is true, then fastTime and cdate are in
     4      * synch. Otherwise, fastTime is ignored, and cdate indicates the
     5      * time.
     6      */
     7     private transient BaseCalendar.Date cdate;
     8 
     9      /**
    10      * Tests if this date is before the specified date.
    11      *
    12      * @param   when   a date.
    13      * @return  <code>true</code> if and only if the instant of time
    14      *            represented by this <tt>Date</tt> object is strictly
    15      *            earlier than the instant represented by <tt>when</tt>;
    16      *          <code>false</code> otherwise.
    17      * @exception NullPointerException if <code>when</code> is null.
    18      */
    19     public boolean before(Date when) {
    20         return getMillisOf(this) < getMillisOf(when);
    21     }
    22 
    23 
    24     /**
    25      * Returns the millisecond value of this <code>Date</code> object
    26      * without affecting its internal state.
    27      */
    28     static final long getMillisOf(Date date) {
    29         if (date.cdate == null || date.cdate.isNormalized()) {
    30             return date.fastTime;
    31         }
    32         BaseCalendar.Date d = (BaseCalendar.Date) date.cdate.clone();
    33         return gcal.getTime(d);
    34     }
    View Code
  • 解析

        核心就是getMillisOf(Date date)这个方法之间的互相比较,getMillisOf(this) < getMillisOf(when)第一个this的对象的毫秒值是否小于when对象的毫秒追,是的话this对象的时间就早于when的时间,即when对象的时间在this对象的时间之前.

测试

1   
2         Date date = new Date(2000);
3 
4         Date date1 = new Date();
5 
6         System.out.println(date.before(date1));
View Code
  • boolean equals(Object obj) 比较两个日期的相等性。

源码解析

  • 源码
     1      /**
     2      * Compares two dates for equality.
     3      * The result is <code>true</code> if and only if the argument is
     4      * not <code>null</code> and is a <code>Date</code> object that
     5      * represents the same point in time, to the millisecond, as this object.
     6      * <p>
     7      * Thus, two <code>Date</code> objects are equal if and only if the
     8      * <code>getTime</code> method returns the same <code>long</code>
     9      * value for both.
    10      *
    11      * @param   obj   the object to compare with.
    12      * @return  <code>true</code> if the objects are the same;
    13      *          <code>false</code> otherwise.
    14      * @see     java.util.Date#getTime()
    15      */
    16     public boolean equals(Object obj) {
    17         return obj instanceof Date && getTime() == ((Date) obj).getTime();
    18     }
    View Code
  • 解析

        通过核心方法equals(Object obj),核心判断 obj instanceof Date && getTime() == ((Date) obj).getTime();同时满足两个对象的类型相同,获取的getTime()毫秒值相同,就判断两个日期相等

测试

1         Date date = new Date(2000);
2 
3         Date date1 = new Date();
4 
5         System.out.println(date.equals(date1));
View Code
  • long getTime() 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。

源码解析

  • 源码
     1     // The default value of gregorianCutover.
     2     static final long DEFAULT_GREGORIAN_CUTOVER = -12219292800000L;
     3 
     4     private static final BaseCalendar gcal = CalendarSystem.getGregorianCalendar();
     5 
     6     private static BaseCalendar jcal;
     7 
     8     private transient long fastTime;
     9 
    10     /*
    11      * If cdate is null, then fastTime indicates the time in millis.
    12      * If cdate.isNormalized() is true, then fastTime and cdate are in
    13      * synch. Otherwise, fastTime is ignored, and cdate indicates the
    14      * time.
    15      */
    16     private transient BaseCalendar.Date cdate;
    17 
    18     /**
    19      * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
    20      * represented by this <tt>Date</tt> object.
    21      *
    22      * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT
    23      *          represented by this date.
    24      */
    25     public long getTime() {
    26         return getTimeImpl();
    27     }
    28 
    29     private final long getTimeImpl() {
    30         if (cdate != null && !cdate.isNormalized()) {
    31             normalize();
    32         }
    33         return fastTime;
    34     }
    35 
    36 
    37     private final BaseCalendar.Date normalize() {
    38         if (cdate == null) {
    39             BaseCalendar cal = getCalendarSystem(fastTime);
    40             cdate = (BaseCalendar.Date) cal.getCalendarDate(fastTime,
    41                     TimeZone.getDefaultRef());
    42             return cdate;
    43         }
    44 
    45         // Normalize cdate with the TimeZone in cdate first. This is
    46         // required for the compatible behavior.
    47         if (!cdate.isNormalized()) {
    48             cdate = normalize(cdate);
    49         }
    50 
    51         // If the default TimeZone has changed, then recalculate the
    52         // fields with the new TimeZone.
    53         TimeZone tz = TimeZone.getDefaultRef();
    54         if (tz != cdate.getZone()) {
    55             cdate.setZone(tz);
    56             CalendarSystem cal = getCalendarSystem(cdate);
    57             cal.getCalendarDate(fastTime, cdate);
    58         }
    59         return cdate;
    60     }
    61 
    62     private static final BaseCalendar getCalendarSystem(long utc) {
    63         // Quickly check if the time stamp given by `utc' is the Epoch
    64         // or later. If it's before 1970, we convert the cutover to
    65         // local time to compare.
    66         if (utc >= 0
    67                 || utc >= GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER
    68                 - TimeZone.getDefaultRef().getOffset(utc)) {
    69             return gcal;
    70         }
    71         return getJulianCalendar();
    72     }
    73 
    74 
    75     synchronized private static final BaseCalendar getJulianCalendar() {
    76         if (jcal == null) {
    77             jcal = (BaseCalendar) CalendarSystem.forName("julian");
    78         }
    79         return jcal;
    80     }
    View Code
  • 解析
    判断BaseCalendar是否为空,和它的格式是否符合设置的格式,为空和格式符合,就返回输入的毫秒值,不为空,不符合格式规范,进入normalize()方法,对BaseCalendar中的参数进行设置 GregorianCalendar.DEFAULTGREGORIANCUTOVER - TimeZone.getDefaultRef().getOffset(utc) 格里高利历默认时间减去系统时区默认的毫秒值时间
    getJulianCalendar()获取儒略历(Julian Calendar)"规则的时间
    normalize() 对象BaseCalendar为空的时候,获取 格里高利历默认时间减去系统时区默认的毫秒值时间或者儒略历(Julian Calendar)"规则的时间放入对象 再通过 cal.getCalendarDate的毫秒值和时区时间,获取对象日期,再通过对象的日期转化为毫秒值 不是标准格式(!cdate.isNormalized()),通过 cdate = normalize(cdate);,获取日期对象 tz != cdate.getZone() 当前对象是否是默认时区,判断时区是否被更改 时区更改了,改回当前的时区,然后通过对象获取日期
    目的,就是获取BaseCalendar对象,获取其相关日期的参数,然后转化为儒略历的时间计算方式

测试

1         Date date = new Date(2000);
2 
3          System.out.println(date.getTime());
View Code
  • String toString() 把此 Date 对象转换为以下形式的 String:

    dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun、 Mon、Tue、Wed、 Thu、 Fri、 Sat)

源码解析

  • 源码
     1 /**
     2      * Converts this <code>Date</code> object to a <code>String</code>
     3      * of the form:
     4      * <blockquote><pre>
     5      * dow mon dd hh:mm:ss zzz yyyy</pre></blockquote>
     6      * where:<ul>
     7      * <li><tt>dow</tt> is the day of the week (<tt>Sun, Mon, Tue, Wed,
     8      *     Thu, Fri, Sat</tt>).
     9      * <li><tt>mon</tt> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun,
    10      *     Jul, Aug, Sep, Oct, Nov, Dec</tt>).
    11      * <li><tt>dd</tt> is the day of the month (<tt>01</tt> through
    12      *     <tt>31</tt>), as two decimal digits.
    13      * <li><tt>hh</tt> is the hour of the day (<tt>00</tt> through
    14      *     <tt>23</tt>), as two decimal digits.
    15      * <li><tt>mm</tt> is the minute within the hour (<tt>00</tt> through
    16      *     <tt>59</tt>), as two decimal digits.
    17      * <li><tt>ss</tt> is the second within the minute (<tt>00</tt> through
    18      *     <tt>61</tt>, as two decimal digits.
    19      * <li><tt>zzz</tt> is the time zone (and may reflect daylight saving
    20      *     time). Standard time zone abbreviations include those
    21      *     recognized by the method <tt>parse</tt>. If time zone
    22      *     information is not available, then <tt>zzz</tt> is empty -
    23      *     that is, it consists of no characters at all.
    24      * <li><tt>yyyy</tt> is the year, as four decimal digits.
    25      * </ul>
    26      *
    27      * @return  a string representation of this date.
    28      * @see     java.util.Date#toLocaleString()
    29      * @see     java.util.Date#toGMTString()
    30      */
    31     public String toString() {
    32         // "EEE MMM dd HH:mm:ss zzz yyyy";
    33         BaseCalendar.Date date = normalize();
    34         StringBuilder sb = new StringBuilder(28);
    35         int index = date.getDayOfWeek();
    36         if (index == BaseCalendar.SUNDAY) {
    37             index = 8;
    38         }
    39         convertToAbbr(sb, wtb[index]).append(' ');                        // EEE
    40         convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' ');  // MMM
    41         CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd
    42 
    43         CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');   // HH
    44         CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
    45         CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
    46         TimeZone zi = date.getZone();
    47         if (zi != null) {
    48             sb.append(zi.getDisplayName(date.isDaylightTime(), TimeZone.SHORT, Locale.US)); // zzz
    49         } else {
    50             sb.append("GMT");
    51         }
    52         sb.append(' ').append(date.getYear());  // yyyy
    53         return sb.toString();
    54     }
    View Code
  • 解析

拼接字符串按照格式:EEE MMM dd HH:mm:ss zzz yyyy,获取周/月/日/时分秒/时区/年

测试

1         Date date = new Date();
2 
3         System.out.println(date.toString());
View Code 

注:
      大部分方法已经被取代了,不推荐使用了 JDK8,已经推出了新的LocalDate系列取代的新方案,

详情查阅 https://www.cnblogs.com/liuyangfirst/p/10076612.html

posted @ 2020-05-11 01:35  北极的大企鹅  阅读(254)  评论(0编辑  收藏  举报
阅读 - 79万