1. 概述

1.1 简介

Java 8 引入了一套全新的时间日期API,操作起来更简便。简单介绍下,LocalDate和LocalTime和LocalDateTime的使用;

java.util.Date月份从0开始,java.time.LocalDate月份从1开始并且提供了枚举。

java.util.Date和SimpleDateFormatter都不是线程安全的,而LocalDate和LocalTime和最基本的String一样,是不变类型,不但线程安全,而且不能修改,它们分别使用 ISO-8601 日历系统的日期和时间,它们提供了简单的日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。

注 : ISO-8601 日历系统是国际标准化组织制定的现代公民的日期和时间的表示法

1.3 环境

2. LocalDate、LocalTime、LocalDateTime

LocalDate、LocalTime、LocalDateTime 三者的使用方式基本一致,所以我们这里就以 LocalDateTime 为例进行索命

2.1 实例

@Test
public void t1() {
// 获取当前时间
LocalDateTime ldt1 = LocalDateTime.now();
System.out.println(ldt1); // 获取指定的时间
LocalDateTime ldt2 = LocalDateTime.of(2018, 12, 10, 10, 10, 10);
System.out.println(ldt2); // 加两年
LocalDateTime ldt3 = ldt1.plusYears(2);
System.out.println(ldt3); // 减两个月
LocalDateTime ldt4 = ldt1.minusYears(2);
System.out.println(ldt4); // 获取年月日时分秒
System.out.println(ldt1.getYear());
System.out.println(ldt1.getMonthValue());
System.out.println(ldt1.getDayOfMonth());
System.out.println(ldt1.getHour());
System.out.println(ldt1.getMinute());
System.out.println(ldt1.getSecond());
}

2.2 Instant : 时间戳

使用 Unix 元年 1970年1月1日 00:00:00 所经历的毫秒值

@Test
public void t2() {
Instant ins = Instant.now(); //默认使用 UTC 时区
System.out.println(ins); // 时间偏移量
OffsetDateTime odt = ins.atOffset(ZoneOffset.ofHours(8));
System.out.println(odt); // 获取毫秒值
System.out.println(ins.getNano()); // 对于元年开始进行运算
Instant ins2 = Instant.ofEpochSecond(60);
System.out.println(ins2);
}

2.3 Duration : 用于计算两个“时间”间隔

@Test
public void t3() throws InterruptedException {
// 时间戳
Instant ins1 = Instant.now(); Thread.sleep(1000); Instant ins2 = Instant.now();
Duration duration = Duration.between(ins1, ins2);
System.out.println("所耗费时间为:" + duration.toMillis()); System.out.println("--------------------------------"); // LocalTime
LocalTime lt1 = LocalTime.now(); Thread.sleep(1000); LocalTime lt2 = LocalTime.now(); System.out.println("所耗费时间为:" + Duration.between(lt1, lt2).toMillis());
}

2.4 Period : 用于计算两个“日期”间隔

@Test
public void t5() {
LocalDate ld1 = LocalDate.of(2017, 1, 1);
LocalDate ld2 = LocalDate.now();
Period period = Period.between(ld1, ld2);
System.out.println("相差" + period.getYears() + "年" + period.getMonths() + "月" + period.getDays() + "天");
}

2.5 日期的操作

TemporalAdjuster 时间校正器,有时我们可能需要获取例如:将日期调整到下个周日等操作。

TemporalAdjusters 该类通过静态方法提供了大量的常用 TemporalAdjuster 的实现。

@Test
public void t6() {
LocalDateTime ldt = LocalDateTime.now(); // 指定这个月的一个固定日期
LocalDateTime ldt2 = ldt.withDayOfMonth(10);
System.out.println(ldt2); // 获取下个周日
LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println("获取下个周日 : " + ldt3); // 自定义:获取下个工作日
LocalDateTime ldt5 = ldt.with((l) -> {
LocalDateTime ldt6 = (LocalDateTime) l;
DayOfWeek dayOfWeek = ldt6.getDayOfWeek(); if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {
return ldt6.plusDays(3);
} else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {
return ldt6.plusDays(2);
} else {
return ldt6.plusDays(1);
}
});
System.out.println("获取下个工作日 : " + ldt5);
}

