【README】
1)本文总结了java8中日期时间常用工具方法;包括:
- 日期时间对象格式化为字符串;
- 日期时间字符串解析为日期时间对象;
- 日期时间对象转换;
- 转换过程中,需要注意的是: Instant与Date带时区(易变),而LocalDateTime,LocalDate,LocalTime 不带时区(不可变);
- 带时区的日期时间 ZonedDateTime 剖析;
2)日期时间工具类定义如下:
java
public class BusiDateTimeUtils {
/** 日期时间格式化器 */
private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
/** 日期格式化器 */
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private BusiDateTimeUtils() {
// do nothing.
}
// ....................
}
【1】当前日期时间操作
java
/** -------------------- 1. 当前日期时间操作 -------------------- */
public static String getNowLocalDateTimeStr() {
return LocalDateTime.now().format(DATETIME_FORMATTER);
}
public static String getNowLocalDateStr() {
return LocalDate.now().format(DATE_FORMATTER);
}
【1.1】单测案例:
java
/** -------------------- 1. 当前日期时间操作 -------------------- */
@Test
public void test1() {
// 获取当前日期时间
String nowLocalDateTimeStr = BusiDateTimeUtils.getNowLocalDateTimeStr();
System.out.println("nowLocalDateTimeStr="+nowLocalDateTimeStr); // 2023-10-05 21:28:09
// 获取当前日期
String nowLocalDateStr = BusiDateTimeUtils.getNowLocalDateStr();
System.out.println("nowLocalDateStr=" + nowLocalDateStr); // 2023-10-05
}
【2】字符串解析为日期时间对象
java
/** -------------------- 2. 字符串解析为日期时间对象 -------------------- */
public static LocalDateTime parseLocalDateTime(String dateTimeStr) {
return LocalDateTime.parse(dateTimeStr, DATETIME_FORMATTER);
}
public static LocalDate parseLocalDate(String dateStr) {
return LocalDate.parse(dateStr, DATE_FORMATTER);
}
【2.1】单测案例
java
/** -------------------- 2. 字符串解析为日期时间对象 -------------------- */
@Test
public void test2() {
// 解析当前日期时间
String nowLocalDateTimeStr = BusiDateTimeUtils.getNowLocalDateTimeStr();
System.out.println("nowLocalDateTimeStr="+ nowLocalDateTimeStr); // 2023-10-05 21:29:32
LocalDateTime parsedLocalDateTime = BusiDateTimeUtils.parseLocalDateTime(nowLocalDateTimeStr);
System.out.println(parsedLocalDateTime); // 2023-10-05T21:29:32
// 解析当前日期
String nowLocalDateStr = BusiDateTimeUtils.getNowLocalDateStr();
System.out.println("nowLocalDateStr=" + nowLocalDateStr); // 2023-10-05
LocalDate parsedLocalDate = BusiDateTimeUtils.parseLocalDate(nowLocalDateStr);
System.out.println(parsedLocalDate); // 2023-10-05
}
【3】日期时间对象格式化为字符串
java
/** -------------------- 3. 日期时间对象格式化为字符串 -------------------- */
public static String format(LocalDateTime localDateTime) {
return localDateTime.format(DATETIME_FORMATTER);
}
public static String format(LocalDate localDate) {
return localDate.format(DATE_FORMATTER);
}
【3.1】单测案例
java
/** -------------------- 3. 日期时间对象格式化为字符串 -------------------- */
@Test
public void test3() {
// 格式化当前日期时间对象为字符串
String nowLocalDateTimeStr = BusiDateTimeUtils.getNowLocalDateTimeStr();
System.out.println("nowLocalDateTimeStr="+ nowLocalDateTimeStr); // 2023-10-05 21:35:19
LocalDateTime parsedLocalDateTime = BusiDateTimeUtils.parseLocalDateTime(nowLocalDateTimeStr);
String formatedLocalDateTime = BusiDateTimeUtils.format(parsedLocalDateTime);
System.out.println(formatedLocalDateTime); // 2023-10-05 21:35:19
// 格式化当前日期对象为字符串
String nowLocalDateStr = BusiDateTimeUtils.getNowLocalDateStr();
System.out.println("nowLocalDateStr=" + nowLocalDateStr); // 2023-10-05
LocalDate parsedLocalDate = BusiDateTimeUtils.parseLocalDate(nowLocalDateStr);
String formatedLocalDate = BusiDateTimeUtils.format(parsedLocalDate);
System.out.println(formatedLocalDate); // 2023-10-05
}
【4】*LocalDateTime 转为其他日期时间类型(重要)
java
/** -------------------- 4. LocalDateTime 转为其他日期时间类型 -------------------- */
public static LocalDate toLocalDate(LocalDateTime localDateTime) {
return localDateTime.toLocalDate();
}
public static Instant toInstant(LocalDateTime localDateTime) {
return localDateTime.toInstant(ZoneOffset.UTC);
}
public static Date toDate(LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
**【说明】**LocalDateTime 转 Instant与Date时,做了一些特殊处理:
- LocalDateTime没有时区,而Instant有时区 ;为了统一,把Instant的时区设置为0时区(UTC),则LocalDateTime与Instant都没有时区了;
- LocalDateTime没有时区,Instant有时区,Date有时区:
- 先把 LocalDateTime转为带时区的日期时间 ZonedDateTime;
- 再把 ZonedDateTime 转 Instant(默认时区为系统时区);
- 最后把Instant转Date(默认时区为系统时区);
【4.1】单测案例
java
/** -------------------- 4. LocalDateTime 转为其他日期时间类型 -------------------- */
@Test
public void test4() {
LocalDateTime nowLocalDateTime = LocalDateTime.now();
System.out.println("nowLocalDateTimeStr="+BusiDateTimeUtils.format(nowLocalDateTime)); // 2023-10-05 21:37:14
// LocalDateTime 转 LocalDate
LocalDate localDate = BusiDateTimeUtils.toLocalDate(nowLocalDateTime);
LocalDate localDate2 = nowLocalDateTime.toLocalDate(); // 与上一行代码效果一样
System.out.println("localDate=" + localDate); // 2023-10-05
// LocalDateTime 转 Instant
Instant nowInstant = BusiDateTimeUtils.toInstant(nowLocalDateTime);
System.out.println(nowInstant); // 2023-10-05T21:37:14.677Z
// LocalDateTime 转 Date
Date nowDate = BusiDateTimeUtils.toDate(nowLocalDateTime);
System.out.println(nowDate); // Thu Oct 05 21:37:14 CST 2023
}
【5】LocalDate 转为其他日期时间类型
java
/** -------------------- 5. LocalDate 转为其他日期时间类型 -------------------- */
public static LocalDateTime toLocalDateTime(LocalDate localDate) {
return localDate.atStartOfDay();
}
public static Instant toInstant(LocalDate localDate) {
return localDate.atStartOfDay().toInstant(ZoneOffset.UTC);
}
public static Date toDate(LocalDate localDate) {
return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
}
**【说明】**LocalDate 转 Instant与Date时,做了一些特殊处理:与 LocalDateTime 转 Instant与Date类似 ,这里不再赘述;参见本文章节【4】;
【5.1】单测案例
java
/** -------------------- 5. LocalDate 转为其他日期时间类型 -------------------- */
@Test
public void test5() {
LocalDate nowLocalDate = LocalDate.now();
System.out.println("nowLocalDateStr="+BusiDateTimeUtils.format(nowLocalDate)); // 2023-10-05
// LocalDate 转 LocalDateTime
LocalDateTime localDateTime = BusiDateTimeUtils.toLocalDateTime(nowLocalDate);
System.out.println("localDateTime=" + localDateTime); // 2023-10-05T00:00
// LocalDate 转 Instant
Instant nowInstant = BusiDateTimeUtils.toInstant(nowLocalDate);
System.out.println(nowInstant); // 2023-10-05T00:00
// LocalDate 转 Date
Date nowDate = BusiDateTimeUtils.toDate(nowLocalDate);
System.out.println(nowDate); // Thu Oct 05 00:00:00 CST 2023
}
【6】Instant 转为其他日期时间类型
java
/** -------------------- 6. Instant 转为其他日期时间类型 -------------------- */
public static LocalDateTime toLocalDateTime(Instant instantWithoutZone) {
return LocalDateTime.ofInstant(instantWithoutZone, ZoneOffset.UTC);
}
public static LocalDate toLocalDate(Instant instantWithoutZone) {
return toLocalDateTime(instantWithoutZone).toLocalDate();
}
public static Date toDate(Instant instantWithoutZone) {
return toDate(toLocalDateTime(instantWithoutZone));
}
【说明】
注意上述工具方法中入参 Instant变量是不带时区的,也可以理解为时区为UTC(0时区);
【6.1】单测案例
java
/** -------------------- 6. Instant 转为其他日期时间类型 -------------------- */
@Test
public void test6() {
Instant nowInstantWithoutZone = LocalDateTime.now().toInstant(ZoneOffset.UTC);
System.out.println("nowZonedInstant="+nowInstantWithoutZone); // 2023-10-05T22:00:54.783Z
System.out.println("Instant.now()=" + Instant.now()); // 2023-10-05T14:00:54.798Z(注意这里晚了8个小时)
// Instant 转 LocalDateTime
LocalDateTime localDateTime = BusiDateTimeUtils.toLocalDateTime(nowInstantWithoutZone);
System.out.println("localDateTime=" + localDateTime); // 2023-10-05T22:00:54.783
// Instant 转 LocalDate
LocalDate localDate = BusiDateTimeUtils.toLocalDate(nowInstantWithoutZone);
System.out.println("localDate=" + localDate); // 2023-10-05
// Instant 转 Date
Date date = BusiDateTimeUtils.toDate(nowInstantWithoutZone);
System.out.println("date=" + date); // date=Thu Oct 05 22:00:54 CST 2023
}
【7】总结
【7.1】带时区的日期时间 ZonedDateTime 剖析
java
/** -------------------- 7. 带时区的日期时间 -------------------- */
@Test
public void test7() {
LocalDateTime nowLocalDateTime = LocalDateTime.now();
System.out.println("nowLocalDateTime=" + nowLocalDateTime); // 2023-10-05T22:19:10.812
// 转为带时区的日期时间(系统时区)
System.out.println("ZoneId.systemDefault()=" + ZoneId.systemDefault()); // Asia/Shanghai
ZonedDateTime zonedDateTime = nowLocalDateTime.atZone(ZoneId.systemDefault());
System.out.println("zonedDateTime.toInstant()(系统时区)="+zonedDateTime.toInstant()); // 2023-10-05T14:19:10.812Z(晚8个小时)
// 转为带时区的日期时间(0时区)
zonedDateTime = nowLocalDateTime.atZone(ZoneOffset.UTC);
System.out.println("zonedDateTime.toInstant()(0时区)="+zonedDateTime.toInstant()); // 2023-10-05T22:19:10.812Z
}
【说明】
- 1)系统时区解析后的Instant,晚8个小时;
- 原因: LocalDateTime 本身没有时区,根据系统时区(东8区 )把LocalDateTime 转为 ZonedDateTime后,把ZonedDateTime转为Instant时,jdk认为 LocalDateTime 的时区为东8区的时间,转Instant默认使用0时区;因为东8区比0时区快8个小时,所以减去了8个小时;
- 2)0时区解析后的Instant,转换正确;
- 原因:LocalDateTime 本身没有时区,根据0时区把LocalDateTime 转为 ZonedDateTime后,把ZonedDateTime转为Instant时,jdk认为 LocalDateTime 的时区为0时区的时间,转Instant默认使用0时区,两者使用的时区一致,所以转换正确;
【7.2】日期时间工具类
java
/**
* @Description 日期时间工具类
* @author xiao tang
* @version 1.0.0
* @createTime 2023年10月05日
*/
public class BusiDateTimeUtils {
/** 日期时间格式化器 */
private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
/** 日期格式化器 */
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private BusiDateTimeUtils() {
// do nothing.
}
/** -------------------- 1. 当前日期时间操作 -------------------- */
public static String getNowLocalDateTimeStr() {
return LocalDateTime.now().format(DATETIME_FORMATTER);
}
public static String getNowLocalDateStr() {
return LocalDate.now().format(DATE_FORMATTER);
}
/** -------------------- 2. 字符串解析为日期时间对象 -------------------- */
public static LocalDateTime parseLocalDateTime(String dateTimeStr) {
return LocalDateTime.parse(dateTimeStr, DATETIME_FORMATTER);
}
public static LocalDate parseLocalDate(String dateStr) {
return LocalDate.parse(dateStr, DATE_FORMATTER);
}
/** -------------------- 3. 日期时间对象格式化为字符串 -------------------- */
public static String format(LocalDateTime localDateTime) {
return localDateTime.format(DATETIME_FORMATTER);
}
public static String format(LocalDate localDate) {
return localDate.format(DATE_FORMATTER);
}
/** -------------------- 4. LocalDateTime 转为其他日期时间类型 -------------------- */
public static LocalDate toLocalDate(LocalDateTime localDateTime) {
return localDateTime.toLocalDate();
}
public static Instant toInstant(LocalDateTime localDateTime) {
return localDateTime.toInstant(ZoneOffset.UTC);
}
public static Date toDate(LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
/** -------------------- 5. LocalDate 转为其他日期时间类型 -------------------- */
public static LocalDateTime toLocalDateTime(LocalDate localDate) {
return localDate.atStartOfDay();
}
public static Instant toInstant(LocalDate localDate) {
return localDate.atStartOfDay().toInstant(ZoneOffset.UTC);
}
public static Date toDate(LocalDate localDate) {
return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
}
/** -------------------- 6. Instant 转为其他日期时间类型 -------------------- */
public static LocalDateTime toLocalDateTime(Instant instantWithoutZone) {
return LocalDateTime.ofInstant(instantWithoutZone, ZoneOffset.UTC);
}
public static LocalDate toLocalDate(Instant instantWithoutZone) {
return toLocalDateTime(instantWithoutZone).toLocalDate();
}
public static Date toDate(Instant instantWithoutZone) {
return toDate(toLocalDateTime(instantWithoutZone));
}
}
【7.3】日期时间工具类单测案例
java
/**
* @Description 日期时间工具类单测案例
* @author xiao tang
* @version 1.0.0
* @createTime 2023年10月05日
*/
public class BusiDateTimeUtilsTest {
/** -------------------- 1. 当前日期时间操作 -------------------- */
@Test
public void test1() {
// 获取当前日期时间
String nowLocalDateTimeStr = BusiDateTimeUtils.getNowLocalDateTimeStr();
System.out.println("nowLocalDateTimeStr="+nowLocalDateTimeStr); // 2023-10-05 21:28:09
// 获取当前日期
String nowLocalDateStr = BusiDateTimeUtils.getNowLocalDateStr();
System.out.println("nowLocalDateStr=" + nowLocalDateStr); // 2023-10-05
}
/** -------------------- 2. 字符串解析为日期时间对象 -------------------- */
@Test
public void test2() {
// 解析当前日期时间
String nowLocalDateTimeStr = BusiDateTimeUtils.getNowLocalDateTimeStr();
System.out.println("nowLocalDateTimeStr="+ nowLocalDateTimeStr); // 2023-10-05 21:29:32
LocalDateTime parsedLocalDateTime = BusiDateTimeUtils.parseLocalDateTime(nowLocalDateTimeStr);
System.out.println(parsedLocalDateTime); // 2023-10-05T21:29:32
// 解析当前日期
String nowLocalDateStr = BusiDateTimeUtils.getNowLocalDateStr();
System.out.println("nowLocalDateStr=" + nowLocalDateStr); // 2023-10-05
LocalDate parsedLocalDate = BusiDateTimeUtils.parseLocalDate(nowLocalDateStr);
System.out.println(parsedLocalDate); // 2023-10-05
}
/** -------------------- 3. 日期时间对象格式化为字符串 -------------------- */
@Test
public void test3() {
// 格式化当前日期时间对象为字符串
String nowLocalDateTimeStr = BusiDateTimeUtils.getNowLocalDateTimeStr();
System.out.println("nowLocalDateTimeStr="+ nowLocalDateTimeStr); // 2023-10-05 21:35:19
LocalDateTime parsedLocalDateTime = BusiDateTimeUtils.parseLocalDateTime(nowLocalDateTimeStr);
String formatedLocalDateTime = BusiDateTimeUtils.format(parsedLocalDateTime);
System.out.println(formatedLocalDateTime); // 2023-10-05 21:35:19
// 格式化当前日期对象为字符串
String nowLocalDateStr = BusiDateTimeUtils.getNowLocalDateStr();
System.out.println("nowLocalDateStr=" + nowLocalDateStr); // 2023-10-05
LocalDate parsedLocalDate = BusiDateTimeUtils.parseLocalDate(nowLocalDateStr);
String formatedLocalDate = BusiDateTimeUtils.format(parsedLocalDate);
System.out.println(formatedLocalDate); // 2023-10-05
}
/** -------------------- 4. LocalDateTime 转为其他日期时间类型 -------------------- */
@Test
public void test4() {
LocalDateTime nowLocalDateTime = LocalDateTime.now();
System.out.println("nowLocalDateTimeStr="+BusiDateTimeUtils.format(nowLocalDateTime)); // 2023-10-05 21:37:14
// LocalDateTime 转 LocalDate
LocalDate localDate = BusiDateTimeUtils.toLocalDate(nowLocalDateTime);
LocalDate localDate2 = nowLocalDateTime.toLocalDate(); // 与上一行代码效果一样
System.out.println("localDate=" + localDate); // 2023-10-05
// LocalDateTime 转 Instant
Instant nowInstant = BusiDateTimeUtils.toInstant(nowLocalDateTime);
System.out.println(nowInstant); // 2023-10-05T21:37:14.677Z
// LocalDateTime 转 Date
Date nowDate = BusiDateTimeUtils.toDate(nowLocalDateTime);
System.out.println(nowDate); // Thu Oct 05 21:37:14 CST 2023
}
/** -------------------- 5. LocalDate 转为其他日期时间类型 -------------------- */
@Test
public void test5() {
LocalDate nowLocalDate = LocalDate.now();
System.out.println("nowLocalDateStr="+BusiDateTimeUtils.format(nowLocalDate)); // 2023-10-05
// LocalDate 转 LocalDateTime
LocalDateTime localDateTime = BusiDateTimeUtils.toLocalDateTime(nowLocalDate);
System.out.println("localDateTime=" + localDateTime); // 2023-10-05T00:00
// LocalDate 转 Instant
Instant nowInstant = BusiDateTimeUtils.toInstant(nowLocalDate);
System.out.println(nowInstant); // 2023-10-05T00:00
// LocalDate 转 Date
Date nowDate = BusiDateTimeUtils.toDate(nowLocalDate);
System.out.println(nowDate); // Thu Oct 05 00:00:00 CST 2023
}
/** -------------------- 6. Instant 转为其他日期时间类型 -------------------- */
@Test
public void test6() {
Instant nowInstantWithoutZone = LocalDateTime.now().toInstant(ZoneOffset.UTC);
System.out.println("nowZonedInstant="+nowInstantWithoutZone); // 2023-10-05T22:00:54.783Z
System.out.println("Instant.now()=" + Instant.now()); // 2023-10-05T14:00:54.798Z(注意这里晚了8个小时)
// Instant 转 LocalDateTime
LocalDateTime localDateTime = BusiDateTimeUtils.toLocalDateTime(nowInstantWithoutZone);
System.out.println("localDateTime=" + localDateTime); // 2023-10-05T22:00:54.783
// Instant 转 LocalDate
LocalDate localDate = BusiDateTimeUtils.toLocalDate(nowInstantWithoutZone);
System.out.println("localDate=" + localDate); // 2023-10-05
// Instant 转 Date
Date date = BusiDateTimeUtils.toDate(nowInstantWithoutZone);
System.out.println("date=" + date); // date=Thu Oct 05 22:00:54 CST 2023
}
}