Date对日期的处理

来源:互联网 发布:报价软件手机版 编辑:程序博客网 时间:2024/05/19 13:26

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

   

   了解Java的人都知道,java.util.Date已经是一个过时的类,但是其处理日期的方式去是类似的,通过查看其源代码我们来看看他的处理方式。

    在Java中,月份是从0开始到11结束,年份是从1900开始计算是很容易理解的,不过令人奇怪的是其构造函数中的参数很有问题。其参数year并不是指的现在是哪一年(如2009),而是指这一年隔1900年有多少年(如2009隔1900年有109年),所以第一个参数可能是109。

    现在再看第二参数,Java是这样算的,如果month>=12,则用month除以12,在原来的年份上再加上这个商,就是要求的年份。而月份则是用month对12取模。但如果month小于0,则有点不同了,下面是CalendarUtis中的静态方法floorDivide:

          public static final long floorDivide(long n, long d) {
              return ((n >= 0) ?
                      (n / d) : (((n + 1L) / d) - 1L));
          }
从源代码可以了解,如果-12=<month<0,则年份是减1。现在看月份的处理:

         public static final int mod(int x, int y) {
             return (x - y * floorDivide(x, y));
         }
首先是在参数月份的基础上加上已化为年单位所消耗的月份(floorDivide方法返回的是负数),则变为了前年的月份,(x=-3, y取12,则通过上面的函数计算后为-3 - (12 * (-1)),结果为9).

    更为复杂的就在下面了。

BaseCalendar cal = getCalendarSystem(y);

该方法的实现如下:

 private static final BaseCalendar getCalendarSystem(int year) {
   if (year >= 1582) {
     return gcal; 

  }

  return getJulianCalendar();
}

 

 其中private static final BaseCalendar gcal =  CalendarSystem.getGregorianCalendar();

 

private static BaseCalendar jcal;

 

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

其大意就是,如果时间在1582年以后或等于1582年,则采用格里高利历(因为1582年10月4日之前,应用的是儒略历),否则采用罗马儒略历。顺便把格里高利历也给大家介绍了:

1582年3月1日,格里高利颁发了改历命令,内容是:

  一、1582年10月4日后的一天是10月15日,而不是10月5日,但星期序号仍然连续计算,10月4日是星期四,第二天10月15日是星期五。这样,就把从公元325年以来积累的老账一笔勾销了。

  二、为避免以后再发生春分飘离的现象,改闰年方法为: 凡公元年数能被4整除的是闰年,但当公元年数后边是带两个“0”的“世纪年”时,必须能被400整除的年才是闰年。

  格里高利历的历年平均长度为365日5时49分12秒,比回归年长26秒。虽然照此计算,过3000年左右仍存在1天的误差,但这样的精确度已经相当了不起了。

  由于格里高利历的内容比较简洁,便于记忆,而且精度较高,与天时符合较好,因此它逐步为各国政府所采用。我国是在辛亥革命后根据临时政府通电,从1912年1月1日正式使用格里高利历的。

  人们将这一历法称为“格里高利历”,也就是今天世界上所通用的历法,简称格里历或公历。

cdate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.getDefaultRef());就很容易理解了,就是返回指定指定时区的一个Date对象,这个Date对象将处理这个时区内所有的时间问题。

 

 

 

 

原创粉丝点击