3. DateTimeFormatter

3.1 简介

在 JDK 1.8 中可以使用 DateTimeFormatter 来代替 SimpleDateFormat 进行日期的格式化,而且 DateTimeFormatter 是线程安全的

3.2 实例

@Test
public void t8() {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime ldt = LocalDateTime.now(); // 将日期格式化为字符串,两种方式否可以
String dtfDate = dtf.format(ldt);
String ldtDate = ldt.format(dtf);
System.out.println("dtfDate : " + dtfDate);
System.out.println("ldtDate : " + ldtDate); // 将字符串格式化为 LocalDateTime
LocalDateTime ldt2 = LocalDateTime.parse(dtfDate, dtf);
System.out.println("时间为 : " + ldt2);
}

3.3 线程安全

在多线程使用 SimpleDateFormat 进行格式化日期的时候会有线程安全问题。

@Test
public void t1() throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Callable<Date> task = new Callable<Date>() {
@Override
public Date call() throws Exception {
return sdf.parse("2018-12-10");
}
}; ExecutorService executor = Executors.newFixedThreadPool(10);
List<Future<Date>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(executor.submit(task));
} for (Future<Date> future : results) {
System.out.println(future.get());
}
executor.shutdown();
}

可以使用 ThreadLocal 的锁解决 SimpleDateFormat 的线程安全问题

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; public class DateFormatThreadLocal {
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
}; public static final Date convert(String source) throws ParseException {
return df.get().parse(source);
}
}

测试方法

@Test
public void t2() throws Exception {
Callable<Date> task = new Callable<Date>() {
@Override
public Date call() throws Exception {
return DateFormatThreadLocal.convert("2018-12-10");
}
}; ExecutorService executor = Executors.newFixedThreadPool(10);
List<Future<Date>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(executor.submit(task));
} for (Future<Date> future : results) {
System.out.println(future.get());
}
executor.shutdown();
}

使用 DateTimeFormatter 进行格式化,DateTimeFormatter 是线程安全的

@Test
public void t3() throws Exception {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd"); Callable<LocalDate> task = new Callable<LocalDate>() {
@Override
public LocalDate call() throws Exception {
return LocalDate.parse("2018-12-10",dtf);
}
}; ExecutorService executor = Executors.newFixedThreadPool(10);
List<Future<LocalDate>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(executor.submit(task));
} for (Future<LocalDate> future : results) {
System.out.println(future.get());
}
executor.shutdown();
}

4. 时区设置

@Test
public void t2() {
LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println(ldt); // 带时区的时间
ZonedDateTime zdt = ldt.atZone(ZoneId.of("Asia/Shanghai"));
System.out.println(zdt);
}

本文首发于凌风博客:Java 8 新的时间日期 API
作者:凌风

