随着数据库的发展, 数据库DAO层框架也蓬勃发展. 从一开始的JDBC, 到Mybaties与Mybaties plus, 再到SpringData. 持久层框架一直在发展, 这种良性的发展更加推动程序员专注业务方面的发展, 而不是花费过多的经历去编写基本的DAO操作. 在最近的项目中使用了mybatis-plus框架,这个框架自动生成映射文件的工具会将MySQL中的datetime类型转化成Java中的LocalDateTime类型. 为什么mybaties plus 框架会选择LocalDateTime来取代原来的时间类Date呢?
在Java8之前,处理日期时间的类是Date、Calendar,这两个在使用起来总是让人感觉不是很舒服,在设计上面有一些缺陷,并且java.util.Date和SimpleDateFormatter都不是线程安全的. 作为JDK1.8 推出的LocalDate、LocalTime、LocalDateTime这个三个时间处理类,主要用来弥补之前的日期时间类的不足,简化日期时间的操作.
LocalDateTime的优势包括:
而在学习这个时间类之前, 我们需要简单了解下UTC/GMT
UTC/GMT
@Test
public void testGMT() {
try {
//获取Date对象,存放的是时间戳
Date date = new Date();
//获取时间戳(毫秒)
long seconds = date.getTime();
System.out.println("当前时间戳: " + seconds);
//当前GMT(格林威治)时间、当前计算机系统所在时区的时间
SimpleDateFormat beijingFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("本地(东八区)时间: " + beijingFormat.format(date) +"; GMT时间: " + date.toGMTString());
//东八区时间转换成东九区(东京)时间,比北京早一个小时
SimpleDateFormat tokyoFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
tokyoFormat.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo"));
System.out.println("东京(东九区)时间: "+tokyoFormat.format(date));
//时间戳转化成Date
SimpleDateFormat timestampFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formatString = timestampFormat.format(seconds);
Date parseDate = timestampFormat.parse(formatString);
System.out.println("时间戳转化成Date之后的时间: "+parseDate + ";格式化之后的: "+ formatString);
System.out.println("Date时间 = " + new Date());
} catch (Exception e) {
e.printStackTrace();
}
}
LocalDate: 日期类, 只针对日期类型的处理, 类似Calender
@Test
public void testLocalDate() {
// 获取今天的日期
LocalDate today = LocalDate.now();
System.out.println("获取今天的日期 = " + today);
// 构造日期LocalDate(严格按照yyyy-MM-dd验证,02写成2都不行,当然也有一个重载方法允许自己定义格式 )
LocalDate localDate = LocalDate.parse("2023-02-01");
System.out.println("将String类型日期格式化成LocalDate类型 = " + localDate);
// 将LocalDate格式化成字符串
DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String text = today.format(formatters);
System.out.println("将LocalDate格式化成字符串 = " + text);
// 今天是几号
int dayUfMonth = today.getDayOfMonth();
System.out.println("今天是几号 = " + dayUfMonth);
// 今天是周几(返回的是个枚举类型,需要再getValue())
int dayOfWeek = today.getDayOfWeek().getValue();
System.out.println("今天是周几 = " + dayOfWeek);
// 今天是今年中的第几天
int dayOfYear = today.getDayOfYear();
System.out.println("今天是今年中的第几天 = " + dayOfYear);
// 获取当前月份
int value = today.getMonth().getValue();
System.out.println("今天是第几月 = " + value);
// 获取当前年份
int year = today.getYear();
System.out.println("当前年份 = " + year);
// 判断当前年份是否是闰年
boolean leapYear = today.isLeapYear();
System.out.println("是否是闰年 = " + leapYear);
// 判断当月有几天
int length = today.getMonth().length(leapYear);
System.out.println("当月有几天 = " + length);
// 获取当天开始时间(获取的是年月日类型的)
LocalDateTime localDateTime = today.atStartOfDay();
System.out.println("获取当天开始时间 = " + localDateTime); //2023-02-01T00:00
// 设置当前月份的指定天数的日期
LocalDate dayOfMonth = today.withDayOfMonth(3);
System.out.println("当前月份的指定天数的日期 = " + dayOfMonth);
// 设置当前年份指定天数的日期
LocalDate dayOfYear1 = today.withDayOfYear(15);
System.out.println("当前年份指定天数的日期 = " + dayOfYear1);
// 当前日期向后推几天
LocalDate plusDays = today.plusDays(4);
System.out.println("当前日期向后推4天 = " + plusDays);
// 当前日期向后推几个时间单位
LocalDate plusWeeks = today.plus(4, ChronoUnit.WEEKS);
System.out.println("当前日期向后推4个星期 = " + plusWeeks);
// 取本月第1天:
LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth());
System.out.println("本月第1天 = " + firstDayOfThisMonth);
// 取本月第2天:
LocalDate secondDayOfThisMonth = today.withDayOfMonth(2);
System.out.println("本月第2天 = " + secondDayOfThisMonth);
// 取本月最后一天,再也不用计算是28,29,30还是31:
LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("本月最后一天 = " + lastDayOfThisMonth);
// 取下一天:
LocalDate firstDayOfNextMonth = lastDayOfThisMonth.plusDays(1);
System.out.println("本月最后一天的下一天 = " + firstDayOfNextMonth);
// 取2023年2月第一个周一:
LocalDate firstMondayOf2023= LocalDate.parse("2023-02-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
System.out.println("2023年2月第一个周一 = " + firstMondayOf2023);
}
LocalTime 只对时分秒纳秒做出处理
@Test
public void testLocalTime() {
// 获取当前时间
LocalTime localTime = LocalTime.now();
System.out.println("当前时间 = " + localTime); //16:45:10.764
// 构造时间
LocalTime zero = LocalTime.of(0, 0, 0);
System.out.println("构造时间方法1 = " + zero);
LocalTime mid = LocalTime.parse("12:00:00");
System.out.println("构造时间方法2 = " + mid);
// 获取当前时间分钟数
int minute = localTime.getMinute();
System.out.println("当前时间分钟数 = " + minute);
// 当前时间向后推指定分钟数
LocalTime plusMinutes = localTime.plusMinutes(10);
System.out.println("当前时间向后推10分钟 = " + plusMinutes);
// 当前时间向后增加几个时间单位
LocalTime plusUnit = localTime.plus(1, ChronoUnit.MINUTES);
System.out.println("前时间向后增加1分钟 = " + plusUnit);
// 根据指定的单位计算到另一个时间为止的时间量
long until = localTime.until(mid, ChronoUnit.HOURS);
System.out.println("当前时间到12点的时间差(小时) = " + until);
// 判断此时间是否在指定时间之后。
boolean after = localTime.isAfter(mid);
System.out.println("当前时间是否在12时之后 = " + after);
// 判断此时间和指定时间大小(大:1, 等于:0, 小于:-1)
int i = localTime.compareTo(mid);
System.out.println("当前时间和12时进行比较 = " + i);
}
LocalDateTime 同时可以处理年月日和时分秒, 类似Date类. 并且可以通过LocalDateTime 来获得LocalTime 和LocalDate , 来对日期和时间进行处理
@Test
public void testLocalDateTime() {
// 获取当前年月日时分秒信息(时期)
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("当前年月日时分秒 = " + localDateTime); //2023-02-01T17:43:23.105, 这里的表示分隔符, 将日期和时间分开
// 转换成LocalDate和LocalTime
LocalDate localDate = localDateTime.toLocalDate();
LocalTime localTime = localDateTime.toLocalTime();
// 当前LocalDateTime时间转指定格式字符串*
String localDateTimeStr = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("当前时间转指定格式字符串 = " + localDateTimeStr);
// 将字符串转换成LocalDateTime*
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime parse = LocalDateTime.parse(localDateTimeStr, df);
System.out.println("当字符串转换成时间 = " + parse);
// 将localDateTime转换成Date
Date from = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
System.out.println("将localDateTime转换成Date = " + from);
// 将Date转换成将localDateTime转换成Date
LocalDateTime ldt = Instant.ofEpochMilli(from.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
System.out.println("将Date转换成将localDateTime转换成Date = " + ldt);
// 获取当前日期相关api
DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();
System.out.println("当前是周几 = " + dayOfWeek); //WEDNESDAY
// 获取当前时间相关api
int hour = localDateTime.getHour();
System.out.println("获取当前小时 = " + hour);
// 当前时期几天后的时间
LocalDateTime plusDays = localDateTime.plusDays(1);
System.out.println("当前时期一天后的时间 = " + plusDays);
// 当前时期是否在指定时期之后
boolean after = localDateTime.isAfter(ldt);
System.out.println("当前时期是否在指定时期之后 = " + after);
// 指定当前减去几小时
LocalDateTime minusHours= localDateTime.minusHours(2);
System.out.println("指定当前减去2小时 = " + minusHours);
}
LocalDateTime, LocalDateTime, LocalTime 与Date, String互转的工具类
主要方法:
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;
/**
* info:LocalDateTime,LocalDate,LocalTime 与Date, String转换的工具类
*
* @Author caoHaiYang
* @Date 2023/02/01 11:11
*/
public class LocalDateTimeConvertUtils {
//===================================LocalDateTime=========================================
/**
* 获取当前时间
*
* @return
*/
public static LocalDateTime now() {
return LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
}
/**
* LocalDateTime转Date
* @param localDateTime
* @return
*/
public static Date asDate(LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
/**
* Date转LocalDateTime
* @param date
* @return
*/
public static LocalDateTime asLocalDateTime(Date date) {
return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
}
/**
* String转LocalDateTime
* @param dateStr
* @return
*/
public static LocalDateTime asLocalDateTime(String dateStr) {
return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
/**
* LocalDateTime转String
* @param localDateTime
* @return yyyy-MM-dd HH:mm:ss
*/
public static String asLocalDateTimeStr(LocalDateTime localDateTime) {
return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
//===============================================localDate=====================================
/**
* LocalDate转date
* @param localDate
* @return
*/
public static Date asDate(LocalDate localDate) {
return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
}
/**
* Date转LocalDate
* @param date
* @return
*/
public static LocalDate asLocalDate(Date date) {
return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
}
/**
* String转LocalDate
* @param dateStr 构造日期LocalDate(严格按照yyyy-MM-dd验证,02写成2都不行,当然也有一个重载方法允许自己定义格式)
* @return
*/
public static LocalDate asLocalDate(String dateStr) {
return LocalDate.parse(dateStr);
}
/**
* 将LocalDate转成String
* @param localDate
* @return
*/
public static String asLocalDateStr(LocalDate localDate) {
// 将LocalDate格式化成字符串
return localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}
//====================================LocalTime=============================================
/**
* String转LocalTime
* @param localTImeStr HH:mm:ss
*/
public static LocalTime asLocalTime(String localTImeStr) {
return LocalTime.parse(localTImeStr);
}
/**
* LocalTime转String
* @param localTimeStr
* @return
*/
public static String asLocalTimeStr(LocalTime localTimeStr) {
return localTimeStr.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
}
}
人生难免糊涂, 也难得糊涂/Hutool. 作为最牛的工具类库, hutool也提供了对 LocalDateTime相关操作的工具类 只需要引入相关jar即可调用, 非常方便. 另外hutool的其他工具类也可以了解下, 非常方便开发. 如果后面有时间, 我也会单开一期hutool工具类库的介绍, 欢迎大家多多点赞支持~
需要引入相关jar
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.22</version>
</dependency>
@Test
public void testHutoolLocalDateTimeUtil() {
// 创建两个时间
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime startTime = LocalDateTime.parse("2023-02-02 10:10:10", df);
LocalDateTime endTime = LocalDateTime.parse("2023-02-02 11:11:11", df);
// 计算时间差
long l = LocalDateTimeUtil.between(startTime, endTime).toMinutes();
System.out.println("时间差(分钟) = " + l);
// 获取当前开始时间和结束时间
LocalDateTime beginOfDay = LocalDateTimeUtil.beginOfDay(startTime);
LocalDateTime endOfDay = LocalDateTimeUtil.endOfDay(beginOfDay);
System.out.println("当天开始时间 = " + beginOfDay + "当天结束时间: " + endOfDay);
// 利用工具类创建时间
LocalDateTime parseDate = LocalDateTimeUtil.parse("2023-02-02 12:12:12", "yyyy-MM-dd HH:mm:ss");
System.out.println("利用工具类创建时间 = " + parseDate);
}
c站某大神的, 博客底部最后一个链接就是传送门
该工具类常见api如下:
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.TemporalUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
/**
* info:LocalDateTime工具类
*
* @Author caoHaiYang
* @Date 2023/2/2 16:25
*/
public class LocalDateTimeUtil{
/**
* 时间格式
*/
private static final String YYYY_MM_DD_HH_MM_SS_SSS = "yyyy-MM-dd HH:mm:ss.SSS";
private static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
private static final String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
private static final String YYYY_MM_DD_HH = "yyyy-MM-dd HH";
private static final String YYYY_MM_DD = "yyyy-MM-dd";
private static final String YYYY_MM = "yyyy-MM";
private static final String YYYY = "yyyy";
/**
* 获取时间类型
* 1-包含开始和结束时间(默认)
* 2-包含结束-不包含开始时间 // 开始时间+1天
* 3-包含开始-不包含结束时间 // 结束时间-1天
* 4-不包含开始和结束时间 // 开始时间+1天 or 结束时间-1天
*/
private static final int BETWEEN_TYPE_ONE = 1;
private static final int BETWEEN_TYPE_TWO = 2;
private static final int BETWEEN_TYPE_THREE = 3;
private static final int BETWEEN_TYPE_FOUR = 4;
private static Random random;
static {
try {
random = SecureRandom.getInstanceStrong();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
/**
* 判断时间 小于
* <P> t1 < t2 = true (如:2019-10-13 11:11:00 < 2020-11-13 13:13:00 = true) </P>
*
* @author wangsong
*/
public static boolean isBefore(LocalDateTime t1, LocalDateTime t2) {
return t1.isBefore(t2);
}
/**
* 判断时间 大于
* <P> t1 > t2 = true </P>
*
* @author wangsong
*/
public static boolean isAfter(LocalDateTime t1, LocalDateTime t2) {
return t1.isAfter(t2);
}
/**
* 自构建 LocalDateTime ==> 年,月,日,时,分
*
* @author wangsong
*/
public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute) {
return LocalDateTime.of(year, month, dayOfMonth, hour, minute);
}
/**
* 自构建 LocalDateTime ==> 年,月,日,时,分,秒,毫秒(精确到9位数)
*
* @author wangsong
*/
public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond) {
return LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nanoOfSecond);
}
//============================================== 时间获取 =================================================
/**
* 获取指定某一天的开始时间 00:00:00
*
* @param time
* @return java.time.LocalDateTime
* @author wangsong
* @date 2020/12/24 0024 15:10
* @version 1.0.1
*/
public static LocalDateTime getDayStart(LocalDateTime time) {
return time.withHour(0)
.withMinute(0)
.withSecond(0)
.withNano(0);
}
/**
* 获取指定某一天的结束时间 23:59:59.999999
*
* @author wangsong
*/
public static LocalDateTime getDayEnd(LocalDateTime time) {
// 年 月 天 时 分 秒 毫秒(这里精确到6位数)
return time.withHour(23)
.withMinute(59)
.withSecond(59)
.withNano(999999);
}
/**
* 获取指定时间是周几 1到7
*
* @author wangsong
*/
public static int week(LocalDateTime time) {
return time.getDayOfWeek().getValue();
}
/**
* 获取指定时间之后的日期
* <P> 根据field不同加不同值 , field为ChronoUnit.*
* 秒 ChronoUnit.SECONDS
* 分 ChronoUnit.MINUTES
* 时 ChronoUnit.HOURS
* 半天 ChronoUnit.HALF_DAYS
* 天 ChronoUnit.DAYS
* 月 ChronoUnit.MONTHS
* 年 ChronoUnit.YEARS
* </P>
*
* @author wangsong
*/
public static LocalDateTime plus(LocalDateTime time, long number, TemporalUnit field) {
return time.plus(number, field);
}
/**
* 获取两个日期的时间差
*
* @param startTime 开始时间
* @param endTime 计算时间
* @param field 根据field不同减不同值 , field 为 ChronoUnit.*
* @return startTime小 endTime大 返回正数,则反之
* @author wangsong
* <p>
* 秒 ChronoUnit.SECONDS
* 分 ChronoUnit.MINUTES
* 时 ChronoUnit.HOURS
* 半天 ChronoUnit.HALF_DAYS
* 天 ChronoUnit.DAYS
* 月 ChronoUnit.MONTHS
* 年 ChronoUnit.YEARS
* </P>
*/
public static long betweenTwoTime(LocalDateTime startTime, LocalDateTime endTime, ChronoUnit field) {
Period period = Period.between(LocalDate.from(startTime), LocalDate.from(endTime));
if (field == ChronoUnit.YEARS) {
return period.getYears();
}
if (field == ChronoUnit.MONTHS) {
return period.getYears() * 12L + period.getMonths();
}
return field.between(startTime, endTime);
}
/**
* 获取指定时间之前的日期
*
* @author wangsong
* <P> 根据field不同减不同值, field 为 ChronoUnit.*
* 秒 ChronoUnit.SECONDS
* 分 ChronoUnit.MINUTES
* 时 ChronoUnit.HOURS
* 半天 ChronoUnit.HALF_DAYS
* 天 ChronoUnit.DAYS
* 月 ChronoUnit.MONTHS
* 年 ChronoUnit.YEARS
* </P>
* @version 1.0.1
*/
public static LocalDateTime subtract(LocalDateTime time, long number, TemporalUnit field) {
return time.minus(number, field);
}
/**
* 获取指定时间 加或减N周的第一天 00:00:00
*
* @author wangsong
*/
public static LocalDateTime weekFirstDay(LocalDateTime time, int num) {
int week = week(LocalDateTime.now());
LocalDateTime newTime = subtract(LocalDateTime.now(), week - 1L, ChronoUnit.DAYS);
newTime = plus(newTime, num * 7L, ChronoUnit.DAYS);
return getDayStart(newTime);
}
/**
* 获取指定时间 加或减N周的最后一天 23:59:59:999999
*
* @author wangsong
*/
public static LocalDateTime weekLastDay(LocalDateTime time, int num) {
int week = week(LocalDateTime.now());
LocalDateTime newTime = plus(LocalDateTime.now(), 7L - week, ChronoUnit.DAYS);
newTime = plus(newTime, num * 7L, ChronoUnit.DAYS);
return getDayEnd(newTime);
}
/**
* 获取指定月 加或减N月的第一天 00:00:00
*
* @author wangsong
*/
public static LocalDateTime monthFirstDay(LocalDateTime time, int num) {
LocalDateTime newTime = plus(time, num, ChronoUnit.MONTHS);
newTime = newTime.with(TemporalAdjusters.firstDayOfMonth());
return getDayStart(newTime);
}
/**
* 获取指定月 加或减N月的最后一天 23:59:59:999999
*
* @author wangsong
*/
public static LocalDateTime monthLastDay(LocalDateTime time, int num) {
LocalDateTime newTime = plus(time, num, ChronoUnit.MONTHS);
newTime = newTime.with(TemporalAdjusters.lastDayOfMonth());
return getDayEnd(newTime);
}
/**
* 获取指定年 加或减N年的第一天 00:00:00
*
* @author wangsong
*/
public static LocalDateTime yearFirstDay(LocalDateTime time, int num) {
LocalDateTime newTime = plus(time, num, ChronoUnit.YEARS);
int year = newTime.getYear();
// 年 月 天 时 分 秒 毫秒(这里精确到9位数)
return LocalDateTime.of(year, 1, 1, 0, 0, 0);
}
/**
* 获取指定年 加或减N年最后一天 23:59:59:999999
*
* @author wangsong
*/
public static LocalDateTime yearLastDay(LocalDateTime time, int num) {
LocalDateTime newTime = subtract(time, num, ChronoUnit.YEARS);
int year = newTime.getYear();
// 年 月 天 时 分 秒 毫秒(这里精确到6位数)
return LocalDateTime.of(year, 12, 31, 23, 59, 59, 999999);
}
/**
* 获取17位时间戳字符串+3位随机数
* <p> 这里增加了线程锁和延时一毫秒,单体项目100%不会重复,可用于生成订单号 </p>
* 20200101125959999 2020-01-01 12:59:59:999
*
* @return
* @author wangsong
*/
public static synchronized String getNo() {
String timeStamp = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
timeStamp += (random.nextInt(10) + "") + (random.nextInt(10) + "") + (random.nextInt(10) + "");
return timeStamp;
}
/**
* 获取整点-- 把指定时间的 分+秒设置为0
*
* @param time time
* @return java.time.LocalDateTime
* @author wangsong
* @date 2020/12/24 0024 15:10
* @version 1.0.1
*/
public static LocalDateTime getTheHour(LocalDateTime time) {
// 分 // 秒 // 毫秒(这里精确到9位数)
return time.withMinute(0)
.withSecond(0)
.withNano(0);
}
/**
* 获取整分-- 把指定时间的 秒设置为0
* <p>
// * 如:
// * 2020-01-01 12:10 ===> 等于 2020-01-01 12:20
// * 2020-01-01 12:11 ===> 等于 2020-01-01 12:20
// * 2020-01-01 12:19 ===> 等于 2020-01-01 12:20
* </P>
*
* @param time
* @return java.time.LocalDateTime
* @author wangsong
* @date 2020/12/24 0024 15:21
* @version 1.0.1
*/
public static LocalDateTime getTheMinute(LocalDateTime time) {
// 秒 // 毫秒(这里精确到9位数)
return time.withSecond(0).withNano(0);
}
//============================================== 转换相关 =================================================
/**
* LocalDateTime 转为 天 的字符串,如 1号返回 01
*
* @author wangsong
*/
public static Integer parseDayInt(LocalDateTime time) {
return Integer.parseInt(parse(time, "dd"));
}
/**
* Date 转 LocalDateTime
*
* @author wangsong
*/
public static LocalDateTime parseLdt(Date date) {
return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}
/**
* LocalDateTime 转 Date
*
* @author wangsong
*/
public static Date parseDate(LocalDateTime time) {
return Date.from(time.atZone(ZoneId.systemDefault()).toInstant());
}
/**
* LocalDateTime 转 毫秒
*
* @author wangsong
*/
public static Long parseMillisecond(LocalDateTime time) {
return time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}
/**
* LocalDateTime 转 秒
*
* @author wangsong
*/
public static Long parseSecond(LocalDateTime time) {
return time.atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
}
/**
* 将时间戳转 为 LocalDateTime
*
* @param timestamp
* @return java.lang.String
* @author wangsong
* @date 2021/5/12 0012 17:13
* @version 1.0.1
*/
public static LocalDateTime parseTimestamp(Long timestamp) {
return LocalDateTime.ofEpochSecond(timestamp / 1000, 0, ZoneOffset.ofHours(8));
}
/**
* 将LocalDateTime 转 为时间戳
*
* @return java.lang.String
* @author wangsong
* @date 2021/5/12 0012 17:13
* @version 1.0.1
*/
public static Long parseTimestamp(LocalDateTime time) {
return time.toEpochSecond(ZoneOffset.ofHours(8));
}
/**
* String 类型转成 LocalDateTime ,必须为完整时间,如:2020-01-20 00:00:00
*
* @param timeStr 时间字符串
* @return java.time.LocalDateTime
*/
public static LocalDateTime parse(String timeStr) {
return parse(timeStr, YYYY_MM_DD_HH_MM_SS);
}
/**
* String (2020-01-20 00:00:00)类型转成 LocalDateTime
*
* @param timeStr timeStr 时间字符串
* @param pattern pattern 格式
* @return java.time.LocalDateTime
*/
public static LocalDateTime parse(String timeStr, String pattern) {
if (pattern.equals(YYYY)) {
timeStr += "-01-01 00:00:00";
} else if (pattern.equals(YYYY_MM)) {
timeStr += "-01 00:00:00";
} else if (pattern.equals(YYYY_MM_DD)) {
timeStr += " 00:00:00";
} else if (pattern.equals(YYYY_MM_DD_HH)) {
timeStr += ":00:00";
} else if (pattern.equals(YYYY_MM_DD_HH_MM)) {
timeStr += ":00";
}
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);
return LocalDateTime.parse(timeStr, dtf);
}
/**
* LocalDateTime 转完整 String 类型的时间 如:2020-01-20 00:00:00
*
* @param time time
* @return java.lang.String
*/
public static String parse(LocalDateTime time) {
return parse(time, YYYY_MM_DD_HH_MM_SS);
}
/**
* LocalDateTime 转指定类型的字符串
*
* @param time time 时间
* @param pattern pattern 格式
*
* @return java.lang.String
* @author wangsong
*/
public static String parse(LocalDateTime time, String pattern) {
if (time == null) {
return null;
}
DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
return df.format(time);
}
/**
* Date 转指定格式的字符串
*
* @param time
* @author wangsong
*/
public static String parse(Date time, String pattern) {
if (time == null) {
return null;
}
SimpleDateFormat format = new SimpleDateFormat(pattern);
return format.format(time);
}
/**
* 获取指定天的24小时(0-23) | yyyy-MM-dd HH 格式
*
* @param t 开始月
* @return
*/
public static List<String> getDay24Hour(LocalDateTime t) {
if (t == null) {
return new ArrayList<>();
}
List<String> times = new ArrayList<>();
String time = parse(t, YYYY_MM_DD);
int hourNum = 24;
for (int i = 0; i < hourNum; i++) {
if (i < 10) {
times.add(time + " 0" + i);
} else {
times.add(time + " " + i);
}
}
return times;
}
/**
* 获取每一天的时间 (指定时间 前n月前的第一天 到 n月后的最后一天的所有时间)
* <P> 一天一条数据 List<DateDays> </P>
*
* @param startNum 前n月,当前月开始为 0
* @param endNum 后n月,当前月就是为 0
* @return java.util.List<com.lplb.common.utils.LocalDateTimeUtil.DateDays>
* @author wangsong
*/
public static List<DateDays> getBetweenDaysUpListByMonth(LocalDateTime time, Integer startNum, Integer endNum) {
// 本月第一天 00:00:00
LocalDateTime startTime = monthFirstDay(time, startNum);
// n月后的最后一天 23:59:59.999
LocalDateTime endTime = monthLastDay(time, endNum);
return getBetweenDaysUpList(startTime, endTime, BETWEEN_TYPE_ONE);
}
/**
* 获取每一天的时间 (指定开始时间和结束时间)
* <P>
* 一天一条数据 List<DateDays>
* 返回数据包括 开始时间 和 结束时间 的当天数据
* </P>
*
* @param startTime 开始时间 (时分秒已开始时间位为准)
* @param endTime 结束时间
* @param type 1-包含开始和结束时间 2-包含结束-不包含开始时间 3-包含开始-不包含结束时间 4-不包含开始和结束时间
* @return java.util.List<com.lplb.common.utils.LocalDateTimeUtil.DateDays>
* @author wangsong
*/
public static List<DateDays> getBetweenDaysUpList(LocalDateTime startTime, LocalDateTime endTime, Integer type) {
List<DateDays> dateDaysList = new ArrayList<>();
List<LocalDateTime> betweenList = getBetweenDaysList(startTime, endTime, type);
for (LocalDateTime localDateTime : betweenList) {
dateDaysList.add(new DateDays(localDateTime, week(localDateTime)));
}
return dateDaysList;
}
/**
* 获取指定开始时间到指定结束时间的每一天, 包括开始时间,不包括结束时间,如:2020-5-16到2020-5-18 获得时间为:[2020-5-16,2020-5-17]
*
* @param startTime
* @param endTime
* @param type 1-包含开始和结束时间 2-包含结束-不包含开始时间 3-包含开始-不包含结束时间 4-不包含开始和结束时间
* @return java.util.List<java.time.LocalDateTime>
* @author wangsong
* @date 2020/12/24 0024 15:16
* @version 1.0.1
*/
public static List<LocalDateTime> getBetweenDaysList(LocalDateTime startTime, LocalDateTime endTime, Integer type) {
// 指定开始时间 00:00:00 // 指定结束时间 00:00:00
LocalDateTime oldStartTime = getDayStart(startTime);
LocalDateTime oldEndTime = getDayStart(endTime);
// 1-包含开始和结束时间(默认) BetweenType
// 2-包含结束-不包含开始时间 // 开始时间+1天
// 3-包含开始-不包含结束时间 // 结束时间-1天
// 4-不包含开始和结束时间 // 开始时间+1天 or 结束时间-1天
if (type == BETWEEN_TYPE_TWO) {
oldStartTime = plus(oldStartTime, 1, ChronoUnit.DAYS);
} else if (type == BETWEEN_TYPE_THREE) {
oldEndTime = subtract(endTime, 1, ChronoUnit.DAYS);
} else if (type == BETWEEN_TYPE_FOUR) {
oldStartTime = plus(oldStartTime, 1, ChronoUnit.DAYS);
oldEndTime = subtract(endTime, 1, ChronoUnit.DAYS);
}
// 返回数据
List<LocalDateTime> everyDays = new ArrayList<>();
// 第一天数据
everyDays.add(oldStartTime);
while (true) {
// 获取之后的每一天时间
LocalDateTime nextDay = plus(everyDays.get(everyDays.size() - 1), 1, ChronoUnit.DAYS);
// 大于最后一天-跳出循环
if (isAfter(nextDay, oldEndTime)) {
break;
}
everyDays.add(nextDay);
}
return everyDays;
}
/**
* 获取月 (返回每一个月的字串, yyyy-MM 格式)
* <p> 包含结束月,不包含开始月 </>
*
* @param startTime 开始月
* @param endTime 结束月
* @return
*/
public static List<String> getBetweenMonthsList(LocalDateTime startTime, LocalDateTime endTime) {
List<String> times = new ArrayList<>();
if (startTime != null && endTime != null) {
// 获取开始月的第一天
endTime = monthFirstDay(endTime, 0);
times.add(parse(startTime, YYYY_MM));
while (isBefore(startTime, endTime)) {
startTime = plus(startTime, 1, ChronoUnit.MONTHS);
times.add(parse(startTime, YYYY_MM));
}
}
return times;
}
/**
* 获取日期端的数据保存对象
*
* @author ws
* @mail 1720696548@qq.com
* @date 2020/5/7 0007 9:41
*/
public static class DateDays {
// 当天时间- 年月日/00:00:00
private LocalDateTime dayTime;
// 当天是周几
private int week;
public DateDays(LocalDateTime dayTime, int week) {
this.dayTime = dayTime;
this.week = week;
}
public LocalDateTime getDayTime() {
return dayTime;
}
public void setDayTime(LocalDateTime dayTime) {
this.dayTime = dayTime;
}
public int getWeek() {
return week;
}
public void setWeek(int week) {
this.week = week;
}
}
}
时间处理工具类, 主要包含以下方法. 这里主要使用的Date类型的, 但是随着后面需要可以手动替换成LocalDateTime类型的
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
/**
* 时间处理工具
*
* @author lvyi
* @date 2021/2/23
*/
public class TimeUtil {
private static final String FORMAT = "yyyy-MM-dd HH:mm:ss";
/**
* 获取两个日期之间的所有年
*
* @param startTime
* @param endTime
* @return:list
*/
public static List<String> getYearBetweenDate(String startTime, String endTime) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
// 声明保存日期集合
List<String> list = new ArrayList<>();
try {
// 转化成日期类型
Date startDate = sdf.parse(startTime);
Date endDate = sdf.parse(endTime);
//用Calendar 进行日期比较判断
Calendar calendar = Calendar.getInstance();
while (startDate.getTime() <= endDate.getTime()) {
// 把日期添加到集合
list.add(sdf.format(startDate));
// 设置日期
calendar.setTime(startDate);
//把年数增加 1
calendar.add(Calendar.YEAR, 1);
// 获取增加后的日期
startDate = calendar.getTime();
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
/**
* 获取两个日期之间的所有月份 (年月)
*
* @param startTime
* @param endTime
* @return:list
*/
public static List<String> getMonthBetweenDate(String startTime, String endTime) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
// 声明保存日期集合
List<String> list = new ArrayList<>();
try {
// 转化成日期类型
Date startDate = sdf.parse(startTime);
Date endDate = sdf.parse(endTime);
//用Calendar 进行日期比较判断
Calendar calendar = Calendar.getInstance();
while (startDate.getTime() <= endDate.getTime()) {
// 把日期添加到集合
list.add(sdf.format(startDate));
// 设置日期
calendar.setTime(startDate);
//把月数增加 1
calendar.add(Calendar.MONTH, 1);
// 获取增加后的日期
startDate = calendar.getTime();
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
/**
* 获取两个日期之间的所有日期 (年月日)
*
* @param startTime
* @param endTime
* @return
*/
public static List<String> getBetweenDate(String startTime, String endTime){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 声明保存日期集合
List<String> list = new ArrayList<String>();
try {
// 转化成日期类型
Date startDate = sdf.parse(startTime);
Date endDate = sdf.parse(endTime);
//用Calendar 进行日期比较判断
Calendar calendar = Calendar.getInstance();
while (startDate.getTime()<=endDate.getTime()){
// 把日期添加到集合
list.add(sdf.format(startDate));
// 设置日期
calendar.setTime(startDate);
//把日期增加一天
calendar.add(Calendar.DATE, 1);
// 获取增加后的日期
startDate=calendar.getTime();
}
} catch (ParseException e) {
e.printStackTrace();
}
return list;
}
/**
* 返回两个时间相差多少时间单位
* @param startTime
* @param endTime
* @param str d-天,h-小时,m-分钟,s-秒 表示返回相差的时间单位
* @return
*/
public static Long dateDiff(String startTime, String endTime, String str) {
// 按照传入的格式生成一个simpledateformate对象
SimpleDateFormat sd = new SimpleDateFormat(FORMAT);
// 一天的毫秒数
long nd = 1000 * 24 * 60 * 60;
// 一小时的毫秒数
long nh = 1000 * 60 * 60;
// 一分钟的毫秒数
long nm = 1000 * 60;
// 一秒钟的毫秒数
long ns = 1000;
long diff;
long day = 0;
long hour = 0;
long min = 0;
long sec = 0;
String result = "0";
// 获得两个时间的毫秒时间差异
try {
diff = sd.parse(endTime).getTime() - sd.parse(startTime).getTime();
// 计算差多少天
day = diff / nd;
// 计算差多少小时
hour = diff % nd / nh + day * 24;
// 计算差多少分钟
min = diff % nd % nh / nm + day * 24 * 60;
// 计算差多少秒
sec = diff % nd % nh % nm / ns;
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// log.info("时间相差:" + day + "天" + (hour - day * 24) + "小时"
// + (min - day * 24 * 60) + "分钟" + sec + "秒。");
if ("d".equalsIgnoreCase(str)) {
return day;
} else if ("h".equalsIgnoreCase(str)) {
return hour;
} else if ("m".equalsIgnoreCase(str)) {
return min;
} else if ("s".equalsIgnoreCase(str)) {
return sec;
} else {
return 0L;
}
}
/**
* 判断当前时间 是否在一个时间段内(时分秒)
*
* @param timeBegin
* @param timeEnd
* @return
* @throws ParseException
*/
public static boolean compareForHour(String timeBegin, String timeEnd) throws ParseException {
boolean flag = false;
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
Date date = new Date();
String timeNow = format.format(date);
Date begin = format.parse(timeBegin);
Date end = format.parse(timeEnd);
Date now = format.parse(timeNow);
if (now.compareTo(begin) > 0 && now.compareTo(end) < 0) {
flag = true;
}
return flag;
}
/**
* 判断当前时间 是否在一个时间段内(年月日时分秒)
*
* @param timeBegin
* @param timeEnd
* @return
* @throws ParseException
*/
public static boolean compareForTime(String timeBegin, String timeEnd) throws ParseException {
boolean flag = false;
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date();
String timeNow = format.format(date);
Date begin = format.parse(timeBegin);
Date end = format.parse(timeEnd);
Date now = format.parse(timeNow);
if (now.compareTo(begin) > 0 && now.compareTo(end) < 0) {
flag = true;
}
return flag;
}
/**
* 获取指定月份有多少天
*
* @param year
* @param month
* @return
*/
public static int getDaysByYearMonth(int year, int month) {
Calendar a = Calendar.getInstance();
a.set(Calendar.YEAR, year);
a.set(Calendar.MONTH, month - 1);
a.set(Calendar.DATE, 1);
a.roll(Calendar.DATE, -1);
int maxDate = a.get(Calendar.DATE);
return maxDate;
}
/**
* 根据日期取得星期几
* @param year
* @param month
* @param day
* @return
*/
public static String getWeek(int year, int month, int day) {
Calendar a = Calendar.getInstance();
a.set(Calendar.YEAR, year);
a.set(Calendar.MONTH, month - 1);
a.set(Calendar.DATE, day);
Date date = a.getTime();
SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
String week = sdf.format(date);
return week;
}
/**
* 前端时间换算成指定格式
*
* @param oldDate
* @return
*/
public static String dealDateFormat(String oldDate) {
Date date1 = null;
DateFormat df2 = null;
try {
oldDate = oldDate.replace("Z", " UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS Z");
Date date = df.parse(oldDate);
SimpleDateFormat df1 = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.UK);
date1 = df1.parse(date.toString());
df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
} catch (ParseException e) {
e.printStackTrace();
}
return df2.format(date1);
}
/**
* 判断当前时间是单月还是双月,双月返回true
*/
public static boolean getMonthisDouble() {
boolean flag = false;
Date dt = new Date();
int month = dt.getMonth() + 1;
if ((month % 2) == 0) {
flag = true;
}
return flag;
}
/**
* 两个时间做比较,返回大的时间
*
* @param time1
* @param time2
* @return
*/
public static String getMaxTime(String time1, String time2) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String resultTiem = time1;
try {
Date dt1 = df.parse(time1);
Date dt2 = df.parse(time2);
if (dt1.before(dt2)) {
resultTiem = time2;
}
} catch (Exception e) {
e.printStackTrace();
}
return resultTiem;
}
/**
* 比较某一个时间是否是时分秒之内
*
* @param time 当前时间 2021-04-14 10:30:26
* @param beginTime 开始时间 8:00:00
* @param endTime 结束时间 11:00:00
* @return
* @throws ParseException
*/
public static boolean compareDayForHour(String time, String beginTime, String endTime) throws ParseException {
SimpleDateFormat format1 = new SimpleDateFormat("HH:mm:ss");
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date timeNow = format.parse(time);
String strNow = format1.format(timeNow);
Date now = format1.parse(strNow);
Date begin = format1.parse(beginTime);
Date end = format1.parse(endTime);
if (now.compareTo(begin) > 0 && now.compareTo(end) < 0) {
return true;
} else {
return false;
}
}
/**
* 获取当前时间字符串
*
* @return
*/
public static String nowString() {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-ddHH:mm:ss");
return dtf.format(LocalDateTime.now(ZoneId.of("Asia/Shanghai")));
}
/**
* 获取当前时间字符串
*
* @return
*/
public static String nowNumber() {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
return dtf.format(LocalDateTime.now(ZoneId.of("Asia/Shanghai")));
}
}
项目中, 会有一种情况就是需要存储的时间和需要保存的时间精度不一样. 比如说, 前端需要显示年月日时分, 但是后端因为数据库存储的是DateTime类型依然会要求保存年月日时分秒 , 因此就需要在全局对需要返回成Json格式的时间进行全局配置.
FastJSON 配置类中声明返回的时间格式化为指定格式. 项目中使用fastJson的用这个
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.nio.charset.StandardCharsets;
/**
* FastJSON 配置类
*/
@Configuration
public class FastjsonConfig extends FastJsonHttpMessageConverter{
@Bean
FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig config = new FastJsonConfig();
// 解析设置
config.setDateFormat("yyyy-MM-dd HH:mm");
config.setCharset(StandardCharsets.UTF_8);
config.setSerializerFeatures(
SerializerFeature.WriteMapNullValue,
SerializerFeature.PrettyFormat,
SerializerFeature.DisableCircularReferenceDetect
);
// converter.setFastJsonConfig(config);
this.setFastJsonConfig(config);
return converter;
}
@Override
protected boolean supports(Class<?> clazz) {
return super.supports(clazz);
}
}
配置文件中进行全局声明, 项目中使用 Jackson-databind 的使用这个
# 规定全局返回时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm
spring.jackson.time-zone=GMT+8
参考 https://blog.csdn.net/duan196_118/article/details/111597682 https://blog.csdn.net/qq_24754061/article/details/95500209 https://xijia.blog.csdn.net/article/details/106007147