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的使用的更多相关文章

  1. 返璞归真 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 上传文件, ...

  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. 使用 ...

  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. ...

  4. 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. 使用 ...

  5. 重新想象 Windows 8.1 Store Apps (88) - 通信的新特性: 新的 HttpClient

    [源码下载] 重新想象 Windows 8.1 Store Apps (88) - 通信的新特性: 新的 HttpClient 作者:webabcd 介绍重新想象 Windows 8.1 Store ...

  6. Atitit.linux 内核 新特性 新功能

    Atitit.linux 内核 新特性 新功能 1.  Linux 3.2内核新特性 2012-02-12 22:41:471 1.1. EXT4:支持更大的块2 1.2. BTRFS:更快的数据清理 ...

  7. Java8新特性第3章(Stream API)

    Stream作为Java8的新特性之一,他与Java IO包中的InputStream和OutputStream完全不是一个概念.Java8中的Stream是对集合功能的一种增强,主要用于对集合对象进 ...

  8. 【java8新特性】日期和时间

    Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本. Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程,新的 JavaScript ...

  9. 【java】JDK1.8时间日期库 新特性 所有java中时间Date的使用

    除了lambda表达式,stream以及几个小的改进之外,Java 8还引入了一套全新的时间日期API,在本篇教程中我们将通过几个简单的任务示例来学习如何使用java 8的这套API.Java对日期, ...

  10. Java11新特性 - 新加一些实用的API

    1. 新的本机不可修改集合API 自从Java9开始,JDK里面为集合(List/Set/Map)都添加了of和copyOf方法,他们可以来创建不可变的集合. Question1:什么叫做不可变集合? ...

随机推荐

  1. Python中执行系统命令的四种方法

    一.os.system方法 在子终端运行系统命令,可以获取命令执行后的返回信息以及执行返回的状态.执行后返回两行结果,第一行是结果, 第二行是执行状态信息,如果命令成功执行,这条语句返回0,否则返回1 ...

  2. Python中断多重循环的几种思路

    I. 跳出单循环 不管是什么编程语言,都有可能会有跳出循环的需求,比如枚举时,找到一个满足条件的数就终止.跳出单循环是很简单的,比如 for i in range(10): if i > 5: ...

  3. Python爬取6271家死亡公司数据,看十年创业公司消亡史

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 朱小五 凹凸玩数据 PS:如有需要Python学习资料的小伙伴可以加 ...

  4. Java生鲜电商平台-SpringCloud微服务开发中的数据架构设计实战精讲

    Java生鲜电商平台-SpringCloud微服务开发中的数据架构设计实战精讲 Java生鲜电商平台:   微服务是当前非常流行的技术框架,通过服务的小型化.原子化以及分布式架构的弹性伸缩和高可用性, ...

  5. Java生鲜电商平台-API请求性能调优与性能监控

    Java生鲜电商平台-API请求性能调优与性能监控 背景 在做性能分析时,API的执行时间是一个显著的指标,这里使用SpringBoot AOP的方式,通过对接口添加简单注解的方式来打印API的执行时 ...

  6. sqlserver 问题来了,视图不会自动更新,如果是用*创建的

    奇葩问题一个 create view时候用的select * 关联了几个表创建的. 后修改select *  的表,结果悲剧了. select * from 视图得到的结果绝对让你想哭.不报错,不提示 ...

  7. 【转载】更简单的学习Android事件分发

    事件分发是Android中非常重要的机制,是用户与界面交互的基础.这篇文章将通过示例打印出的Log,绘制出事件分发的流程图,让大家更容易的去理解Android的事件分发机制. 一.必要的基础知识 1. ...

  8. [转]Eclipse插件开发之基础篇(6) SWT简介

    原文地址:http://www.cnblogs.com/liuzhuo/archive/2010/09/01/eclipse_plugin_1_3_1.html SWT(Standard Widget ...

  9. git零基础快速入门实战,重点讲解,在实际生产中整合idea对版本、分支的管理等

    1.什么是版本管理 (多人协作)项目中常见的问题: 代码放在什么地方 ?? 同步(到服务器),代码的冲突问题 ?? 服务器访问权限问题 ?? (代码)服务器内容修改的细节 ?? 项目版本的发布 ?? ...

  10. Event事件、进程池与线程池、协程

    目录 Event事件 进程池与线程池 多线程爬取梨视频 协程 协程目的 gevent TCP服务端socket套接字实现协程 Event事件 用来控制线程的执行 出现e.wait(),就会把这个线程设 ...