1. 概述

1.1 简介

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

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

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

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

1.3 环境

2. LocalDate、LocalTime、LocalDateTime

LocalDateLocalTimeLocalDateTime 三者的使用方式基本一致,所以我们这里就以 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. 2017NOIP初赛游记

    前天晚上,玩三国杀,玩到了昨天凌晨2点40多分吧,我觉得初赛要爆炸了, 不得不吐槽一下,三国杀的武将太少了. 昨天是初赛的日子,上午8点多来了后看了看阅读程序和程序填空,复习了以下理论知识和wsj 然 ...

  2. LA 4973异面线段

    题目大意:给两条线段求他们间的最小距离的平方(以分数形式输出). 贴个模版吧!太抽象了. #include<cstdio> #include<cmath> #include&l ...

  3. Tarjan 算法 自学整理

    算法介绍 如果两个顶点可以相互通达,则称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强连通子图,称为强连通分量( ...

  4. Codeforces 432D Prefixes and Suffixes kmp

    手动转田神的大作:http://blog.csdn.net/tc_to_top/article/details/38793973 D. Prefixes and Suffixes time limit ...

  5. ci框架——数据库(增删改查)

    1:配置数据库(application/config/database.php)修改 $db['default'] = array( 'dsn' => '', 'hostname' => ...

  6. android自定义Activity窗体大小

    先给大家看图吧: 看,是不是很酷呢,呵呵. 这里我说关键的地方,就是自定义Activity的窗体大小. 这个登录框它不是一个Dialog,而是一个Activity. 如何定义,即把Activity的主 ...

  7. Elasticsearch使用syslog发送Watcher告警事件

    https://blog.csdn.net/mvpboss1004/article/details/70158864?locationNum=9&fps=1

  8. raspi集成库及安装

    原文:http://blog.csdn.net/xukai871105/article/details/12684617   树莓派来自国外,国外嵌入式开源领域具有良好的分享精神,树莓派各种集成库也层 ...

  9. IntelliJ IDEA出现:This file is indented with tabs instead of 4 spaces的问题解决

    根据阿里巴巴Java开发手册,不能使用Tab字符,改成4个字符,设置如下: 注意:是不选择! 一定要选择这个:

  10. BroadcastReceiver详解(二)

    BroadCastReceiver 简介 (末尾有源码) BroadCastReceiver 源码位于: framework/base/core/java/android.content.Broadc ...