java时间操作三部曲之java.util.Calendar

   Calendar是个抽象类,它为特定瞬间与一组诸如 YEARMONTHDAY_OF_MONTHHOUR 等 日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。瞬间可用毫秒值来表示,它是距历元(即格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000,格里高利历)的偏移量。它有一个具体的实现类GregorianCalendar子类。

  Calendar类中定义了大量的常量用于方便获取某一瞬间的个个元素点,比如年,月,日,在当年中的第几天,在当月中的第几天等等。

 

public static void main(String[] args) {
    Calendar c=Calendar.getInstance();//2016-11-01 09:27
    System.out.println(c);
}

//下面数据为输出数据
java.util.GregorianCalendar[ time=1477963633233, (日历当前设置时间,毫秒单位) areFieldsSet=true,(如果 fields[] 与当前的设置时间同步,则返回 true。) areAllFieldsSet=true, lenient=true, ( Calendar 有两种解释日历字段的模式,即 lenient 和 non-lenient。当 Calendar 处于 lenient 模式时,它可接受比它所生成的日历字段范围更大范围内的值。
当 Calendar 重新计算日历字段值,以便由 get() 返回这些值时,所有日历字段都被标准化。例如,lenient 模式下的 GregorianCalendar 将 MONTH == JANUARY、DAY_OF_MONTH == 32
解释为 February 1。 当 Calendar 处于 non-lenient 模式时,如果其日历字段中存在任何不一致性,它都会抛出一个异常。例如,GregorianCalendar 总是在 1 与月份的长度之间生成 DAY_OF_MONTH 值。
如果已经设置了任何超出范围的字段值,那么在计算时间或日历字段值时,处于 non-lenient 模式下的 GregorianCalendar 会抛出一个异常。) zone=sun.util.calendar.ZoneInfo[ id="Asia/Shanghai", offset=28800000, dstSavings=0, useDaylight=false, transitions=19, lastRule=null], firstDayOfWeek=1, minimalDaysInFirstWeek=1, ERA=1, YEAR=2016,(年) MONTH=10,(月,10+1,因为是从0开始的) WEEK_OF_YEAR=45,(在当前年是第几周) WEEK_OF_MONTH=1,(在当前月是第几周) DAY_OF_MONTH=1,(指示一个月中的某天,一个月中第一天的值为 1。) DAY_OF_YEAR=306,(在一年中的第几天) DAY_OF_WEEK=3,(在一周的第几天,第一天为周日) DAY_OF_WEEK_IN_MONTH=1,当前月的第几个星期 AM_PM=0,(指示 HOUR 是在中午之前还是在中午之后。例如,在 10:04:15.250 PM 这一时刻,AM_PM 为 PM。) HOUR=9,(小时,12时制,值为1-11) HOUR_OF_DAY=9,(24小时制,时间0-23) MINUTE=27,(分钟) SECOND=13,(秒) MILLISECOND=233,(毫秒) ZONE_OFFSET=28800000, DST_OFFSET=0]

类构造函数

1.protected Calendar()  关键字可以看出,Calendar不希望我们外部直接创建实例,其实Calendar是一个抽象类,不能直接实例化的。

 

类方法

1.static Calendar getInstance() 因为该类是抽象类无法实例化,因此类的创造者提供了获取Calendar实例的方法,看一下源码

public static Calendar getInstance()
{
        return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}

private static Calendar createCalendar(TimeZone zone,Locale aLocale)
{
  CalendarProvider provider =LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale).getCalendarProvider();
   if (provider != null) {
     try {
          return provider.getInstance(zone, aLocale);
      } catch (IllegalArgumentException iae) {
                // fall back to the default instantiation
      }
  }

  Calendar cal = null;

  if (aLocale.hasExtensions()) {
    String caltype = aLocale.getUnicodeLocaleType("ca");
     if (caltype != null) {
       switch (caltype) {
          case "buddhist":
             cal = new BuddhistCalendar(zone, aLocale);
              break;
           case "japanese":
             cal = new JapaneseImperialCalendar(zone, aLocale);
              break;
           case "gregory":
              cal = new GregorianCalendar(zone, aLocale);
                    break;
         }
     }
 }
        if (cal == null) {
            // If no known calendar type is explicitly specified,
            // perform the traditional way to create a Calendar:
            // create a BuddhistCalendar for th_TH locale,
            // a JapaneseImperialCalendar for ja_JP_JP locale, or
            // a GregorianCalendar for any other locales.
            // NOTE: The language, country and variant strings are interned.
            if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                cal = new BuddhistCalendar(zone, aLocale);
            } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                       && aLocale.getCountry() == "JP") {
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else {
                cal = new GregorianCalendar(zone, aLocale);
            }
        }
        return cal;
    }

其实返回的就是GregorianCalendar的实例对象

2.setTime 和 getTime 方法   设置或返回一个表示此 Calendar 时间值(从历元至现在的毫秒偏移量)的 Date 对象。

Calendar c = Calendar.getInstance();
Date date_one = new Date(1421565547000L);
c.setTime(date_one);
System.out.println(c.get(Calendar.YEAR)+"年 "+(c.get(Calendar.MONTH)+1)+"月 "+c.get(Calendar.DAY_OF_MONTH)+"日");//2015年 1月 18日

3.set(int field,int value) 以及该方法的重载,将给定的日历字段设置为给定值。不管处于何种宽松性模式下,该值都不由此方法进行解释。

在使用set方法之前,必须先clear一下,否则很多信息会继承自系统当前时间   

 重载:set(int year,int month,int date);后面还可以加时,分,秒

