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 LocalDateTimeof(int year, int month, int dayOfMonth, int hour, int minute)从年,月,日,小时和分钟获得 LocalDateTime的实例,将秒和纳秒设置为零
static LocalDateTimeof(int year, int month, int dayOfMonth, int hour, int minute, int second)从年,月,日,小时,分钟和秒获得 LocalDateTime的实例,将纳秒设置为零
static LocalDateTimeof(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond)从年,月,日,小时,分钟和秒以及纳秒获得 LocalDateTime的实例
static LocalDateTimeof(int year, Month month, int dayOfMonth, int hour, int minute)从年,月,日,小时和分钟获得 LocalDateTime的实例,将秒和纳秒设置为零
static LocalDateTimeof(int year, Month month, int dayOfMonth, int hour, int minute, int second)从年,月,日,小时,分钟和秒获得 LocalDateTime的实例,将纳秒设置为零
static LocalDateTimeof(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
方法修饰符及返回值方法名称及参数方法说明
LocalDateTimeplus(long amountToAdd, TemporalUnit unit)amountToAdd:要增加的数值
TemporalUnit :单位,可以参考java.time.temporal.ChronoUnit枚举
LocalDateTimeplusDays(long days)加多少天
LocalDateTimeplusHours(long hours)加多少秒
LocalDateTimeplusMinutes(long minutes)加多少分钟
LocalDateTimeplusMonths(long months)加几个月
LocalDateTimeplusWeeks(long weeks)加多少星期
LocalDateTimeplusYears(long years)加多少年

同理还有对应的减日期的操作
minusxxx方法,这里就不一一列举了。

得到具体的年月日…

方法修饰符及返回值方法名称及参数方法说明
intget(TemporalField field)获取指定字段的值,TemporalField的实现类,参考java.time.temporal.ChronoField
intgetYear()获取年份
MonthgetMonth()使用 Month枚举获取月份字段
intgetMonthValue()月份 1 到 12
intgetDayOfMonth()获取 日 1到 31
intgetDayOfYear()一年中的第几天
DayOfWeekgetDayOfWeek()星期几
intgetHour()
intgetMinute()
intgetSecond()

修改时间

方法修饰符及返回值方法名称及参数方法说明
LocalDateTimewithDayOfYear(int dayOfYear)修改 day 字段
LocalDateTimewithHour(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
方法修饰符及返回值方法名称及参数方法说明
longtoEpochMilli()1970-01-01T00:00:00Z到此时间戳的毫秒
longgetEpochSecond()1970-01-01T00:00:00Z到此时间戳的
intgetNano()获取 2021-03-18T14:18:38.049Z 秒后面的049Z的纳秒值
static InstantofEpochSecond(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 SetgetAvailableZoneIds()获取所有可用的时区ID
static ZoneIdof(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("解析失败...");
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值