1. 背景
データベースの発展に伴い、データベースのDAO層フレームワークも盛んになり、当初はJDBCから、Mybaties、Mybaties plus、そしてSpringDataへと、永続化層のフレームワークが発展してきており、この無害な発展により、プログラマーは
さらにビジネスの側面に焦点を当てる. 基本的な DAO 操作の記述に多くの経験を費やす代わりに、開発を行う.
最近のプロジェクトでは、mybatis-plus フレームワークが使用されています. このフレームワークは、MySQL の datetime 型を LocalDateTime 型に変換するマッピング ファイル ツールを自動的に生成しますJava. . mybaties plus フレームワークが LocalDateTime を選択して元の時間クラス Date を置き換えるのはなぜですか?
2.はじめに
Java8より前の日付と時刻を扱うクラスはDateとCalendar. この2つは常に使いにくい. 設計にはいくつかの欠陥があり, java.util.DateとSimpleDateFormatterはスレッドセーフではない. 3つ
はJDK1.8としてリリースされた時刻処理クラスLocalDate、LocalTime、LocalDateTimeは、主にこれまでの日時クラスの欠点を補い、日時の操作を簡素化するために使用されます。
LocalDateTime の利点は次のとおりです。
- 最も基本的な文字列と同様に、LocalDate と LocalTime は不変型であり、シングル スレッド セーフではなく、変更できません。
- 日付と時刻を分離します。LocalDate には日付のみを含めることができ、LocalTime には時刻のみを含めることができ、LocalDateTime には日付と時刻の両方を含めることができます。
- java.util.Date は、時間を計算して (数日進める/数日戻す/特定の年、特定の月の最初の日を計算するなど)、Calender を組み合わせて多くのコードを記述します。かなり面倒. LocaDate は対応するメソッドを使用するだけでよい
今回の授業を学ぶ前に、UTC/GMTを簡単に理解する必要があります
UTC/GMT
- プログラムで通常表示される 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();
}
}
3.学習
ローカル日付
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
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);
}
4. ツール
LocalDateTimeConvertUtils
localDateTime、LocalDateTime、LocalTime および Date、String 変換のツール クラス
主な方法:
- 現在の LocalDateTime 時刻を取得する
- LocalDateTime to Date
- 日付から LocalDateTime
- 文字列から LocalDateTime
- LocalDateTime から文字列へ
- LocalDate日付
- Date转LocalDate
- 文字列から LocalDate
- LocalDate を文字列に変換する
- 文字列から LocalTime
- LocalTime から文字列へ
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"));
}
}
LocalDateTimeUtil(フツール)
人生で混乱することは避けられず、混乱することはめったにありません/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);
}
LocalDateTimeUtil
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 [email protected]
* @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;
}
}
}
TimeUtil
時間処理ツール クラスには主に次のメソッドが含まれます.
ここでは主に Date 型が使用されますが、後で必要に応じて手動で LocalDateTime 型に置き換えることができます
- 2 つの日付の間のすべての年を取得する
- 2 つの日付の間のすべての月 (yearmonth) を取得します
- 2 つの日付の間のすべての日付 (年月日) を取得する
- 2 つの時間の時間単位の差を返します
- 現在の時刻が時間帯 (時、分、秒) 内にあるかどうかを判断します。
- 現在の時刻が期間内 (年、月、日、時、分、秒) にあるかどうかを判断します。
- 指定した月の日数を取得する
- 日付から曜日を取得する
- フロントエンド時刻を指定された形式に変換します
- 現在の時刻が 1 か月か隔月かを判断し、隔月の場合は true を返します
- 2 つの時間を比較し、大きい方の時間を返します
- 現在の時刻文字列を取得する
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")));
}
}
5.拡張
LocalDateTime の時刻形式の問題について
プロジェクトでは、保存する必要がある時刻と、保存する必要がある時刻の精度が異なる場合があります.たとえば、フロント
エンドは年、月、日、および時間を表示する必要があります.ですが、データベースには DateTime タイプの seconds が格納されているため、バックエンドでは年、月、日、および時間を保存する必要があります。そのため、 Json
形式で返す必要がある時刻をグローバルに構成する必要があります。
方法1
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);
}
}
方法 2
構成ファイルでグローバル宣言を行い、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