Calendar c=Calendar.getInstance();
Date date_one=new Date(1421565547000L);
c.setTime(date_one);
System.out.println(c.get(Calendar.YEAR)+"年 "+(c.get(Calendar.MONTH)+1)+"月 "+c.get(Calendar.DAY_OF_MONTH)+"日");//2015年 1月 18日
c.set(Calendar.YEAR,2016);
System.out.println(c.get(Calendar.YEAR)+"年 "+(c.get(Calendar.MONTH)+1)+"月 "+c.get(Calendar.DAY_OF_MONTH)+"日");//2016年 1月 18日
c.set(2016, (11-1), 01, 13, 43,23);
System.out.println(c.get(Calendar.YEAR)+"年 "+(c.get(Calendar.MONTH)+1)+"月 "+c.get(Calendar.DAY_OF_MONTH)+"日 "+c.get(Calendar.HOUR_OF_DAY)+":"+c.get(Calendar.MINUTE));//2016年 11月 1日 13:43

4.clear() 将此 Calendar 的所日历字段值和时间值(从历元至现在的毫秒偏移量)设置成未定义。也可以针对某一个属性设为为定义,就是用clear(int field)

5.before() 和  after()  这两个方法和Date对象的before 和 after 用法一致

6.add(int field,int amount) 根据日历的规则,为给定的日历字段添加或减去指定的时间量。例如,要从当前日历时间减去 5 天,可以通过调用以下方法做到这一点:

add(Calendar.DAY_OF_MONTH, -5)

 

常见问题

1.在获取某一瞬间的各种属性的时候,使用这个类比较方便,因为这个类提供了大量的常量使用,例如:

Date date = new Date();  
        Calendar c = Calendar.getInstance();  
        c.setTime(date);  
        //Calendar.YEAR:日期中的年  
        int year = c.get(Calendar.YEAR);  
        //Calendar.MONTH:日期中的月,需要加1  
        int mounth = c.get(Calendar.MONTH) + 1;  
        //Calendar.DATE:日期中的日  
        int day = c.get(Calendar.DATE);  
        //Calendar.HOUR:日期中的小时(12小时制)  
        int hour = c.get(Calendar.HOUR);  
        //Calendar.HOUR_OF_DAY:24小时制  
        int HOUR_OF_DAY = c.get(Calendar.HOUR_OF_DAY);  
        //Calendar.MINUTE:日期中的分钟  
        int minute = c.get(Calendar.MINUTE);  
        //Calendar.SECOND:日期中的秒  
        int second = c.get(Calendar.SECOND);  
        System.err.println(year + "-" + mounth + "-" + day + " " + hour + ":" + minute + ":" + second);  
          
        //Calendar.WEEK_OF_YEAR:当前年中星期数  
        int WEEK_OF_YEAR = c.get(Calendar.WEEK_OF_YEAR);  
        //Calendar.WEEK_OF_MONTH:当前月中星期数  
        int WEEK_OF_MONTH = c.get(Calendar.WEEK_OF_MONTH);  
        //Calendar.DAY_OF_YEAR:当前年中的第几天  
        int DAY_OF_YEAR = c.get(Calendar.DAY_OF_YEAR);  
        //Calendar.DAY_OF_MONTH:当前月中的第几天  
        int DAY_OF_MONTH = c.get(Calendar.DAY_OF_MONTH);  
        //Calendar.DAY_OF_WEEK:当前星期的第几天(星期天表示第一天,星期六表示第七天)  
        int  DAY_OF_WEEK = c.get(Calendar.DAY_OF_WEEK);  
        //Calendar.DAY_OF_WEEK_IN_MONTH:当前月中的第几个星期  
        int DAY_OF_WEEK_IN_MONTH = c.get(Calendar.DAY_OF_WEEK_IN_MONTH);  

2.计算某一月份的最大天数  

Calendar time=Calendar.getInstance();     
time.clear();     
time.set(Calendar.YEAR,year);     
time.set(Calendar.MONTH,month-1);//注意,Calendar对象默认一月为0                 
int day=time.getActualMaximum(Calendar.DAY_OF_MONTH);//本月份的天数    

3.计算两个任意时间中间的间隔天数

public static void main(String[] args) {
        
        Calendar begin = Calendar.getInstance();
        begin.set(2016, 10, 30);
        Calendar end = Calendar.getInstance();
        end.set(2016, 10, 15);
        System.out.println(CalendarTest.getDaysBetween(begin, end));
    }
    
    public static int getDaysBetween (Calendar begin, Calendar end) {    
        if (begin.after(end)) {      
            Calendar temp = begin;    
            begin = end;    
            end = temp;    
        }    
        int days = end.get(Calendar.DAY_OF_YEAR) - begin.get(Calendar.DAY_OF_YEAR);    
        int y2 = end.get(Calendar.YEAR);    
        if (begin.get(Calendar.YEAR) != y2) {    
            begin = (Calendar) begin.clone();    
            do {    
                days += begin.getActualMaximum(Calendar.DAY_OF_YEAR);//得到当年的实际天数    
                begin.add(Calendar.YEAR, 1);    
            } while (begin.get(Calendar.YEAR) != y2);    
        }    
        return days;    
    }     

4.在我们总结老的时间操作类的时候,java 8  又更新了新的时间操作包,可以阅读一下后面推荐的东西

http://www.open-open.com/lib/view/open1422849534537.html

 

转载于:https://www.cnblogs.com/gaofeng0527/p/6019588.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值