日期时间实战
日期时间各种转换,以LocalDateTime为中介。
DateUtils
重构后的代码
package com.nightglow.util;
import java.sql.Timestamp;
import java.time.DateTimeException;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.StringUtils;
public class DateUtils {
public static final String YYYYMMDD_PATTERN = "yyyyMMdd";
public static final String YYYY_MMDD_PATTERN = "yyyy-MM-dd";
public static final String YYYYMMDDHHMMSS_PATTERN = "yyyyMMddHHmmss";
public static final String YYYY_MM_DD_HH_MM_SS_PATTERN = "yyyy-MM-dd HH:mm:ss";
private static final ZoneOffset CHINA_ZONE = ZoneOffset.of("+8");
public static LocalDateTime mills2DateTime(Long mills) {
if (Objects.isNull(mills)) {
return null;
}
try {
Instant instant = Instant.ofEpochMilli(mills);
return LocalDateTime.ofInstant(instant, CHINA_ZONE);
} catch (DateTimeException e) {
// log
}
return null;
}
public static Long dateTime2Mills(LocalDateTime dateTime) {
if (Objects.isNull(dateTime)) {
return null;
}
try {
return dateTime.toInstant(CHINA_ZONE).toEpochMilli();
} catch (ArithmeticException e) {
// log
}
return null;
}
public static LocalDateTime str2DateTime(String str) {
return str2DateTime(str, YYYY_MM_DD_HH_MM_SS_PATTERN);
}
public static LocalDateTime str2DateTime(String str, String pattern) {
if (StringUtils.isBlank(str) || StringUtils.isBlank(pattern)) {
return null;
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
try {
return LocalDateTime.parse(str, formatter);
} catch (DateTimeParseException e) {
// log
}
return null;
}
public static String dateTime2Str(LocalDateTime dateTime) {
return dateTime2Str(dateTime, YYYY_MM_DD_HH_MM_SS_PATTERN);
}
public static String dateTime2Str(LocalDateTime dateTime, String pattern) {
if (Objects.isNull(dateTime) || StringUtils.isBlank(pattern)) {
return null;
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
try {
return dateTime.format(formatter);
} catch (DateTimeException e) {
// log
}
return null;
}
public static LocalDateTime timeStamp2DateTime(Timestamp timestamp) {
if (Objects.isNull(timestamp)) {
return null;
}
return timestamp.toLocalDateTime();
}
public static Timestamp dateTime2TimeStamp(LocalDateTime dateTime) {
if (Objects.isNull(dateTime)) {
return null;
}
return Timestamp.valueOf(dateTime);
}
public static LocalDateTime date2DateTime(Date date) {
if (Objects.isNull(date)) {
return null;
}
try {
return LocalDateTime.ofInstant(date.toInstant(), CHINA_ZONE);
} catch (DateTimeException e) {
// log
}
return null;
}
public static Long nanosBetween(LocalDateTime startDateTime, LocalDateTime endDateTime) {
if (Objects.isNull(startDateTime) || Objects.isNull(endDateTime)) {
return null;
}
Duration duration = Duration.between(startDateTime, endDateTime);
return duration.toNanos();
}
/*
* plus负值,等价minus
*/
public static LocalDateTime plusTime(LocalDateTime dateTime, Long value, ChronoUnit chronoUnit) {
if (Objects.isNull(dateTime) || Objects.isNull(value) || Objects.isNull(chronoUnit)) {
return null;
}
return dateTime.plus(value, chronoUnit);
}
public static Long convertByTimeUnit(Long srcValue, TimeUnit srcTimeUnit, TimeUnit timeUnit) {
if (Objects.isNull(srcValue) || Objects.isNull(srcTimeUnit) || Objects.isNull(timeUnit)) {
return null;
}
return timeUnit.convert(srcValue, srcTimeUnit);
}
}
场景验证
用DateUtils中静态方法替换老的DateUtil,验证其通用性;
实际开发中需判null或者使用Optional。
DateUtil验证代码
package com.nightglow.util;
import com.google.common.collect.Maps;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import static com.nightglow.util.DateUtils.YYYYMMDD_PATTERN;
import static com.nightglow.util.DateUtils.YYYY_MMDD_PATTERN;
import static com.nightglow.util.DateUtils.YYYY_MM_DD_HH_MM_SS_PATTERN;
public class DateUtil {
public static final int DAY_MINUTES = 24 * 60;
public static void cmp1() {
System.out.println(DAY_MINUTES);
System.out.println(DateUtils.convertByTimeUnit(1L, TimeUnit.DAYS, TimeUnit.MINUTES));
}
public static String parseDateMinusDays(LocalDate localDate, int day, String format) {
LocalDate date = localDate.minusDays(day);
String str = date.format(DateTimeFormatter.ofPattern(format));
return str;
}
public static void cmp2() {
LocalDate localDate = LocalDate.now();
int day = 1;
String format = DateUtils.YYYY_MMDD_PATTERN;
System.out.println(parseDateMinusDays(localDate, day, format));
LocalDateTime dateTime = localDate.atTime(LocalTime.now());
LocalDateTime minuteDateTime = DateUtils.plusTime(dateTime, Long.valueOf(-day), ChronoUnit.DAYS);
System.out.println(DateUtils.dateTime2Str(minuteDateTime, format));
}
public static String getLocalDateStr(LocalDate localDate) {
if (Objects.isNull(localDate)) {
return null;
}
return localDate.format(DateTimeFormatter.ofPattern(YYYY_MMDD_PATTERN));
}
public static void cmp3() {
LocalDate localDate = LocalDate.now();
System.out.println(getLocalDateStr(localDate));
LocalDateTime dateTime = localDate.atTime(LocalTime.now());
System.out.println(DateUtils.dateTime2Str(dateTime, YYYY_MMDD_PATTERN));
}
public static LocalDate getNeighboringLocalDate(int relativeDays) {
LocalDate today = LocalDate.now();
return today.plusDays(relativeDays);
}
public static void cmp4() {
int relativeDays = 1;
System.out.println(getNeighboringLocalDate(relativeDays));
LocalDateTime dateTime = DateUtils.plusTime(LocalDateTime.now(), Long.valueOf(relativeDays), ChronoUnit.DAYS);
System.out.println(dateTime.toLocalDate());
}
/**
* 时间相差的分钟数
* @param startTime
* @param endTime
* @return
*/
public static long localDateTimeDiff2Minutes(LocalDateTime startTime, LocalDateTime endTime){
Duration duration = Duration.between(startTime ,endTime);
return duration.toMinutes();
}
public static void cmp5() {
LocalDateTime endTime = LocalDateTime.now();
LocalDateTime startTime = endTime.minusDays(1);
System.out.println(localDateTimeDiff2Minutes(startTime, endTime));
Long nanos = DateUtils.nanosBetween(startTime, endTime);
System.out.println(DateUtils.convertByTimeUnit(nanos, TimeUnit.NANOSECONDS, TimeUnit.MINUTES));
}
/**
* 获取今天的指定时间
*
* @param hour
* @param minute
* @param second
* @return
*/
public static LocalDateTime getTodayLocalDateTime(int hour, int minute, int second) {
LocalDateTime now = LocalDateTime.now();
return LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), hour, minute, second);
}
public static void cmp6() {
int hour = 12;
int minute = 0;
int second = 0;
System.out.println(getTodayLocalDateTime(hour, minute, second));
System.out.println(LocalDateTime.of(LocalDate.now(), LocalTime.of(hour, minute, second)));
}
/**
* 日期格式化
* @param date
* @param pattern
* @return
*/
public static String date2Str(Date date, String pattern){
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
return sdf.format(date);
}
public static void cmp7() {
Date date = new Date();
String pattern = DateUtils.YYYY_MM_DD_HH_MM_SS_PATTERN;
System.out.println(date2Str(date, pattern));
LocalDateTime dateTime = DateUtils.date2DateTime(date);
System.out.println(DateUtils.dateTime2Str(dateTime, pattern));
}
/**
* Date类型转为Timestamp类型
*
* @param date
* @return Timestamp
*/
public static Timestamp dateToTimestamp(Date date) {
return new Timestamp(date.getTime());
}
public static void cmp8() {
Date date = new Date();
System.out.println(dateToTimestamp(date));
LocalDateTime dateTime = DateUtils.date2DateTime(date);
System.out.println(DateUtils.dateTime2TimeStamp(dateTime));
}
/**
* 获取某天所在的日期,例如20220106
*
* @param day 0 表示当前日期,往前的天数(负数),往后的天数(正数)
* @return
*/
public static String constructDate(int day) {
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(YYYYMMDD_PATTERN);
LocalDate targetDate = LocalDate.now().plus(day, ChronoUnit.DAYS);
return dateFormatter.format(targetDate);
}
public static void cmp9() {
int day = 1;
System.out.println(constructDate(day));
LocalDateTime dateTime = DateUtils.plusTime(LocalDateTime.now(), Long.valueOf(day), ChronoUnit.DAYS);
System.out.println(DateUtils.dateTime2Str(dateTime, YYYYMMDD_PATTERN));
}
/**
* 获取某天所在月的第一天
*
* @param day 0 表示当前日期,往前的天数(负数),往后的天数(正数)
* @return
*/
public static String constructFirstDayOfMonth(int day) {
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(YYYYMMDD_PATTERN);
LocalDate targetDate = LocalDate.now().plus(day, ChronoUnit.DAYS);
targetDate = targetDate.with(TemporalAdjusters.firstDayOfMonth());
return dateFormatter.format(targetDate);
}
public static void cmp10() {
int day = 10;
System.out.println(constructFirstDayOfMonth(day));
LocalDateTime dateTime = DateUtils.plusTime(LocalDateTime.now(), Long.valueOf(day), ChronoUnit.DAYS);
LocalDateTime adjustDateTime = dateTime.with(TemporalAdjusters.firstDayOfMonth());
System.out.println(DateUtils.dateTime2Str(adjustDateTime, YYYYMMDD_PATTERN));
}
/**
* 获取某一天前一天的起始和结束时间
* @param day day 0 表示当前日期,往前的天数(负数),往后的天数(正数)
* @param pattern 格式化 yyyy-MM-dd HH:mm:ss:SSS
* @return
*/
public static Map<String, Object> constructStartAndEndTimeOfDay (int day, String pattern) {
Map<String, Object> mapTime = Maps.newHashMap();
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.add(Calendar.DAY_OF_MONTH, day);
Date startOfPreviousDay = cal.getTime();
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.MILLISECOND, 999);
Date endOfPreviousDay = cal.getTime();
//格式转换
//前一天凌晨时间 2022-12-11 00:00:00.000
String startTime = date2Str(startOfPreviousDay,pattern);
//前一天末尾时间 2022-12-11 23:59:59.999
String endTime = date2Str(endOfPreviousDay,pattern);
mapTime.put("startTime",startTime);
mapTime.put("endTime",endTime);
return mapTime;
}
public static void cmp11() {
int day = 1;
String pattern = YYYY_MM_DD_HH_MM_SS_PATTERN;
System.out.println(constructStartAndEndTimeOfDay(day, pattern));
LocalDateTime dateTime = LocalDateTime.now();
LocalDateTime adjustDateTime = DateUtils.plusTime(dateTime, Long.valueOf(day), ChronoUnit.DAYS);
Map<String, String> result = Maps.newHashMap();
LocalDateTime startDateTime = LocalDateTime.of(adjustDateTime.toLocalDate(), LocalTime.MIN);
LocalDateTime endDateTime = LocalDateTime.of(adjustDateTime.toLocalDate(), LocalTime.MAX);
result.put("startTime", DateUtils.dateTime2Str(startDateTime, pattern));
result.put("endTime", DateUtils.dateTime2Str(endDateTime, pattern));
System.out.println(result);
}
/**
* 计算两个时间相距多少秒
*
* @param before
* @return
*/
public static int secondsBetween(Date before, Date after) {
return (int) ((after.getTime() - before.getTime()) / 1000);
}
public static void cmp12() {
Date before = new Date();
Date after = new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(1));
System.out.println(secondsBetween(before, after));
LocalDateTime startDateTime = DateUtils.date2DateTime(before);
LocalDateTime endDateTime = DateUtils.date2DateTime(after);
Long nanos = DateUtils.nanosBetween(startDateTime, endDateTime);
System.out.println(DateUtils.convertByTimeUnit(nanos, TimeUnit.NANOSECONDS, TimeUnit.SECONDS));
}
/**
* 计算两个时间相距多少分钟
*
* @param before
* @return
*/
public static int minutesBetween(Date before, Date after) {
try {
return (int) ((after.getTime() - before.getTime()) / 1000 / 60);
} catch (Exception e) {
return 0;
}
}
public static void cmp13() {
Date before = new Date();
Date after = new Date(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(10));
System.out.println(minutesBetween(before, after));
LocalDateTime startDateTime = DateUtils.date2DateTime(before);
LocalDateTime endDateTime = DateUtils.date2DateTime(after);
Long nanos = DateUtils.nanosBetween(startDateTime, endDateTime);
System.out.println(DateUtils.convertByTimeUnit(nanos, TimeUnit.NANOSECONDS, TimeUnit.MINUTES));
}
/**
* 计算 minute 分钟后的时间
*
* @param date
* @param minute
* @return
*/
public static Date addMinute(Date date, int minute) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.MINUTE, minute);
return calendar.getTime();
}
public static void cmp14() {
Date date = new Date();
int minute = 1;
System.out.println(addMinute(date, minute));
LocalDateTime dateTime = DateUtils.date2DateTime(date);
LocalDateTime adjustDateTime = DateUtils.plusTime(dateTime, Long.valueOf(minute), ChronoUnit.MINUTES);
System.out.println(DateUtils.dateTime2Date(adjustDateTime));
}
/**
* 计算 minute 分钟前的时间
*
* @param date
* @param minute
* @return
*/
public static Date delMinute(Date date, int minute) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar. add(Calendar.MINUTE, -minute);
return calendar.getTime();
}
public static void cmp15() {
Date date = new Date();
int minute = 10;
System.out.println(delMinute(date, minute));
LocalDateTime dateTime = DateUtils.date2DateTime(date);
LocalDateTime adjustDateTime = DateUtils.plusTime(dateTime, Long.valueOf(-minute), ChronoUnit.MINUTES);
System.out.println(DateUtils.dateTime2Date(adjustDateTime));
}
/**
* 将yyyy-MM-dd HH:mm:ss或者yyyy-MM-dd'T'HH:mm:ss 或其他格式转换为Date类型
*/
public static Date dateStr2Date(String dateStr, String pattern) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
try {
return sdf.parse(dateStr);
} catch (ParseException e) {
// log
}
return null;
}
public static void cmp16() {
String dateStr = "2023-07-01 00:00:00";
String pattern = YYYY_MM_DD_HH_MM_SS_PATTERN;
System.out.println(dateStr2Date(dateStr, pattern));
LocalDateTime dateTime = DateUtils.str2DateTime(dateStr, pattern);
System.out.println(DateUtils.dateTime2Date(dateTime));
}
/**
* 针对业务上传的特殊日期格式转换
* eg:2023/5/31 09:43 -> 2023-05-31 09:43:00
*/
public static String specialDateStr2Str(String dateStr) {
String str = "";
try {
if (dateStr.contains("/")) {
str = date2Str(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(dateStr.length() <= 16 ? dateStr.concat(":00") : dateStr), "yyyy-MM-dd HH:mm:ss");
} else if (dateStr.contains("-")) {
str = date2Str(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateStr.length() <= 16 ? dateStr.concat(":00") : dateStr), "yyyy-MM-dd HH:mm:ss");
}
} catch (Exception e) {
// log
}
return str;
}
public static void cmp17() {
String dateStr = "2023-07-01 00:00";
System.out.println(specialDateStr2Str(dateStr));
LocalDateTime dateTime = DateUtils.str2DateTime(dateStr, "[yyyy/MM/dd HH:mm:ss][yyyy/MM/dd HH:mm][yyyy-MM-dd HH:mm:ss][yyyy-MM-dd HH:mm]");
System.out.println(DateUtils.dateTime2Str(dateTime, "yyyy-MM-dd HH:mm:ss"));
}
public static void main(String[] args) {
cmp1();
cmp2();
cmp3();
cmp4();
cmp5();
cmp6();
cmp7();
cmp8();
cmp9();
cmp10();
cmp11();
cmp12();
cmp13();
cmp14();
cmp15();
cmp16();
cmp17();
}
}