Java 8 新的时间日期 API
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的更多相关文章
- Java 8新的时间日期库的20个使用示例
原文链接 作者:Javin Paul 译者:之诸暇 除了lambda表达式,stream以及几个小的改进之外,Java 8还引入了一套全新的时间日期API,在本篇教程中我们将通过几个简单的任务示例来学 ...
- Java 8新的时间日期库,这二十个案例看完你还学不会算我的!!!
Java对日期,日历及时间的处理一直以来都饱受诟病,尤其是它决定将java.util.Date定义为可修改的以及将SimpleDateFormat实现成非线程安全的.看来Java已经意识到需要为时间及 ...
- JAVA8学习——新的时间日期API&Java8总结
JAVA8-时间日期API java8之前用过的时间日期类. Date Calendar SimpleDateFormat 有很多致命的问题. 1.没有时区概念 2.计算麻烦,实现困难 3.类是可变的 ...
- java8新特性——时间日期API
传统的时间 API 存在线程安全的问题,在多线程开发中必须要上锁,所以 java8 现在为我们提供了一套全新的时间日期 API ,今天进来学习一下java8 的时间日期 API. 一.使用 Local ...
- 【java】JDK1.8时间日期库 新特性 所有java中时间Date的使用
除了lambda表达式,stream以及几个小的改进之外,Java 8还引入了一套全新的时间日期API,在本篇教程中我们将通过几个简单的任务示例来学习如何使用java 8的这套API.Java对日期, ...
- Java8新特性时间日期库DateTime API及示例
Java8新特性的功能已经更新了不少篇幅了,今天重点讲解时间日期库中DateTime相关处理.同样的,如果你现在依旧在项目中使用传统Date.Calendar和SimpleDateFormat等API ...
- java8新的时间日期库及使用示例
转自:https://www.cnblogs.com/comeboo/p/5378922.html 来自:Java译站 链接:http://it.deepinmind.com/java/2015/03 ...
- Java 8 的时间日期 API
上一篇文章『Java 的时间日期 API』中,我们学习了由 Date.Calendar,DateFormat 等组成的「传统时间日期 API」,但是传统的处理接口设计并不是很友好,不易使用.终于,Ja ...
- Java8新特性(三)——Optional类、接口方法与新时间日期API
一.Optional容器类 这是一个可以为null的容器对象.如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象. 查看结构图可以看到有如下常用方法: of(T)—— ...
随机推荐
- 浅谈Oracle数据库分区表
Oracle数据库分区是作为Oracle数据库性能优化的一种重要的手段和方法,之前,只听过分区的大名,却总未用过,最近简单学习了一下,总结如下,不对之处,还希望朋友们多多指点,交流! 1.表空间及分区 ...
- 程序自动分析(codevs 4600)
题目描述 Description 在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足. 考虑一个约束满足问题的简化版本:假设x1,x2,x3,…代表程序中出现的变量,给定n个形如xi ...
- 页面中用Context.Handler传递
最近被WCF弄得身心疲惫.今天抽空看了一下页面传值的一些技巧.传统的cookie session 什么的就不介绍了 今天介绍Context的用法 首先要应用using System.Runtim ...
- android 完美退出应用程序。
Android 程序在点击回退键时,如果只有一个activity,调用finish()方法就能退出界面,如果有多个界面,在调用该方法时,只会销毁当前的activity,显示栈顶的其它activity, ...
- LeetCode OJ--Valid Parentheses
http://oj.leetcode.com/problems/valid-parentheses/ 对栈的考察,看括号的使用方式是否合法. class Solution { public: bool ...
- 解决三星 BIOS 模式没有 Fast Bios Mode选项 U盘动项问题
今天想分下盘,进入biso竟然没有网上说 Fast Bios Mode选项,最后自己误打误撞竟然设置成功了,太不可思议了官方这么说:开机按F2进入BIOS设置,找到Boot选项下Boot Device ...
- 某考试 T1 function
(数据范围 n<=10^9 ,T<=10 ) 首先,我来证明一下 Σμ(d) * σ(i/d)^2 = σ(i^2) 相信做过约数个数和的童鞋都可以完成从右式推到左式,那么我现在就说一下怎 ...
- 3.JAVA语言基础部分—Class类与反射
什么是Java反射机制? JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的以及动态调用对象的方法的功能称为 ...
- 使用Swagger生成Spring Boot REST客户端(支持Feign)(待实践)
如果项目上使用了Swagger做RESTful的文档,那么也可以通过Swagger提供的代码生成器生成客户端代码,同时支持Feign客户端. 但是经过测试,生成Feign代码和REST客户端有些臃肿. ...
- (二)《机器学习》(周志华)第4章 决策树 笔记 理论及实现——“西瓜树”——CART决策树
CART决策树 (一)<机器学习>(周志华)第4章 决策树 笔记 理论及实现——“西瓜树” 参照上一篇ID3算法实现的决策树(点击上面链接直达),进一步实现CART决策树. 其实只需要改动 ...