Java8 日期API
简介
java8推出了一套全新的日期API,为什么要再出一套API呢,那是因为,之前的日期操作不是线程安全的,是可变的。Java8时间相关类在java.time包路径下,新的日期API之所有线程安全,是因为全新的日期操作都会返回一个新的对象实例,所有安全。
简单实用
LocalDate、LocalTime、LocalDateTime
LocalDate、LocalTime、LocalDateTime 类的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。它们提供
了简单的日期或时间,并不包含当前的时间信
息。也不包含与时区相关的信息。
这三个类都是由 final 修饰
获取当前时间
//获取当前时间
LocalDateTime now = LocalDateTime.now();
System.out.println(now);// 2021-03-18T20:49:40.549
获取指定日期,包括年月日时分秒
//指定 年月日时分秒
LocalDateTime ldt = LocalDateTime.of(2021, 3, 20, 12, 12,12);
System.out.println(ldt);// 2021-03-20T12:12:12
方法修饰符及返回值 | 方法名称及参数 | 方法说明 |
---|---|---|
static LocalDateTime | of(int year, int month, int dayOfMonth, int hour, int minute) | 从年,月,日,小时和分钟获得 LocalDateTime的实例,将秒和纳秒设置为零 |
static LocalDateTime | of(int year, int month, int dayOfMonth, int hour, int minute, int second) | 从年,月,日,小时,分钟和秒获得 LocalDateTime的实例,将纳秒设置为零 |
static LocalDateTime | of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond) | 从年,月,日,小时,分钟和秒以及纳秒获得 LocalDateTime的实例 |
static LocalDateTime | of(int year, Month month, int dayOfMonth, int hour, int minute) | 从年,月,日,小时和分钟获得 LocalDateTime的实例,将秒和纳秒设置为零 |
static LocalDateTime | of(int year, Month month, int dayOfMonth, int hour, int minute, int second) | 从年,月,日,小时,分钟和秒获得 LocalDateTime的实例,将纳秒设置为零 |
static LocalDateTime | of(int year, Month month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond) | 从年,月,日,小时,分钟和秒以及纳秒获得 LocalDateTime的实例 |
对时间的加减操作
//获取当前时间
LocalDateTime now = LocalDateTime.now();
System.out.println(now);// 2021-03-18T21:12:07.982
LocalDateTime plusYears = now.plusYears(1);
System.out.println(plusYears);//2022-03-18T21:12:07.982
方法修饰符及返回值 | 方法名称及参数 | 方法说明 |
---|---|---|
LocalDateTime | plus(long amountToAdd, TemporalUnit unit) | amountToAdd:要增加的数值 TemporalUnit :单位,可以参考java.time.temporal.ChronoUnit枚举 |
LocalDateTime | plusDays(long days) | 加多少天 |
LocalDateTime | plusHours(long hours) | 加多少秒 |
LocalDateTime | plusMinutes(long minutes) | 加多少分钟 |
LocalDateTime | plusMonths(long months) | 加几个月 |
LocalDateTime | plusWeeks(long weeks) | 加多少星期 |
LocalDateTime | plusYears(long years) | 加多少年 |
同理还有对应的减日期的操作
minusxxx方法,这里就不一一列举了。
得到具体的年月日…
方法修饰符及返回值 | 方法名称及参数 | 方法说明 |
---|---|---|
int | get(TemporalField field) | 获取指定字段的值,TemporalField的实现类,参考java.time.temporal.ChronoField |
int | getYear() | 获取年份 |
Month | getMonth() | 使用 Month枚举获取月份字段 |
int | getMonthValue() | 月份 1 到 12 |
int | getDayOfMonth() | 获取 日 1到 31 |
int | getDayOfYear() | 一年中的第几天 |
DayOfWeek | getDayOfWeek() | 星期几 |
int | getHour() | 时 |
int | getMinute() | 分 |
int | getSecond() | 秒 |
修改时间
方法修饰符及返回值 | 方法名称及参数 | 方法说明 |
---|---|---|
LocalDateTime | withDayOfYear(int dayOfYear) | 修改 day 字段 |
LocalDateTime | withHour(int hour) | 修改H字段 |
… | … | … |
//获取当前时间
LocalDateTime now = LocalDateTime.now();
System.out.println(now);// 2021-03-18T21:43:46.373
System.out.println("年份: " + now.getYear());// 年份: 2021
System.out.println("月份: " + now.getMonth());//月份: MARCH
System.out.println("月份: " + now.getMonthValue());// 月份: 3
System.out.println("日: " + now.getDayOfMonth());// 日: 18
System.out.println("日: " + now.getDayOfYear());// 日: 77
System.out.println("星期 : " + now.getDayOfWeek());// 日: THURSDAY
System.out.println("时: " + now.getHour());// 时: 21
System.out.println("分: " + now.getMinute());// 分: 43
System.out.println("秒: " + now.getSecond());//秒: 46
Instant
Instant 时间戳
它是以Unix元年 1970年1月1日 00:00:00 到某时间的毫秒值。
获取当前时间戳
Instant instant = Instant.now();
System.out.println(instant);//2021-03-18T14:01:53.068Z
注意: 输出 2021-03-18T14:01:53.068Z ,但是系统时间为22:01:53
因为 输出的是UTC时间,北京时间需要在此基础上加8个小时,相差8个时区
进行偏移量计算
Instant instant = Instant.now();
System.out.println(instant); //2021-03-18T14:18:38.049Z
OffsetDateTime atOffset = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(atOffset); //2021-03-18T22:18:38.049+08:00
//获取纳秒
System.out.println(instant.getNano());//49000000
//指定 时间戳,1970年1月1日0时0分0秒开始,加上3600秒(1个小时)
System.out.println(instant.ofEpochSecond(3600));//1970-01-01T01:00:00Z
方法修饰符及返回值 | 方法名称及参数 | 方法说明 |
---|---|---|
long | toEpochMilli() | 1970-01-01T00:00:00Z到此时间戳的毫秒值 |
long | getEpochSecond() | 1970-01-01T00:00:00Z到此时间戳的秒数 |
int | getNano() | 获取 2021-03-18T14:18:38.049Z 秒后面的049Z的纳秒值 |
static Instant | ofEpochSecond(long epochSecond) | 从1970-01-01T00:00:00Z开始,加上指定的秒数获得一个 Instant的实例 |
Duration & Period
Duration是计算 两个 “时间” 之间的间隔
Period 是计算 两个 “日期” 之间的间隔
Instant instant1 = Instant.now();
Thread.sleep(3000);
Instant instant2 = Instant.now();
Duration between = Duration.between(instant1, instant2);
System.out.println(between);// PT3.011S
//获取 秒
System.out.println(between.getSeconds());// 3
//获取毫秒
System.out.println(between.toMillis());// 3011
//获取纳秒
System.out.println(between.getNano());//11000000
LocalDate ld1 = LocalDate.of(2021, 3, 18);
LocalDate ld2 = LocalDate.of(2022, 4, 19);
Period between = Period.between(ld1, ld2);
System.out.println(between);// P1Y1M1D 相差 1年 1月 1日
System.out.println(between.getYears());//1
System.out.println(between.getMonths());//1
System.out.println(between.getDays());//1
时间调整
TemporalAdjuster : 时间校正器。
有时我们可能需要获取例如:将日期调整到“下个周日”等操作
TemporalAdjusters: 该类通过静态方法提供了大量的常
用 TemporalAdjuster 的实现
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);// 2021-03-18T23:36:49.352
LocalDateTime ldt2 = ldt.withMonth(5);
System.out.println(ldt2);// 2021-05-18T23:36:49.352
//下一个 周一,当前日期为 2021年03月18日,星期四
LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
System.out.println(ldt3);// 2021-03-22T23:36:49.352
//自定义,下一个工作日
LocalDateTime ldt4 = ldt.with((temporal) -> {
LocalDateTime localDateTime = (LocalDateTime) temporal;
DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();//获取星期几
if(dayOfWeek.equals(DayOfWeek.FRIDAY)) {// 周五,下一个工作日 加3天
return localDateTime.plusDays(3);
}else if(dayOfWeek.equals(DayOfWeek.SATURDAY)) {
return localDateTime.plusDays(2);
}else {
return localDateTime.plusDays(1);
}
});
System.out.println(ldt4);// 2021-03-19T23:36:49.352
带时区的日期
ZonedDateTime 用来表示带时区信息的日期。
一个时区ID,如Europe/Paris
ZoneId用于识别用于在Instant和LocalDateTime之间转换的规则。
时区ID
该ID在系统内是唯一的。 有三种类型的ID。
最简单的ID是ZoneOffset 。 这由“Z”和以“+”或“ - ”开头的ID组成。
下一种类型的ID是具有某些形式的前缀的偏移样式ID,例如“GMT + 2”或“UTC + 01:00”。 识别的前缀是“UTC”,“GMT”和“UT”。 偏移量是后缀,在创建过程中将被归一化。 这些ID可以归一ZoneOffset使用normalized() 。
第三种类型的ID是基于区域的ID。 基于区域的ID必须为两个或更多个字符,而不是以“UTC”,“GMT”,“UT”+“或” - “开头。 基于区域的ID由配置定义,请参见ZoneRulesProvider 。 配置重点是提供从ID到底层的查找ZoneRules
时区规则由政府界定,频繁变化。 有一些组织,这里被称为组,监视时区更改并整理它们。 默认组是IANA时区数据库(TZDB)。 其他组织包括国际航协(航空业机构)和微软。
方法修饰符及方法返回值 | 方法名称及参数 | 方法说明 |
---|---|---|
static Set | getAvailableZoneIds() | 获取所有可用的时区ID |
static ZoneId | of(String zoneId) | zoneId可以参考 getAvailableZoneIds 返回集合里面的值 |
获取当前时间(指定时区)
LocalDateTime sh = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));//上海
LocalDateTime tokyo = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));//东京
System.out.println(sh); // 上海时间: 2021-03-19T11:59:44.378
System.out.println(tokyo); // 东京时间: 2021-03-19T12:59:44.378
显示时区信息
LocalDateTime tokyo = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));//东京
System.out.println("东京时间: " + tokyo);
LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));
ZonedDateTime atZone = ldt.atZone(ZoneId.of("Asia/Tokyo"));
System.out.println("东京时间: " + atZone);
东京时间: 2021-03-19T13:27:03.599
东京时间: 2021-03-19T13:27:03.599+09:00[Asia/Tokyo]
注意:
LocalDateTime ldt = LocalDateTime.now(ZoneId.of(“Asia/Tokyo”));
ZonedDateTime atZone = ldt.atZone(ZoneId.of(“Asia/Tokyo”));
这里在构建时间时必须指定相同的时区
DateTimeFormatter 日期格式化
日期转字符串
DateTimeFormatter类已经写好了很多日期格式
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_DATE;
LocalDateTime ldt = LocalDateTime.now();
String format = ldt.format(dateTimeFormatter);
System.out.println("格式化前: " + ldt);// 格式化前: 2021-03-19T11:19:35.369
System.out.println("格式化后: " +format);//格式化后: 2021-03-19
自定义格式
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_DATE;
LocalDateTime ldt = LocalDateTime.now();
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
String format2 = ldt.format(pattern);
System.out.println(format2); // 2021/03/19 11:19:35
字符串转日期
LocalDateTime ldt = LocalDateTime.now();
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
String format2 = ldt.format(pattern);
System.out.println(format2);// 2021/03/19 11:19:35
LocalDateTime parse = ldt.parse(format2,pattern);
System.out.println(parse);// 2021-03-19T11:19:35
注意: 将字符串转日期使,parse方法如果不传格式化匹配器的话,默认是按照ISO 8601标准格式(类似 2021-03-19T11:19:35 )去转换
时间转换
//时间戳 转 LocalDateTime
Instant instant = Instant.now();
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
System.out.println(ldt);
//时间戳转时区时间
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
System.out.println(zonedDateTime);
//LocalDateTime 转时间戳 因为LocalDateTime不带时区信息,因此需要指定当前时区到UTC的offset
Instant instant2 = ldt.toInstant(ZoneOffset.ofHours(8));
System.out.println(instant2);
//时区时间转时间戳 ZonedDateTime自带时区信息
Instant instant3 = zonedDateTime.toInstant();
System.out.println(instant3);
// LocalDateTime转时区时间(为时间加上时区信息)
ZonedDateTime zonedDateTime2 = ZonedDateTime.of(ldt, ZoneId.systemDefault());
//ZonedDateTime atZone = ldt.atZone(ZoneId.systemDefault()); 也可以使用这种方式
//System.out.println(atZone);
System.out.println(zonedDateTime2);
// 时区时间转换为LocalDateTime,将时区时间的时区信息去除
LocalDateTime ldt2 = zonedDateTime.toLocalDateTime();
System.out.println(ldt2);
输出如下
2021-03-19T13:41:50.708
2021-03-19T13:41:50.708+08:00[Asia/Shanghai]
2021-03-19T05:41:50.708Z
2021-03-19T05:41:50.708Z
2021-03-19T13:41:50.708+08:00[Asia/Shanghai]
2021-03-19T13:41:50.708
LocalDateTime与Date转换
Instant和Date是新老时间转换的桥梁,二者都是时间戳的表现形式,但Date在打印时会转换成当前时区时间(可通过设置TimeZone调整),Instant打印时默认是0时区时间
Date 转 LocalDateTime
// Date 转 LocalDateTime
Date date = new Date();
System.out.println(date);
Instant instant = date.toInstant();
// 方法 一
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
System.out.println(ldt);
//方法二
LocalDateTime ldt2 = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
System.out.println(ldt2);
输出
Fri Mar 19 13:58:09 CST 2021
2021-03-19T13:58:09.634
2021-03-19T13:58:09.634
LocalDateTime 转 Date
ZoneId zoneId = ZoneId.systemDefault();
// 第一步 将 LocalDateTime 转为 ZonedDateTime
LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zone = ldt.atZone(zoneId);
// 也可以 使用这种方式
//ZonedDateTime zone2 = ZonedDateTime.of(ldt, zoneId);
// 第二步 将ZonedDateTime转为instant
Instant instant = zone.toInstant();
// 从Instant 获取Date
Date date = Date.from(instant);
System.out.println("LocalDateTime = " + ldt);
System.out.println("Date = " + date);
输出
LocalDateTime = 2021-03-19T14:10:05.968
Date = Fri Mar 19 14:10:05 CST 2021
工具类 LocalDateTimeUtils
package com.qianxun.utils;
import java.time.DayOfWeek;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
import java.time.temporal.UnsupportedTemporalTypeException;
import java.util.Date;
/**
* JDK8+中的LocalDateTime 工具类封装
*
* @author qianxun
*
*/
public class LocalDateTimeUtils {
private static final ZoneId ZONE_ID_DEFAULT = ZoneId.systemDefault();
private static final ZoneId ZONE_ID_UTC = ZoneId.of("UTC");
//private static String YYYY_MM_DD = "yyyy-MM-dd";
//private static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
private static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
private static String[] parsePatterns = {
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm",
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm",
"yyyy.MM.dd HH:mm:ss"};
/**
* <pre>
* 当前时间,默认时区
* 返回格式如下 2021-03-19T14:29:08.551
* </pre>
*
* @return {@link LocalDateTime}
*/
public static LocalDateTime now() {
return LocalDateTime.now();
}
/**
* 日期路径 即年/月/日 如2021/03/18
*/
public static final String datePath() {
return format(now(), "yyyy/MM/dd");
}
/******** 日期转换部分 start ***/
/**
* 使用系统默认时区,将Instant 转 LocalDateTime
*
* @param instant
* {@link Instant}
* @return {@link LocalDateTime}
*/
public static LocalDateTime toLocalDateTime(Instant instant) {
return toLocalDateTime(instant, null);
}
/**
* 使用UTC时区(格林威治 时间标准时间 0时区),将Instant 转 LocalDateTime
*
* @param instant
* {@link Instant}
* @return {@link LocalDateTime}
*/
public static LocalDateTime toLocalDateTimeUTC(Instant instant) {
return toLocalDateTime(instant, ZONE_ID_UTC);
}
/**
* <pre>
* 使用指定的时区id,将Instant 转 LocalDateTime,
* 如果 ZoneId 为 NULL 则使用系统默认时区
* </pre>
*
* @param instant
* {@link Instant}
* @param zoneId
* {@link ZoneId}
* @return {@link LocalDateTime}
*/
public static LocalDateTime toLocalDateTime(Instant instant, ZoneId zoneId) {
if (null == instant) {
return null;
}
// ZoneId 为 NULL 则使用系统默认时区
ZoneId zoneIdUse = (null == zoneId) ? ZONE_ID_DEFAULT : zoneId;
return LocalDateTime.ofInstant(instant, zoneIdUse);
}
/**
* ZonedDateTime 转 LocalDateTime
*
* @param zonedDateTime
* {@link ZonedDateTime}
* @return {@link LocalDateTime}
*/
public static LocalDateTime toLocalDateTime(ZonedDateTime zonedDateTime) {
if (null == zonedDateTime) {
return null;
}
return zonedDateTime.toLocalDateTime();
}
/**
* 使用系统默认时区,Date 转 LocalDateTime
*
* @param date
* {@link Date}
* @return {@link LocalDateTime}
*/
public static LocalDateTime toLocalDateTime(Date date) {
if (null == date) {
return null;
}
Instant instant = date.toInstant();
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
}
/**
* 毫秒转{@link LocalDateTime},使用默认时区
*
* <p>
* 注意:此方法使用默认时区,如果非UTC,会产生时间偏移
* </p>
*
* @param epochMilli
* 从1970-01-01T00:00:00Z开始计数的毫秒数
* @return {@link LocalDateTime}
*/
public static LocalDateTime toLocalDateTime(long epochMilli) {
return toLocalDateTime(Instant.ofEpochMilli(epochMilli));
}
/**
* 毫秒转{@link LocalDateTime},使用UTC时区
*
* @param epochMilli
* 从1970-01-01T00:00:00Z开始计数的毫秒数
* @return {@link LocalDateTime}
*/
public static LocalDateTime toLocalDateTimeUTC(long epochMilli) {
return toLocalDateTimeUTC(Instant.ofEpochMilli(epochMilli));
}
/******** 日期转换部分 end ***/
/** 日期时间 解析部分 start */
/**
* 解析日期时间字符串为{@link LocalDateTime},仅支持yyyy-MM-dd'T'HH:mm:ss格式,例如:2007-12-03T10:15:30
*
* @param text
* 日期时间字符串
* @return {@link LocalDateTime}
*/
public static LocalDateTime parse(CharSequence text) {
return parse(text, (DateTimeFormatter) null);
}
/**
* 解析日期时间字符串为{@link LocalDate},仅支持yyyy-MM-dd,例如:2021-03-18
*
* @param text
* 日期时间字符串
* @return {@link LocalDate}
*/
public static LocalDate parseDate(CharSequence text) {
return parseDate(text, (DateTimeFormatter) null);
}
/**
* 解析日期时间字符串为{@link LocalDateTime},格式支持日期时间、日期、时间
*
* @param text
* 日期时间字符串
* @param formatter
* 日期格式化器,预定义的格式见:{@link DateTimeFormatter}
* @return {@link LocalDateTime}
*/
public static LocalDateTime parse(CharSequence text, DateTimeFormatter formatter) {
if (null == text) {
return null;
}
if (null == formatter) {
// 使用ISO 8601标准格式
return LocalDateTime.parse(text);
}
// return LocalDateTime.parse(text,formatter);
return of(formatter.parse(text));
}
/**
* 解析日期字符串为{@link LocalDateTime}
*
* @param text
* @param format
* @return
*/
public static LocalDateTime parse(CharSequence text, String format) {
if (null == text) {
return null;
}
return parse(text, DateTimeFormatter.ofPattern(format));
}
/**
* 通过给定的日期格式解析日期时间字符串。<br>
* 传入的日期格式会逐个尝试,直到解析成功,返回{@link LocalDateTime}对象,否则抛出{@link RuntimeException}异常
*
* @param text
* @param format
* @return
*/
public static LocalDateTime parse(String text, String... format) {
if (null == text) {
return null;
}
return parseByPatterns(text, parsePatterns);
}
/**
* 解析日期时间字符串为{@link LocalDate},格式支持日期
*
* @param text
* 日期时间字符串
* @param formatter
* 日期格式化器,预定义的格式见:{@link DateTimeFormatter}
* @return {@link LocalDate}
*/
public static LocalDate parseDate(CharSequence text, DateTimeFormatter formatter) {
if (null == text) {
return null;
}
if (null == formatter) {
return LocalDate.parse(text);
}
return ofDate(formatter.parse(text));
}
/**
* 解析日期字符串为{@link LocalDate}
*
* @param text
* 日期字符串
* @param format
* 日期格式,类似于yyyy-MM-dd
* @return {@link LocalDateTime}
*/
public static LocalDate parseDate(CharSequence text, String format) {
if (null == text) {
return null;
}
return parseDate(text, DateTimeFormatter.ofPattern(format));
}
/**
* 格式化日期时间为yyyy-MM-dd HH:mm:ss格式
*
* @param time
* {@link LocalDateTime}
* @return 格式化后的字符串
*/
@SuppressWarnings("unused")
private static String formatNormal(LocalDateTime time) {
return format(time, DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
}
/**
* 格式化日期时间为指定格式
*
* @param time
* {@link LocalDateTime}
* @param formatter
* 日期格式化器,预定义的格式见:{@link DateTimeFormatter}
* @return 格式化后的字符串
*/
public static String format(LocalDateTime time, DateTimeFormatter formatter) {
return format(time, formatter);
}
/**
* 格式化日期时间为指定格式
*
* @param time
* {@link LocalDateTime}
* @param format
* 日期格式,类似于yyyy-MM-dd HH:mm:ss,SSS
* @return 格式化后的字符串
*/
public static String format(LocalDateTime time, String format) {
if (null == time) {
return null;
}
return format(time, DateTimeFormatter.ofPattern(format));
}
/**
* 格式化日期时间为指定格式
*
* @param time
* {@link TemporalAccessor}
* @param formatter
* 日期格式化器,预定义的格式见:{@link DateTimeFormatter}
* @return 格式化后的字符串
*/
public static String format(TemporalAccessor time, DateTimeFormatter formatter) {
if (null == time) {
return null;
}
if (null == formatter) {
formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
}
try {
return formatter.format(time);
} catch (UnsupportedTemporalTypeException e) {
if (time instanceof LocalDate && e.getMessage().contains("HourOfDay")) {
// 用户传入LocalDate,但是要求格式化带有时间部分,转换为LocalDateTime重试
return formatter.format(((LocalDate) time).atStartOfDay());
} else if (time instanceof LocalTime && e.getMessage().contains("YearOfEra")) {
// 用户传入LocalTime,但是要求格式化带有日期部分,转换为LocalDateTime重试
return formatter.format(((LocalTime) time).atDate(LocalDate.now()));
}
throw e;
}
}
/******** 日期转换部分 end ***/
/**
* {@link TemporalAccessor}转{@link LocalDateTime},使用默认时区
*
* @param temporalAccessor
* @return
*/
public static LocalDateTime of(TemporalAccessor temporalAccessor) {
if (null == temporalAccessor) {
return null;
}
if (temporalAccessor instanceof LocalDate) {
return ((LocalDate) temporalAccessor).atStartOfDay();
}
return LocalDateTime.of(getField(temporalAccessor, ChronoField.YEAR),
getField(temporalAccessor, ChronoField.MONTH_OF_YEAR),
getField(temporalAccessor, ChronoField.DAY_OF_MONTH),
getField(temporalAccessor, ChronoField.HOUR_OF_DAY),
getField(temporalAccessor, ChronoField.MINUTE_OF_HOUR),
getField(temporalAccessor, ChronoField.SECOND_OF_MINUTE),
getField(temporalAccessor, ChronoField.NANO_OF_SECOND));
}
/**
* {@link TemporalAccessor}转{@link LocalDate},使用默认时区
*
* @param temporalAccessor
* @return
*/
public static LocalDate ofDate(TemporalAccessor temporalAccessor) {
if (null == temporalAccessor) {
return null;
}
if (temporalAccessor instanceof LocalDateTime) {
return ((LocalDateTime) temporalAccessor).toLocalDate();
}
return LocalDate.of(getField(temporalAccessor, ChronoField.YEAR),
getField(temporalAccessor, ChronoField.MONTH_OF_YEAR),
getField(temporalAccessor, ChronoField.DAY_OF_MONTH));
}
/**
* 获取下一个 工作日 默认 周一 至 周五
*
* @return
*/
public static LocalDateTime getNextWorkDay() {
LocalDateTime now = now();
LocalDateTime workDay = now.with((temporal) -> {
LocalDateTime localDateTime = (LocalDateTime) temporal;
DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();// 获取星期几
if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {// 周五,下一个工作日 加3天
return localDateTime.plusDays(3);
} else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {
return localDateTime.plusDays(2);
} else {
return localDateTime.plusDays(1);
}
});
return workDay;
}
/**
* 安全获取时间的某个属性,属性不存在返回0
*
* @param temporalAccessor
* 需要获取的时间对象
* @param field
* 需要获取的属性
* @return 时间的值,如果无法获取则默认为 0
*/
private static int getField(TemporalAccessor temporalAccessor, TemporalField field) {
if (temporalAccessor.isSupported(field)) {
return temporalAccessor.get(field);
}
return (int) field.range().getMinimum();
}
public static LocalDateTime parseByPatterns(String str,final String... parsePatterns) throws RuntimeException{
if (str == null || parsePatterns == null) {
throw new IllegalArgumentException("解析匹配格式不能为空");
}
for (final String parsePattern : parsePatterns){
try {
return parse(str, parsePattern);
} catch (final DateTimeParseException ignore) {
}
}
throw new RuntimeException("解析失败...");
}
}