Java 8 新的时间日期 API的更多相关文章

  1. Java 8新的时间日期库的20个使用示例

    原文链接 作者:Javin Paul 译者:之诸暇 除了lambda表达式,stream以及几个小的改进之外,Java 8还引入了一套全新的时间日期API,在本篇教程中我们将通过几个简单的任务示例来学 ...

  2. Java 8新的时间日期库,这二十个案例看完你还学不会算我的!!!

    Java对日期,日历及时间的处理一直以来都饱受诟病,尤其是它决定将java.util.Date定义为可修改的以及将SimpleDateFormat实现成非线程安全的.看来Java已经意识到需要为时间及 ...

  3. JAVA8学习——新的时间日期API&Java8总结

    JAVA8-时间日期API java8之前用过的时间日期类. Date Calendar SimpleDateFormat 有很多致命的问题. 1.没有时区概念 2.计算麻烦,实现困难 3.类是可变的 ...

  4. java8新特性——时间日期API

    传统的时间 API 存在线程安全的问题,在多线程开发中必须要上锁,所以 java8 现在为我们提供了一套全新的时间日期 API ,今天进来学习一下java8 的时间日期 API. 一.使用 Local ...

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

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

  6. Java8新特性时间日期库DateTime API及示例

    Java8新特性的功能已经更新了不少篇幅了,今天重点讲解时间日期库中DateTime相关处理.同样的,如果你现在依旧在项目中使用传统Date.Calendar和SimpleDateFormat等API ...

  7. java8新的时间日期库及使用示例

    转自:https://www.cnblogs.com/comeboo/p/5378922.html 来自:Java译站 链接:http://it.deepinmind.com/java/2015/03 ...

  8. Java 8 的时间日期 API

    上一篇文章『Java 的时间日期 API』中,我们学习了由 Date.Calendar,DateFormat 等组成的「传统时间日期 API」,但是传统的处理接口设计并不是很友好,不易使用.终于,Ja ...

  9. Java8新特性(三)——Optional类、接口方法与新时间日期API

    一.Optional容器类 这是一个可以为null的容器对象.如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象. 查看结构图可以看到有如下常用方法: of(T)—— ...

随机推荐

  1. Mysql字符集与校对规则

    字符集是一套字符和编码的集合,校对规则是用于比较字符集的一套规则. 所以字符集有两部分组成字符集合和对应的编码集合.比如说,现在有这几个字符:A B a b, 假设它们对应的编码分别是00, 01, ...

  2. java面

    常被问到的十个 Java 面试题 每周 10 道 Java 面试题 : 面向对象, 类加载器, JDBC, Spring 基础概念 Java 面试题问与答:编译时与运行时 java面试基础1 java ...

  3. alibaba/fastjson 之 JSONPath

    JOSNPath 是一个非常强大的工具,对于处理 json 对象非常方便. 官方地址:https://github.com/alibaba/fastjson/wiki/JSONPath 基本用法:ht ...

  4. JDBC自定义连接池

    开发中,"获得连接"和"释放资源"是非常消耗系统资源的,为了解决此类性能问题可以采用连接池技术来共享连接Connection. 1.概述 用池来管理Connec ...

  5. Centos7 下安装 RabbitMQ

    安装 erlang 1.下载erlang 官网地址 http://www.erlang.org/download 挑选合适的版本 然后 wget 比如目前最新版本 19.3 运行命令 wget htt ...

  6. Oracle EBS - 工单状态

    Job status update 1. Job的几种状态 unreleased --未核发 released--已核发 complete --完成 complete no charges--完成不计 ...

  7. CentOS 5.5下搭建部署独立SVN服务器全程详解

    SVN服务器有2种运行方式:1.独立服务器 (例如:svn://xxx.com/xxx):2.借助apache   (例如:http://svn.xxx.com/xxx):为了不依赖apache,我选 ...

  8. 【转载】lvs为何不能完全替代DNS轮询

    上一篇文章"一分钟了解负载均衡的一切"引起了不少同学的关注,评论中大家争论的比较多的一个技术点是接入层负载均衡技术,部分同学持这样的观点: 1)nginx前端加入lvs和keepa ...

  9. Elasticsearch 之 慘痛部署(分片移位)

    部署说明 硬件 server两台: 机器A:64G内存 机器B:32G内存 分片 共12个节点 2个查询节点.10个存储节点 8个主分片 1个复制分片(每一个分片都有一个副本分布在不同的节点上面) 每 ...

  10. windows核心编程之进程间共享数据

    有时候我们会遇到window进程间共享数据的需求,例如说我想知道系统当前有多少某个进程的实例. 我们能够在程序中定义一个全局变量.初始化为0.每当程序启动后就加1.当然我们我们能够借助第三方介质来储存 ...