zoukankan      html  css  js  c++  java
  • 6.4 Java 8的日期、时间类

    一、Date类——java.util.Date

    Date对象既包含时间也包含日期,但是由于Date类从JDK1.0就开始存在了,所以它大部分方法和构造器都显示过时了,不推荐使用。
    Date类提供了6个构造器,剩下2个构造器:
    (1)Date():生成一个代表当前日期时间的对象。该构造器在底层调用System.currentTimeMillis()获取long整数作为日期的参数。
    (2)Date(long date):根据long型整数生成一个Date对象,该构造器的参数表示的Date对象与GMT 1970年1月1日00:00:00之间的时间差,以毫秒作为计时单位。
    Date类未过时的方法:
    (1)boolean after(Date when):测试该日期在指定日期When之后
    (2)boolean before(Date when):测试该日期在指定日期When之前
    (3)long getTime():返回该时间对应的long型整数。以时间戳返回,单位为毫秒
    (4)void setTime(long time):设置该对象的时间

    import java.util.Date;
    public class DateTest
    {
    	public static void main(String[] args)
    	{
    		var d1=new Date();
    		//获取当前时间的后100ms
    		var d2=new Date(System.currentTimeMillis()+100);
    		System.out.println(d2);
    		System.out.println(d1.compareTo(d2));
    		System.out.println(d1.before(d2));
    	}
    }
    ---------- 运行Java捕获输出窗 ----------
    Thu Mar 12 11:40:03 CST 2020
    -1
    true
    
    输出完成 (耗时 0 秒) - 正常终止
    

    二、Calendar类

    由于Date类在设计上的一些缺陷,所以Java提供了Calendar类来更好地处理日期和时间。Calendar是一个抽象类,它用于表示日历。
    为了统一计时,全球通常选择最普及和最通用的日历:Gregorian Calendar,也就是介绍年份时最常用的“公元几年”。
    Calendar是一个抽象类,它是所有日历类的模板,并提供了一些日历中通用的方法;但它本身不能直接实例化,程序只能创建Calendar子类的实例,Java本身提供了GregorianCalendar类,一个代表格里高利日历的子类,它代表了我们通常所说的公历。
    当然也可以创建自己的Calendar子类,可以自己通过互联网查看Calendar各子类的源代码学习。
    Calendar类是一个抽象类,所以不能通过Calendar构造器来创建Calendar对象,但它提供了几个静态方法 getInstance()方法来获取Calendar对象,这些方法根据TimeZone,Locale类来获取特定的Calendar,如果不指定TimeZone,Locale ,则默认使用TimeZone,Locale来创建Calendar。
    Calendar类与Date类都是表示日期的工具类,它们可以直接自由转换:

    //创建一个Calendar实例
    var canlendar=Calendar.getInstance();
    //从Canlendar对象中取出Date对象
    var date=calendar.getTime();
    //通过Date对象获得Canlendar对象
    //因为Calendar/GregorianCalendar没有构造器可以接受Date对象
    //所以必须先获得一个Calendar实例,然后调用其setTime()方法
    var canlendar2=Calendar.getInstance();
    calendar2.setTime(date);
    

    Calendar提供了大量访问、修改日期时间的方法:
    (1)void add(int field,int amount):根据日历的规则给指定日历字段添加和减去指定时间量
    (2)int get(int field):获取指定日历字段的值
    (3)int getActualMaximum(int field):返回指定日历字段可能拥有的最大值。例如:月,最大值为11
    (4)int getActualMinimum(int field):返回指定日历字段可能拥有的最小值。例如:月,最大值为0
    (5)int roll(int field,int amount):与add()方法相似,区别在于加上amount后超过了该字段所能表示的最大范围,也并不会向上一个字段进位。
    (6)void set(int year,int month,int date):设置Calenar年月日三个字段的值。
    (7)void set(int year,int month,int date,int hourOfDay,int minute,int second):设置Calenar年月日时分秒6个字段的值。
    上面的方法都需要一个int类型的field参数,field是Calendar类的类变量,如Calendar.YEAR、Calendar.MONTH等。

    import java.util.*;
    import static java.util.Calendar.*;
    public class CalendarTest
    {
    	public static void main(String[] args)
    	{
    		var c = Calendar.getInstance();
    		// 取出年
    		System.out.println(c.get(YEAR));
    		// 取出月份
    		System.out.println(c.get(MONTH));
    		// 取出日
    		System.out.println(c.get(DATE));
    		// 分别设置年、月、日、小时、分钟、秒
    		c.set(2003, 10, 23, 12, 32, 23); //2003-11-23 12:32:23
    		System.out.println(c.getTime());
    		// 将Calendar的年前推1年
    		c.add(YEAR, -1); //2002-11-23 12:32:23
    		System.out.println(c.getTime());
    		// 将Calendar的月前推8个月
    		c.roll(MONTH, -8); //2002-03-23 12:32:23
    		System.out.println(c.getTime());
    
    
    		var cal1 = Calendar.getInstance();
    		cal1.set(2003, 7, 23, 0, 0, 0); // 2003-8-23
    		cal1.add(MONTH, 6); //2003-8-23 => 2004-2-23
    		System.out.println(cal1.getTime());
    
    
    		var cal2 = Calendar.getInstance();
    		cal2.set(2003, 7, 31, 0, 0, 0); // 2003-8-31
    		// 因为进位到后月份改为2月,2月没有31日,自动变成29日
    		cal2.add(MONTH, 6); // 2003-8-31 => 2004-2-29
    		System.out.println(cal2.getTime());
    
    
    		var cal3 = Calendar.getInstance();
    		cal3.set(2003, 7, 23, 0, 0, 0); //2003-8-23
    		// MONTH字段“进位”,但YEAR字段并不增加
    		cal3.roll(MONTH, 6); //2003-8-23 => 2003-2-23
    		System.out.println(cal3.getTime());
    
    
    		var cal4 = Calendar.getInstance();
    		cal4.set(2003, 7, 31, 0, 0, 0); //2003-8-31
    		// MONTH字段“进位”后变成2,2月没有31日,
    		// YEAR字段不会改变,2003年2月只有28天
    		cal4.roll(MONTH, 6); //2003-8-31 => 2003-2-28
    		System.out.println(cal4.getTime());
    	}
    }
    
    ---------- 运行Java捕获输出窗 ----------
    2020
    2
    12
    Sun Nov 23 12:32:23 CST 2003
    Sat Nov 23 12:32:23 CST 2002
    Sat Mar 23 12:32:23 CST 2002
    Mon Feb 23 00:00:00 CST 2004
    Sun Feb 29 00:00:00 CST 2004
    Sun Feb 23 00:00:00 CST 2003
    Fri Feb 28 00:00:00 CST 2003
    
    输出完成 (耗时 0 秒) - 正常终止
    

    1、add和roll的区别

    add(int field,int amount),add主要用于改变Calendar的特定字段的值。如果需要增加,则让amount为正,如果需要减少某字段的值,则让amount为负。
    add(int field,int amount)有两条规则:
    (1)当修改的字段超过了它允许的范围,会发生进位,则上一级字段增大。
    (2)如果下一级字段也需要改变,那么该字段会修正到变化最小的值。

    	cal2.set(2003, 7, 31, 0, 0, 0); // 2003-8-31
    	// 因为进位到后月份改为2月,2月没有31日,自动变成29日
    	cal2.add(MONTH, 6); // 2003-8-31 => 2004-2-29
    

    roll()的规则与add()不同:当被处理的字段超过它允许的范围,则上一级字段不会增大

    	cal3.set(2003, 7, 23, 0, 0, 0); //2003-8-23
    	// MONTH字段“进位”,但YEAR字段并不增加
    	cal3.roll(MONTH, 6); //2003-8-23 => 2003-2-23
    

    下一级处理规则与add()类似

    	cal4.set(2003, 7, 31, 0, 0, 0); //2003-8-31
    	// MONTH字段“进位”后变成2,2月没有31日,
    	// YEAR字段不会改变,2003年2月只有28天
    	cal4.roll(MONTH, 6); //2003-8-31 => 2003-2-28
    

    2、设置Calendar的容错性

    例如set()方法传入一个不合法的参数,比如MONTH字段设置为13

    import java.util.Calendar;
    import static java.util.Calendar.*;
    public class LenientTest
    {
    	public static void main(String[] args)
    	{
    		Calendar cal=Calendar.getInstance();
    		System.out.println(cal.getTime());//Thu Mar 12 21:16:52 CST 2020
    		//结果是YEAR增加1,MOMTH字段为1(2月)
    		cal.set(MONTH,13);
    		System.out.println(cal.getTime());//Fri Feb 12 21:16:52 CST 2021
    		//关闭容错性
    		cal.setLenient(false);
    		//导致运行时异常
    		cal.set(MONTH,13);
    		System.out.println(cal.getTime());
    
    	}
    }
    

    Calendar有两种解释日历字段的模式:lenient模式和non-lenient模式。当Calendar处于lenient模式时,每个字段可接受超出它允许范围的值;当Calendar处于non-lenient模式时,每个字段不可接受超出它允许范围的值,将会抛出异常;

    3、set()方法延迟修改

    set(f,value)方法将日历字段f更改为value,此外他还有一个内部成员变量,以指示日历字段f已被更改。尽管日历字段f是立即更改的,但该Calendar所代表的时间不会立即修改,直到下次调用get()getTime()getTimeMillis()add() oll()时才会重新计算日历时间,这被称作set()方法的延迟修改,采用延迟修改的优势是多次调用set()不会触发多次不必要的计算(需要计算出一个代表时间的long型整数)。

    import java.util.Calendar;
    import static java.util.Calendar.*;
    public class LazyTest
    {
    	public static void main(String[] args)
    	{
    		Calendar cal=Calendar.getInstance();
    		cal.set(2003,7,31);
    		//将年份设置为9,但9月31日不存在
    		//如果立即修改,系统会把cal自动调节到10,1
    		cal.set(MONTH,8);
    		//下面代码将输出10.1
    		//System.out.println(cal.getTime());//Wed Oct 01 21:29:39 CST 2003
    		cal.set(DATE,5);
    		System.out.println(cal.getTime());//Fri Sep 05 21:30:55 CST 2003
    	}
    }
    

    三、Java 8新增的日期、时间包——java.time

    具体这些类的用法查看API文档

  • 相关阅读:
    Redis详解(一)- redis的简介与安装
    集合-全部集合概览
    集合-LinkedList源码解析
    集合-ArrayDeque源码解析
    集合-DelayQueue源码解析
    集合-ConcurrentLinkedQueue 源码解析
    集合-LinkedTransferQueue源码解析
    集合-PriorityBlockingQueue 源码解析
    集合-SynchronousQueue 源码解析
    集合-LinkedBlockingQueue 源码解析
  • 原文地址:https://www.cnblogs.com/weststar/p/12468072.html
Copyright © 2011-2022 走看看