Java8与传统的日期和时间类详解
一、传统的日期时间类(Date和Calendar)
1. Date类
这里的Date是位于java.util包下的类,而不是java.sql包下的date类,Date对象即包含日期也包含时间,从JDK1.0就开始存在了,历史相当悠久,因此,它的大部分构造器和方法已经过时了,不在推荐使用。
Date提供了6个构造器,其中4个已经Deprecated(不推荐使用了,如果继续使用,编译器会提出警告信息,并导致程序性能和安全性方面的问题),剩下2个构造器如下:
♦ Date():生成一个代表当前日期的Date对象。该构造器在底层调用System.currentTimeMillis()获得long长整数作为日期参数。
♦ Date(long date):根据指定的long型整数生成一个Date对象。该构造器的参数表示创建的Date对象和GMT1970年1月1日00:00:00之间的时间差,以毫秒为单位。
Date对象的大部分方法也已经过时了,仅剩下以下几个方法:
♦ boolean after(Date when):测试该日期是否在指定的日期when之后。
♦ boolean before(Date when):测试该日期是否在指定的日期when之前。
♦ long getTime():返回该时间对应的long 型整数,即从GMT 1970-01-01 00:00:00到该Date对象之间的时间差,以毫秒为单位。
♦ void setTine(long time):设置该Date对象的时间。
Date类常用用法如下面程序示例:
public class DateTest {
public static void main(String[] args) {
Date d1 = new Date();
//获取当前时间后的200毫秒的时间
Date d2 = new Date(System.currentTimeMillis() + 200);
System.out.println(d2);
System.out.println(d1.compareTo(d2));
System.out.println(d1.before(d2));
}
}
运行代码结果如下:
Fri Feb 22 21:32:14 CST 2019
-1
true
总体来说,Date类不推荐使用,如果需要获取指定的时间或对时间进行加减运算,可使用calendar工具类。
2. Calendar类
Calendar类本身是一个抽象类,它是所有日历类的模板,但不能之间创建对象,但它提供了几个静态getInstance()方法来获取Calendar对象。
Calendar和Date都是日期的工具类,它们之间可以自由转换,如下代码所示:
Calendar cal = Calendar.getInstance();
//从Calendar对象中取出Date对象
Date date = cal.getTime();
//通过Date对象获取对应的Calendar对象
//由于Calendar没有构造器接收Date对象
//所以必须先获得一个Calendar实例,然后调用其setTime()方法
Calendar cal2 = Calendar.getInstance();
cal2.setTime(date);
Calendar提供了大量的访问、修改日期的方法,常用的如下:
♦ void add(int field,int amount):根据日历的规则,为给定的日历字段添加或减去指定的时间量。
♦ int get(int field):返回指定日历字段的值。
♦ int getActualMaximum(int field):返回指定的日历字段可能拥有的最大值。例如月,最大值为11。
♦ int getActualMinimum(int field):返回指定的日历字段可能拥有的最小值。例如月,最小值为0。
♦ void roll(int field,int amount):与add方法类似,区别在于加上amount后如果超过了该字段的最大范围,也不会向上一个字段进位。
♦ void set(int field,int value):将给定的日历字段设置为给定值。
♦ void set(int year,int month,int date):设置Calendar对象的年、月、日3个字段的值。
♦ void set(int year,int month,int date,int hour,int minute,int second):设置Calendar对象的年、月、日、时、分、秒6个字段的值。
可以看出上面很多方法都需要一个int类型的field参数,field时Calendar类的类变量,如Calendar.YEAR、Calendar.MONTH、Calendar.DATE等分别代表了年、月、日、时、分、秒等字段,需要注意的是Calendar.MONTH月份的起始值是0,范围是0-11。下面程序示范了Calendar的常规用法:
public class CalendarTest {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
//取出年
System.out.print("取出年:");
System.out.println(cal.get(Calendar.YEAR));
//取出月:当前月减1
System.out.print("取出月:");
System.out.println(cal.get(Calendar.MONTH));
//取出日
System.out.print("取出日:");
System.out.println(cal.get(Calendar.DATE));
//分别设置年、月、日、时、分、秒
System.out.print("设置时间:");
cal.set(2019, 02, 22, 22, 06, 34);
System.out.println(cal.getTime());
//将Calendar的年前推1年
System.out.print("将Calendar的年前推1年:");
cal.add(Calendar.YEAR, -1);
System.out.println(cal.getTime());
//将Calendar的月前推3个月
System.out.print("将Calendar的月前推3个月:");
cal.add(Calendar.MONTH, -3);
System.out.println(cal.getTime());
}
}
打印结果为:
取出年:2019
取出月:1
取出日:22
设置时间:Fri Mar 22 22:06:34 CST 2019
将Calendar的年前推1年:Thu Mar 22 22:06:34 CST 2018
将Calendar的月前推3个月:Fri Dec 22 22:06:34 CST 2017
Calendar类需要注意的以下几点:
♦ add与roll的区别
add(int field,int amount)方法主要用于改变Calendar的特定字段的值。如果要增加某个字段的值,则amount为正数,如果要减少某个字段的值,则amount为负数。此方法有如下两条规则:
1)当被修改的字段超出它允许的范围时,会发生进位,即上一级字段也会增大。例如:
Calendar cal = Calendar.getInstance();
cal.set(2008,7,23,0,0,0);//2008-8-23
cal.add(Calendar.MONTH,6);//2008-8-23 =>2009-2-23
2) 如果下一级字段也需要改变,则该字段会修正到变化最小的值。例如:
Calendar cal = Calendar.getInstance();
cal.set(2008,7,31,0,0,0);//2008-8-31
//因为进位后月份变为2,而2月没有31日,自动变成28
cal.add(Calendar.MONTH,6);//2008-8-31 =>2009-2-28
roll()的规则与add()规则处理不同:当被修改的字段超出它允许的范围时,上一级字段也不会增大,即不会发生进位。例如:
Calendar cal = Calendar.getInstance();
cal.set(2008,7,23,0,0,0);//2008-8-23
cal.add(Calendar.MONTH,6);//2008-8-23 =>2008-2-23
roll()下一级字段的处理与add()相同,都会修正到该字段变化的最小值,例如:
Calendar cal = Calendar.getInstance();
cal.set(2008,7,31,0,0,0);//2008-8-31
//2月没有31日,自动变成29,YEAR字段不会改变
cal.add(Calendar.MONTH,6);//2008-8-31 =>2008-2-29
♦ 设置Calendar的容错性
先看如下代码:
Calendar cal = Calendar.getInstance();
System.out.println("现在时间:"+cal.getTime());
cal.set(Calendar.MONTH, );//(1)
System.out.println("月份加上13后的时间"+cal.getTime());
//关闭容错性
cal.setLenient(false);
cal.set(Calendar.MONTH, );//(2)
System.out.println(cal.getTime());
打印结果为:
现在时间:Sat Feb :: CST
月份加上13后的时间Sun Feb :: CST
Exception in thread "main" java.lang.IllegalArgumentException: MONTH
at java.util.GregorianCalendar.computeTime(GregorianCalendar.java:)
at java.util.Calendar.updateTime(Calendar.java:)
at java.util.Calendar.getTimeInMillis(Calendar.java:)
at java.util.Calendar.getTime(Calendar.java:)
at com.bhyj.CalendarTest.main(CalendarTest.java:)
从打印结果可以看出:月份加上13后,代码能正常执行,YEAR字段加1,MONTH字段为1即2月,但是加上cal.setLenient(false);这行代码后,代码运行时异常,因为月份超出了最大月份。Calendar默认支持较好的容错性,可以关闭其容错性,让它进行严格的参数检查。
♦ set()方法延迟修改
通过set()方法设置某一个字段的值得时候,该字段的值不会立马修改,直到下次调用get()、getTime()等时才会重新计算日历的时间。延迟修改的优势是多次调用set()方法不会触发多次不必要的计算。下面程序演示了set()方法延迟修改的效果:
Calendar cal = Calendar.getInstance();
cal.set(2003,7,31);//2003-8-31
//将月份设为9,但9月31不存在
//如果立即修改,系统会把cal自动调整到10月1日
cal.set(Calendar.MONTH,8);
//下面代码输出了10月1日
System.out.println(cal.getTime());//(1)
//设置DATE字段为5
cal.set(Calendar.DATE, 5);//(2)
System.out.println(cal.getTime());//(3)
打印结果为:
Wed Oct 01 22:25:41 CST 2003
Sun Oct 05 22:25:41 CST 2003
如果将(1)处的代码注释掉,打印结果为:
Fri Sep 05 22:28:06 CST 2003
你看明白了吗?如果将(1)处的代码注释掉,因为set()方法具有延迟性,它内部只是先记录下MONTH字段的值为8,接着程序将DATE字段设置为5,程序内部再次记录DATE字段的值为5——就是9月5日。
二、Java8新增的日期、时间包
为了弥补传统Java对日期、时间处理的不足,Java8提供了一套全新的日期时间库。Java8专门新增了一个java.time包,该包下包含了如下常用类。
♦ Clock:该类用于获取指定时区的当前日期、时间。该类可以取代System类的currentTimeMillis()方法,该类提供了大量的方法获取当前的日期和时间,如下图:
程序代码示例如下:
//获取当前Clock
Clock clock = Clock.systemUTC();
//获取clock对应的毫秒数
//等于System.currentTimeMillis()
System.out.println(clock.millis());
System.out.println(System.currentTimeMillis());
♦ Duration:该类代表持续时间
示例代码如下:
Duration d = Duration.ofSeconds(600);
System.out.println("600秒="+d.toMinutes()+"分");
System.out.println("600秒="+d.toHours()+"时");
System.out.println("600秒="+d.toDays()+"天");
♦ Instant:该类代表一个具体的时刻,可以精确到纳秒。该类主要提供了以下几个方法:
1)now():获取当前时刻。
2)now(Clock clock):获取clock对应的时刻。
3)minusXxx():在当前时刻基础上减去一段时间。
4)plusXxx():在当前时刻基础上加上一段时间。
代码示例如下:
//获取当前时间
Instant instant = Instant.now();
System.out.println(instant);
//instant增加600秒
Instant instant2 = instant.plusSeconds(600);
♦ LocalDate:该类代表不带时区的日期,如:2019-02-24。该类主要提供了以下几个方法:
1)now():获取当前日期。
2)now(Clock clock):获取clock对应的日期。
3)minusXxx():在当前年份基础上减去几年、几月、几周或几日等。
4)plusXxx():在当前年份基础上加上几年、几月、几周或几日等。
♦ LocalTime:该类代表不带时区的时间,如:10:20:09。该类主要提供了以下几个方法:
1)now():获取当前时间。
2)now(Clock clock):获取clock对应的时间。
3)minusXxx():在当前年份基础上减去几小时、几分、几秒等。
4)plusXxx():在当前年份基础上加上几小时、几分、几秒等。
♦ LocalDateTime:该类代表不带时区的日期、时间,如:2019-02-24T10:20:09。该类主要提供了以下几个方法:
1)now():获取当前日期、时间。
2)now(Clock clock):获取clock对应的日期、时间。
3)minusXxx():在当前年份基础上减去几年、几月、几周或几日、几小时、几分、几秒等。
4)plusXxx():在当前年份基础上加上几年、几月、几周或几日、几小时、几分、几秒等。
♦ MonthDay:该类仅代表月日,如:--09-20。该类主要提供了以下几个方法:
1)now():获取当前月日。
2)now(Clock clock):获取clock对应的月日。
♦ Year:该类仅代表年,如:2019。该类主要提供了以下几个方法:
1)now():获取当前年份。
2)now(Clock clock):获取clock对应的年份。
3)minusXxx():在当前年份基础上减去几年。
4)plusXxx():在当前年份基础上加上几年。
♦ YearMonth:该类仅代表年月,如:2019-02。该类主要提供了以下几个方法:
1)now():获取当前年月。
2)now(Clock clock):获取clock对应的年月。
3)minusXxx():在当前年份基础上减去几年、几月。
4)plusXxx():在当前年份基础上加上几年、几月。
♦ ZonedDateTime:该类代表一个时区化的日期、时间。
♦ ZonedId:该类代表一个时区。
♦ DayOfWeek:该类是一个枚举类,定义了周日到周六的枚举值。
♦ Month:该类是一个枚举类,定义了一月到十二月的枚举值。
欢迎关注微信公众号【Java典籍】,收看更多Java技术干货!
▼微信扫一扫下图↓↓↓二维码关注
Java8与传统的日期和时间类详解的更多相关文章
- PHP 日期与时间函数详解
在开发过程中,我们经常碰到日期与时间戳相关的功能,今天趁此机会做个详细笔记. date_default_timezone_set('PRC'); /*把时间调到北京时间,php5默认为格林威治标准时间 ...
- Java8 日期和时间类
新的日期和时间API 新的日期和时间类解决了Date和Calendar类出现的问题 浅尝 LocalDate 日期类 LocalDate of = LocalDate.of(2018, 7, 13); ...
- Java知多少(77)日期和时间类
Java 的日期和时间类位于 java.util 包中.利用日期时间类提供的方法,可以获取当前的日期和时间,创建日期和时间参数,计算和比较时间. Date 类 Date 类是 Java 中的日期时间类 ...
- 【java8新特性】日期和时间
Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本. Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程,新的 JavaScript ...
- C# 内置 DateTime类详解
C# 内置 DateTime类详解 摘抄自微软官方文档,用来方便自己查阅:网址:https://msdn.microsoft.com/zh-cn/library/system.datetime(v=v ...
- URLConnection类详解-转
转-http://www.cnblogs.com/shijiaqi1066/p/3753224.html 1. URLConnection概述 URLConnection是一个抽象类,表示指向URL指 ...
- SQL Server时间粒度系列----第3节旬、月时间粒度详解
本文目录列表: 1.SQL Server旬时间粒度2.SQL Server月有关时间粒度 3.SQL Server函数重构 4.总结语 5.参考清单列表 SQL Server旬时间粒度 ...
- SQL Server时间粒度系列----第4节季、年时间粒度详解
本文目录列表: 1.SQL Server季时间粒度2.SQL Server年时间粒度 3.总结语 4.参考清单列表 SQL Serve季时间粒度 季时间粒度也即是季度时间粒度.一年每3 ...
- [NewLife.XCode]实体类详解
NewLife.XCode是一个有10多年历史的开源数据中间件,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含 ...
随机推荐
- 在MFC中怎么获得Excel文档中已经使用了的行数和列数
_Worksheet ws;Range range; range = ws.GetUsedRange();//获得Worksheet已使用的范围range = range.GetRows(); / ...
- 【LOJ #6094. 「Codeforces Round #418」归乡迷途】
题目大意: 传送门. lca说的很明白就不重复了. 题解: 先膜一发lca. 大体读完题以后我们可以知道对于第i个节点最短路一定是连向1到i-1中的某个点. 然后我们考虑将到1距离(这里及以下均是最短 ...
- 【强连通分量】Bzoj1194 HNOI2006 潘多拉的盒子
Description Sulotion 首先要对每对咒语机建图,判断机器a是否能生成所有机器b生成的 如果跑一个相同的串,最后结束的点b可输出a不可输出,判断就为否 大概就用这种思路,f[x][y] ...
- dev和master合并冲突解决
前景 master主分支,dev是开发分支,master会保持最新的dev代码 问题的产生 dev开发新功能 版本发布,dev合并到了master,发布生产环境 新需求来了,在dev进行开发 同时,线 ...
- zookeeper源码 — 二、集群启动—leader选举
上一篇介绍了zookeeper的单机启动,集群模式下启动和单机启动有相似的地方,但是也有各自的特点.集群模式的配置方式和单机模式也是不一样的,这一篇主要包含以下内容: 概念介绍:角色,服务器状态 服务 ...
- 《前端之路》之 JavaScript 高级技巧、高阶函数(一)
目录 一.高级函数 1-1 安全的类型检测 1-2 作用域安全的构造函数 1-3 惰性载入函数 1-4 函数绑定 1-5 函数柯里化 1-6 反函数柯里化 一.高级函数 1-1 安全的类型检测 想到类 ...
- Java3y文章目录导航
由于写的文章已经是有点多了,为了自己和大家的检索方便,于是我就做了这么一个博客导航. 想要获取最新原创的技术文章欢迎关注我的公众号:Java3y 文章目录导航:https://github.com/Z ...
- [JavaScript] AMD和CMD概述
1. cmd 和 amd 在浏览器中,受网络和浏览器渲染的制约,不能采用同步加载,只能采用异步加载.于是 AMD 规范应运而生 2. AMD AMD(Asynchronous Module Defin ...
- [Linux] host dig nslookup查询域名的DNS解析
root@VM-38-204-ubuntu:~# host baidu.com baidu.com has address 220.181.57.216 baidu.com has address 1 ...
- PHP 中move_uploaded_file 上传中文文件名失败
项目需要上传文件名保持不变,发现上传中文失败:错误如下: move_uploaded_file(public/upload/files//-/\开密二次开发.rar): failed to open ...