Java8新特性——新一套时间API的使用
JDK 1.0中包含了一个java.util.Date类,但是它的大多数方法已经在JDK 1.1引入Calendar类之后被弃用了。而Calendar并不比Date好多少。它们面临的问题是:
可变性:像日期和时间这样的类应该是不可变的。
偏移性:Date中的年份是从1900开始的,而月份都从0开始。
格式化:格式化只对Date有用,Calendar则不行。
此外,它们也不是线程安全的;不能处理闰秒等。
关于线程安全问题,下面举个例子
package com.xnn.time;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* 类(接口)描述:
* @author xnn
* 2018年10月24日下午10:59:06
*/
public class TestSimpleDateFormat {
public static void main(String[] args) throws Exception {
//定义日期格式
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
Callable<Date> callable = new Callable<Date>() {
@Override
public Date call() throws Exception {
return format.parse("20181024");
}
};
//创建一个有10个线程的线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
List<Future<Date>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
//把每个线程执行的结果放在集合中去
futures.add(pool.submit(callable));
}
for (Future<Date> future : futures) {
System.out.println(future.get());
}
}
}
运行结果
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NumberFormatException: multiple points
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at com.xnn.time.TestSimpleDateFormat.main(TestSimpleDateFormat.java:37)
Caused by: java.lang.NumberFormatException: multiple points
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1890)
at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.lang.Double.parseDouble(Double.java:538)
at java.text.DigitList.getDouble(DigitList.java:169)
at java.text.DecimalFormat.parse(DecimalFormat.java:2056)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
at java.text.DateFormat.parse(DateFormat.java:364)
at com.xnn.time.TestSimpleDateFormat$1.call(TestSimpleDateFormat.java:28)
at com.xnn.time.TestSimpleDateFormat$1.call(TestSimpleDateFormat.java:1)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
报了个并发异常的错,
在Java8之前,我们都是通过加锁来处理诸如此类的问题。
/**
*
*/
package com.xnn.time;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 类(接口)描述:线程池锁
* @author xnn
* 2018年10月25日上午9:39:07
*/
public class DateFormatThreadLocal {
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
//重写ThreadLocal类的initialValue()方法没返回一个
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyyMMdd");
}
};
//解析时间
public static Date convert (String source) throws Exception {
return df.get().parse(source);
}
}
package com.xnn.time;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* 类(接口)描述:
* @author xnn
* 2018年10月24日下午10:59:06
*/
public class TestSimpleDateFormat {
public static void main(String[] args) throws Exception {
Callable<Date> callable = new Callable<Date>() {
@Override
public Date call() throws Exception {
return DateFormatThreadLocal.convert("20181024");
}
};
//创建一个有10个线程的线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
List<Future<Date>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
//把每个线程执行的结果放在集合中去
futures.add(pool.submit(callable));
}
for (Future<Date> future : futures) {
System.out.println(future.get());
}
pool.shutdown();
}
}
运行结果
Wed Oct 24 00:00:00 CST 2018
Wed Oct 24 00:00:00 CST 2018
Wed Oct 24 00:00:00 CST 2018
Wed Oct 24 00:00:00 CST 2018
Wed Oct 24 00:00:00 CST 2018
Wed Oct 24 00:00:00 CST 2018
Wed Oct 24 00:00:00 CST 2018
Wed Oct 24 00:00:00 CST 2018
Wed Oct 24 00:00:00 CST 2018
Wed Oct 24 00:00:00 CST 2018
第三次引入的API是成功的,并且java 8中引入的java.time API 已经纠正了过去的缺陷,将来很长一段时间内它都会为我们服务。
Java 8 吸收了 Joda-Time 的精华,以一个新的开始为 Java 创建优秀的 API。新的 java.time 中包含了所有关于本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。历史悠久的 Date 类新增了 toInstant() 方法,用于把 Date 转换成新的表示形式。这些新增的本地化时间日期 API 大大简化了日期时间和本地化的管理.
java.time – 包含值对象的基础包
java.time.chrono – 提供对不同的日历系统的访问
java.time.format – 格式化和解析时间和日期
java.time.temporal – 包括底层框架和扩展特性
java.time.zone – 包含时区支持的类
说明:大多数开发者只会用到基础包和format包,也可能会用到temporal包。因此,尽管有68个新的公开类型,大多数开发者,大概将只会用到其中的三分之一。
现在有了新的时间日期API可以完美解决线程安全问题
package com.xnn.time;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* 类(接口)描述:
* @author xnn
* 2018年10月24日下午10:59:06
*/
public class TestSimpleDateFormat {
public static void main(String[] args) throws Exception {
//用LocalDate类
Callable<LocalDate> callable = new Callable<LocalDate>() {
@Override
public LocalDate call() throws Exception {
//定义格式用DateTimeFormater类
DateTimeFormatter formatter =DateTimeFormatter.ofPattern("yyyyMMdd") ;
return LocalDate.parse("20181025",formatter);
}
};
//创建一个有10个线程的线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
List<Future<LocalDate>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
//把每个线程执行的结果放在集合中去
futures.add(pool.submit(callable));
}
for (Future<LocalDate> future : futures) {
System.out.println(future.get());
}
pool.shutdown();
}
}
本地时间与时间戳LocalDate LocalTime LocalDateTime
LocalDate、LocalTime、LocalDateTime 类是其中较重要的几个类,它们的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息
package com.xnn.time;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.Period;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import org.junit.Test;
/**
* 类(接口)描述:
* @author xnn
* 2018年10月25日上午10:39:10
*/
public class TestLocalDAteTime {
//1、LocalDate LocalTime LocalDateTime
@Test
public void test() {
//now()方法 获取当前系统时间
LocalDateTime dateTime = LocalDateTime.now();
System.out.println("当前时间:"+dateTime);
LocalDateTime dateTime2 = LocalDateTime.of(2018, 10, 10, 10, 10, 10);
System.out.println("自定义的时间:"+dateTime2);
//对时间的运算
LocalDateTime plusYears = dateTime.plusYears(1);
System.out.println("对当前时间加一年:"+plusYears);
LocalDateTime minusYears = dateTime.minusYears(2);
System.out.println("对当前时间减去两年:"+minusYears);
//get系列
System.out.println("得到当前时间的年:"+dateTime.getYear());
System.out.println("得到当前时间的年月;"+dateTime.getMonth().getValue());
}
}
运行结果:
当前时间:2018-10-25T12:02:21.250
自定义的时间:2018-10-10T10:10:10
对当前时间加一年:2019-10-25T12:02:21.250
对当前时间减去两年:2016-10-25T12:02:21.250
得到当前时间的年:2018
得到当前时间的年月;10
Instant:时间戳(以uninx元年:1970年1月1日00:00:00到某个时间的毫秒值)
//Instant:时间戳(以uninx元年:1970年1月1日00:00:00到某个时间的毫秒值)
@Test
public void test1() {
Instant instant = Instant.now();//默认获取UTC时区,我们是东八区,相差八小时
System.out.println("当前UTC时区的时间:"+instant);
//带偏移量的
OffsetDateTime offset = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println("偏移了8小时的时区的时间"+offset);
//转化成毫秒值
System.out.println("毫秒值:"+instant.toEpochMilli());
//从1970年1月1日00:00:00加了1000毫秒
Instant instant2 =Instant.ofEpochMilli(1000);
System.out.println("从1970年一月一日加上一秒:"+instant2);
}
结果:
当前UTC时区的时间:2018-10-25T04:07:31.595Z
偏移了8小时的时区的时间2018-10-25T12:07:31.595+08:00
毫秒值:1540440451595
从1970年一月一日加上一秒:1970-01-01T00:00:01Z
Duration Period
//Duration:计算两个时间的间隔
//Period:计算两个日期间的间隔
@Test
public void test2() throws Exception {
Instant instant = Instant.now();
Thread.sleep(1000);
Instant instant1 = Instant.now();
Duration duration = Duration.between(instant, instant1);
System.out.println("间隔是"+duration.toMillis()+"毫秒");
System.out.println("=============");
LocalDateTime time = LocalDateTime.now();
Thread.sleep(1000);
LocalDateTime time1 = LocalDateTime.now();
Duration duration1 = Duration.between(time, time1);
System.out.println(duration1.toMillis()+"毫秒");
//两个日期的间隔
LocalDate date = LocalDate.of(2018, 1, 1);
LocalDate date1 = LocalDate.now();
Period period = Period.between(date, date1);
System.out.println("两个日期的间隔是"+period.getYears()+"年"+period.getMonths()+"月"+period.getDays()+"天");
}
运行结果
间隔是1000毫秒
=============
1000毫秒
两个日期的间隔是0年9月24天
TemporalAdjuster:时间校正器
//TemporalAdjuster:时间校正器
@Test
public void test3() throws Exception {
LocalDateTime dateTime =LocalDateTime.now();
System.out.println("当前时间是:"+dateTime);
//把月中的天指定为自己设定的数值
LocalDateTime dayOfMonth = dateTime.withDayOfMonth(10);
System.out.println("自己设定的值:"+dayOfMonth);
//下个周日
TemporalAdjuster adjuster = TemporalAdjusters.next(DayOfWeek.SUNDAY);
LocalDateTime with = dateTime.with(adjuster );
System.out.println("下个周日是"+with);
//也可以自定义(比如下个周日)
LocalDateTime with2 = dateTime.with((l)->{
LocalDateTime dateTime1 =(LocalDateTime)l;
if(dateTime1.equals(DayOfWeek.FRIDAY)) {
return dateTime1.plusDays(3);
}else if(dateTime1.equals(DayOfWeek.SATURDAY)) {
return dateTime1.plusDays(2);
}
else {
return dateTime1.plusDays(1);
}
});
System.out.println("下个工作日是:"+with2);
}
运行结果
当前时间是:2018-10-25T12:11:46.891
自己设定的值:2018-10-10T12:11:46.891
下个周日是2018-10-28T12:11:46.891
下个工作日是:2018-10-26T12:11:46.891
DateTimeFormater:格式化日期时间
//DateTimeFormater:格式化日期时间
@Test
public void test4() throws Exception {
DateTimeFormatter isoDateTime = DateTimeFormatter.ISO_DATE;
LocalDateTime dateTime = LocalDateTime.now();
String format = dateTime.format(isoDateTime);
System.out.println("ISO_DATE格式:"+format);
System.out.println("+++++++++++++++++");
//把时间日期指定为特定格式的字符串形式
DateTimeFormatter isoDateTime1 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
String format2 = dateTime.format(isoDateTime1);
System.out.println("\"ISO_DATE格式:\"+格式"+format2);
System.out.println("+++++++++++++++++");
//解析日期时间(按照特定的格式)
LocalDateTime parse = LocalDateTime.parse(format2, isoDateTime1);
System.out.println("解析后得到时间:"+parse);
}
ZonedDate ZonedDate ZoneDateTime 带时区的操作
//ZonedDate ZonedDate ZoneDateTime 带时区的操作
@Test
public void test5() throws Exception {
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
ZonedDateTime zone = now.atZone(ZoneId.of("Asia/Shanghai"));
System.out.println("上海时区"+zone);
}
运行结果
2018-10-25T12:20:58.861
上海时区2018-10-25T12:20:58.861+08:00[Asia/Shanghai]
Java8新特性——新一套时间API的使用的更多相关文章
- 返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, .net 4.5 带来的更方便的异步操作
原文:返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, ...
- Atitit.mysql 5.0 5.5 5.6 5.7 新特性 新功能
Atitit.mysql 5.0 5.5 5.6 5.7 新特性 新功能 1. MySQL 5.6 5 大新特性1 1.1. 优化器的改进1 1.2. InnoDB 改进1 1.3. 使用 ...
- Atitit. visual studio vs2003 vs2005 vs2008 VS2010 vs2012 vs2015新特性 新功能.doc
Atitit. visual studio vs2003 vs2005 vs2008 VS2010 vs2012 vs2015新特性 新功能.doc 1.1. Visual Studio2 1.2. ...
- Atitit.mysql 5.0 5.5 5.6 5.7 新特性 新功能
Atitit.mysql 5.0 5.5 5.6 5.7 新特性 新功能 1. MySQL 5.6 5 大新特性1 1.1. 优化器的改进1 1.2. InnoDB 改进1 1.3. 使用 ...
- 重新想象 Windows 8.1 Store Apps (88) - 通信的新特性: 新的 HttpClient
[源码下载] 重新想象 Windows 8.1 Store Apps (88) - 通信的新特性: 新的 HttpClient 作者:webabcd 介绍重新想象 Windows 8.1 Store ...
- Atitit.linux 内核 新特性 新功能
Atitit.linux 内核 新特性 新功能 1. Linux 3.2内核新特性 2012-02-12 22:41:471 1.1. EXT4:支持更大的块2 1.2. BTRFS:更快的数据清理 ...
- Java8新特性第3章(Stream API)
Stream作为Java8的新特性之一,他与Java IO包中的InputStream和OutputStream完全不是一个概念.Java8中的Stream是对集合功能的一种增强,主要用于对集合对象进 ...
- 【java8新特性】日期和时间
Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本. Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程,新的 JavaScript ...
- 【java】JDK1.8时间日期库 新特性 所有java中时间Date的使用
除了lambda表达式,stream以及几个小的改进之外,Java 8还引入了一套全新的时间日期API,在本篇教程中我们将通过几个简单的任务示例来学习如何使用java 8的这套API.Java对日期, ...
- Java11新特性 - 新加一些实用的API
1. 新的本机不可修改集合API 自从Java9开始,JDK里面为集合(List/Set/Map)都添加了of和copyOf方法,他们可以来创建不可变的集合. Question1:什么叫做不可变集合? ...
随机推荐
- go-数据结构
数据结构 数据结构(算法)的介绍 数据结构的介绍 1) 数据结构是一门研究算法的学科,只从有了编程语言也就有了数据结构.学好数据结构可以编写 出更加漂亮,更加有效率的代码. 2) 要学习好数据结构就要 ...
- JQ中的Ajax的封装
1.认识JQ中ajax的封装 jQ 对于ajax的封装有两层实现:$.ajax 为底层封装实现:基于 $.ajax ,分别实现了$.get 与$.post 的高层封装实现: 2.Ajax的底 ...
- liunx简单命令
mysql -h主机地址 -u用户名 -p用户密码 --进入数据库1.显示数据库列表. show databases; 2.显示库中的数据表: use mysql: //打开库 show tables ...
- Linux常用命令(2)
3.帮助命令 A,帮助命令:man B,其他帮助命令 3.1,格式:man [命令名] 查看命令拥有哪个级别的帮助: ...
- java基础第十五篇之IO流和递归算法
FileInputStream : 输入流 int available() : 一次读取所有的字节数 read() : 将文件上的字节读取到内存的数组中 FileOutputStream : 输出流 ...
- PHP配置篇(一)--php开启redis扩展
因为最近要用到Redis,下面记录下如何给PHP开启redis的扩展. 一.安装redis 1.安装redis:https://github.com/MSOpenTech/redis/releases ...
- Git入门基础教程和SourceTree应用
目录 一.Git的安装 1.1 图形化界面 1.2 命令行界面 二.本地仓库的创建与提交 2.1 图形化界面 2.1.1 首先在电脑上有一个空白目录 2.1.2 打开SourceTree 2.1.3 ...
- Shell命令-系统信息及显示之free、cal
文件及内容处理 - free.cal 1. free:查看系统内存 free命令的功能说明 free 命令用于显示内存状态.free 指令会显示内存的使用情况,包括实体内存,虚拟的交换文件内存,共享内 ...
- day53_9_17 django数据库表关联,路由和视图
一.数据库的关系建立. 在原生的数据库语句中,建立表与表之间的联系,就是添加一个字段,将联系的表的id值添加到该字段中. django所作的也就是这些. 以图书管理系统为例,图书管理系统有四张表:书籍 ...
- java(android)命名规范
在讲解命名规范前,先初略介绍下当前主要的标识符命名法和英文缩写规则. 标识符命名法标识符命名法最要有四种: 1 驼峰(Camel)命名法:又称小驼峰命名法,除首单词外,其余所有单词的第一个字母大写. ...