- 一、JDK8中日期时间API的介绍
- 1.1、LocalDate、LocalTime、LocalDateTime的使用
- 2.2、Instant类的使用
- 2.3、DateTimeFormatter的使用
- 2.4、ZoneId, ZonedDateTime, Clock, TemporalAdjuster
- 2.5、参考:与传统日期处理的转换
- 二、时间工具类
java.time包介绍 : https://www.yiibai.com/javatime/javatime_instant.html
1、新日期时间API出现的背景
如果我们可以跟别人说:“我们在1502643933071见面,别晚了!”那么就再简单不过了。但是我们希望时间与昼夜和四季有关,于是事情就变复杂了。JDK 1.0中包含了一个java.util.Date类,但是它的大多数方法已经在JDK 1.1引入Calendar类之后被弃用了。而Calendar并不比Date好多少。它们面临的问题是:
- 可变性:像日期和时间这样的类应该是不可变的。
- 偏移性:Date中的年份是从1900开始的,而月份都从0开始。
- 格式化:格式化只对Date有用,Calendar则不行。
- 此外,它们也不是线程安全的;不能处理闰秒等。
import org.junit.Test;
import java.util.Date;
/**
* jdk 8中日期时间API的测试
*
*/
public class JDK8DateTimeTest {
@Test
public void testDate(){
//偏移量
Date date1 = new Date(2020,9,8);
System.out.println(date1); //Fri Oct 08 00:00:00 CST 3920
Date date2 = new Date(2020 - 1900,9 - 1,8);
System.out.println(date2); //Tue Sep 08 00:00:00 CST 2020
}
}
第三次引入的API是成功的,并且Java 8中引入的java.time
API 已经纠正了过去的缺陷,将来很长一段时间内它都会为我们服务。
Java 8 吸收了Joda-Time 的精华,以一个新的开始为Java 创建优秀的API。新的java.time
中包含了所有关于 本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。历史悠久的Date 类新增了toInstant()
方法,用于把Date 转换成新的表示形式。这些新增的本地化时间日期API 大大简化了日期时间和本地化的管理。
- LocalDate:表示日期,包含:年月日。格式为:2020-01-13
- LocalTime:表示时间,包含:时分秒。格式为:16:39:09.307
- LocalDateTime:表示日期时间,包含:年月日 时分秒。格式为:2020-01-13T16:40:59.138
- DateTimeFormatter:日期时间格式化类
- Instant:时间戳类
- Duration:用于计算 2 个时间(LocalTime,时分秒)之间的差距
- Period:用于计算 2 个日期(LocalDate,年月日)之间的差距
- ZonedDateTime:包含时区的时间
LocalDate、LocalTime、LocalDateTime
类是其中较重要的几个类,它们的实例是不可变的对象,分别表示使用ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。LocalDate
代表IOS格式(yyyy-MM-dd)的日期,可以存储生日、纪念日等日期。LocalTime
表示一个时间,而不是日期。LocalDateTime
是用来表示日期和时间的,这是一个最常用的类之一。
- 注:ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法,也就是公历。
import org.junit.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
* jdk 8中日期时间API的测试
*/
public class JDK8DateTimeTest {
/**
* LocalDate、LocalTime、LocalDateTime的使用
*
*/
@Test
public void test1(){
//now():获取当前的日期、时间、日期+时间
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDate);
System.out.println(localTime);
System.out.println(localDateTime);
//of():设置指定的年、月、日、时、分、秒。没有偏移量
LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 6, 13, 23, 43);
System.out.println(localDateTime1);
//getXxx():获取相关的属性
System.out.println(localDateTime.getDayOfMonth());
System.out.println(localDateTime.getDayOfWeek());
System.out.println(localDateTime.getMonth());
System.out.println(localDateTime.getMonthValue());
System.out.println(localDateTime.getMinute());
//体现不可变性
//withXxx():设置相关的属性
LocalDate localDate1 = localDate.withDayOfMonth(22);
System.out.println(localDate);
System.out.println(localDate1);
LocalDateTime localDateTime2 = localDateTime.withHour(4);
System.out.println(localDateTime);
System.out.println(localDateTime2);
//不可变性
LocalDateTime localDateTime3 = localDateTime.plusMonths(3);
System.out.println(localDateTime);
System.out.println(localDateTime3);
LocalDateTime localDateTime4 = localDateTime.minusDays(6);
System.out.println(localDateTime);
System.out.println(localDateTime4);
}
}
-
Instant
:时间线上的一个瞬时点。这可能被用来记录应用程序中的事件时间戳。 -
java.time
包通过值类型Instant
提供机器视图,不提供处理人类意义上的时间单位。Instant
表示时间线上的一点,而不需要任何上下文信息,例如,时区。概念上讲,它只是简单的表示自1970年1月1日0时0分0秒(UTC)开始的秒数。因为java.time
包是基于纳秒计算的,所以Instant
的精度可以达到纳秒级。
(1 ns = 10-9s) 1秒= 1000毫秒=106微秒=109纳秒
时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。
import org.junit.Test;
import java.time.*;
/**
* jdk 8中日期时间API的测试
*/
public class JDK8DateTimeTest {
/**
* Instant的使用
*/
@Test
public void test2(){
//now():获取本初子午线对应的标准时间
Instant instant = Instant.now();
System.out.println(instant); //2020-05-10T09:55:55.561Z
//添加时间的偏移量
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));//东八区
System.out.println(offsetDateTime); //2020-05-10T18:00:00.641+08:00
//toEpochMilli():获取自1970年1月1日0时0分0秒(UTC)开始的毫秒数 ---> Date类的getTime()
long milli = instant.toEpochMilli();
System.out.println(milli); //1589104867591
//ofEpochMilli():通过给定的毫秒数,获取Instant实例 -->Date(long millis)
Instant instant1 = Instant.ofEpochMilli(1550475314878L);
System.out.println(instant1); //2019-02-18T07:35:14.878Z
}
}
2.3、DateTimeFormatter的使用
java.time.format.DateTimeFormatter
类:该类提供了三种格式化方法:
- 预定义的标准格式。如:
ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
- 本地化相关的格式。如:
ofLocalizedDateTime(FormatStyle.LONG)
- 自定义的格式。如:
ofPattern(“yyyy-MM-dd hh:mm:ss”)
import org.junit.Test;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.TemporalAccessor;
/**
* jdk 8中日期时间API的测试
*/
public class JDK8DateTimeTest {
/**
* DateTimeFormatter:格式化或解析日期、时间
* 类似于SimpleDateFormat
*/
@Test
public void test3(){
//方式一:预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
//格式化:日期-->字符串
LocalDateTime localDateTime = LocalDateTime.now();
String str1 = formatter.format(localDateTime);
System.out.println(localDateTime);
System.out.println(str1);//2020-05-10T18:26:40.234
//解析:字符串 -->日期
TemporalAccessor parse = formatter.parse("2020-05-10T18:26:40.234");
System.out.println(parse);
//方式二:
//本地化相关的格式。如:ofLocalizedDateTime()
//FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT :适用于LocalDateTime
DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
//格式化
String str2 = formatter1.format(localDateTime);
System.out.println(str2);//2020年5月10日 下午06时26分40秒
//本地化相关的格式。如:ofLocalizedDate()
//FormatStyle.FULL / FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT : 适用于LocalDate
DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
//格式化
String str3 = formatter2.format(LocalDate.now());
System.out.println(str3);//2020-5-10
//重点: 方式三:自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
//格式化
String str4 = formatter3.format(LocalDateTime.now());
System.out.println(str4);//2020-05-10 06:26:40
//解析
TemporalAccessor accessor = formatter3.parse("2020-05-10 06:26:40");
System.out.println(accessor);
}
}
2.4、ZoneId, ZonedDateTime, Clock, TemporalAdjuster
- ZoneId:该类中包含了所有的时区信息,一个时区的ID,如Europe/Paris
- ZonedDateTime:一个在ISO-8601日历系统时区的日期时间,如2007-12-03T10:15:30+01:00Europe/Paris。
- 其中每个时区都对应着ID,地区ID都为“{区域}/{城市}”的格式,例如:Asia/Shanghai等
import org.junit.Test;
import java.time.*;
import java.util.Set;
/**
* jdk 8中日期时间API的测试
*/
public class JDK8DateTimeTest {
@Test
public void test1(){
//ZoneId:类中包含了所有的时区信息
// ZoneId的getAvailableZoneIds():获取所有的ZoneId
Set zoneIds= ZoneId.getAvailableZoneIds();
for(String s: zoneIds) {
System.out.println(s);
}
// ZoneId的of():获取指定时区的时间
LocalDateTime localDateTime= LocalDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println(localDateTime);
//ZonedDateTime:带时区的日期时间
// ZonedDateTime的now():获取本时区的ZonedDateTime对象
ZonedDateTime zonedDateTime= ZonedDateTime.now();
System.out.println(zonedDateTime);
// ZonedDateTime的now(ZoneId id):获取指定时区的ZonedDateTime对象
ZonedDateTime zonedDateTime1= ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println(zonedDateTime1);
}
}
- Clock:使用时区提供对当前即时、日期和时间的访问的时钟。
- 持续时间:Duration,用于计算两个“时间”间隔
- 日期间隔:Period,用于计算两个“日期”间隔
- TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整到“下一个工作日”等操作。
- TemporalAdjusters : 该类通过静态方法(firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用TemporalAdjuster 的实现。
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import org.junit.Test;
public class JDK8APITest {
@Test
public void test2(){
//Duration:用于计算两个“时间”间隔,以秒和纳秒为基准
LocalTime localTime= LocalTime.now();
LocalTime localTime1= LocalTime.of(15, 23, 32);
//between():静态方法,返回Duration对象,表示两个时间的间隔
Duration duration= Duration.between(localTime1, localTime);
System.out.println(duration);
System.out.println(duration.getSeconds());
System.out.println(duration.getNano());
LocalDateTime localDateTime= LocalDateTime.of(2016, 6, 12, 15, 23, 32);
LocalDateTime localDateTime1= LocalDateTime.of(2017, 6, 12, 15, 23, 32);
Duration duration1= Duration.between(localDateTime1, localDateTime);
System.out.println(duration1.toDays());
}
}
import java.time.Period;
import org.junit.Test;
public class JDK8APITest {
@Test
public void test3(){
//Period:用于计算两个“日期”间隔,以年、月、日衡量
LocalDate localDate= LocalDate.now();
LocalDate localDate1= LocalDate.of(2028, 3, 18);
Period period= Period.between(localDate, localDate1);
System.out.println(period);
System.out.println(period.getYears());
System.out.println(period.getMonths());
System.out.println(period.getDays());
Period period1= period.withYears(2);
System.out.println(period1);
}
}
2.5、参考:与传统日期处理的转换
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class DateTimeUtils {
public static final String PATTERN_YYYY_MM_DD = "yyyy-MM-dd";
public static final String PATTERN_YYYY_MM_DD_HH = "yyyy-MM-dd HH";
public static final String PATTERN_YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
public static final String PATTERN_YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
public static final String PATTERN_YYYY_MM_DD_HH_MM_SS_SSS = "yyyy-MM-dd HH:mm:ss.SSS";
public static final String PATTERN_YYYY_MM_DD_T_HH_MM_SS_SSS_Z = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
public static final String PATTERN_YYYYMMDD = "yyyyMMdd";
public static final String PATTERN_YYYYMMDDHH = "yyyyMMddHH";
public static final String PATTERN_YYYYMMDDHHMM = "yyyyMMddHHmm";
public static final String PATTERN_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
public static final String PATTERN_YYYYMMDDHHMMSSSSS = "yyyyMMddHHmmssSSS";
public static final String PATTERN_HH_MM = "HH:mm";
public static final String PATTERN_HH_MM_SS = "HH:mm:ss";
public static final String PATTERN_HHMMSS = "HHmmss";
public static final String[] WEEKS = {"一", "二", "三", "四", "五", "六", "日"};
public static final String[] DAYS = {"今天", "明天", "后天"};
public static final DateTimeFormatter FORMATTER_YYYY_MM_DD = DateTimeFormatter.ofPattern(PATTERN_YYYY_MM_DD).withZone(ZoneId.systemDefault());
public static final DateTimeFormatter FORMATTER_YYYY_MM_DD_HH = DateTimeFormatter.ofPattern(PATTERN_YYYY_MM_DD_HH).withZone(ZoneId.systemDefault());
public static final DateTimeFormatter FORMATTER_YYYY_MM_DD_HH_MM = DateTimeFormatter.ofPattern(PATTERN_YYYY_MM_DD_HH_MM).withZone(ZoneId.systemDefault());
public static final DateTimeFormatter FORMATTER_YYYY_MM_DD_HH_MM_SS = DateTimeFormatter.ofPattern(PATTERN_YYYY_MM_DD_HH_MM_SS).withZone(ZoneId.systemDefault());
public static final DateTimeFormatter FORMATTER_YYYY_MM_DD_HH_MM_SS_SSS = DateTimeFormatter.ofPattern(PATTERN_YYYY_MM_DD_HH_MM_SS_SSS).withZone(ZoneId.systemDefault());
public static final DateTimeFormatter FORMATTER_YYYYMMDD = DateTimeFormatter.ofPattern(PATTERN_YYYYMMDD).withZone(ZoneId.systemDefault());
public static final DateTimeFormatter FORMATTER_YYYYMMDDHH = DateTimeFormatter.ofPattern(PATTERN_YYYYMMDDHH).withZone(ZoneId.systemDefault());
public static final DateTimeFormatter FORMATTER_YYYYMMDDHHMM = DateTimeFormatter.ofPattern(PATTERN_YYYYMMDDHHMM).withZone(ZoneId.systemDefault());
public static final DateTimeFormatter FORMATTER_YYYYMMDDHHMMSS = DateTimeFormatter.ofPattern(PATTERN_YYYYMMDDHHMMSS).withZone(ZoneId.systemDefault());
public static final DateTimeFormatter FORMATTER_YYYYMMDDHHMMSSSSS = DateTimeFormatter.ofPattern(PATTERN_YYYYMMDDHHMMSSSSS).withZone(ZoneId.systemDefault());
public static final DateTimeFormatter FORMATTER_HH_MM = DateTimeFormatter.ofPattern(PATTERN_HH_MM).withZone(ZoneId.systemDefault());
public static final DateTimeFormatter FORMATTER_HH_MM_SS = DateTimeFormatter.ofPattern(PATTERN_HH_MM_SS).withZone(ZoneId.systemDefault());
public static final DateTimeFormatter FORMATTER_HHMMSS = DateTimeFormatter.ofPattern(PATTERN_HHMMSS).withZone(ZoneId.systemDefault());
public static final DateTimeFormatter FORMATTER_YYYY_MM_DD_T_HH_MM_SS_SSS_Z = DateTimeFormatter.ofPattern(PATTERN_YYYY_MM_DD_T_HH_MM_SS_SSS_Z).withZone(ZoneId.systemDefault());
private static final Map FORMATTERS = new ConcurrentHashMap();
static {
FORMATTERS.put(PATTERN_YYYY_MM_DD, FORMATTER_YYYY_MM_DD);
FORMATTERS.put(PATTERN_YYYY_MM_DD_HH, FORMATTER_YYYY_MM_DD_HH);
FORMATTERS.put(PATTERN_YYYY_MM_DD_HH_MM, FORMATTER_YYYY_MM_DD_HH_MM);
FORMATTERS.put(PATTERN_YYYY_MM_DD_HH_MM_SS, FORMATTER_YYYY_MM_DD_HH_MM_SS);
FORMATTERS.put(PATTERN_YYYY_MM_DD_HH_MM_SS_SSS, FORMATTER_YYYY_MM_DD_HH_MM_SS_SSS);
FORMATTERS.put(PATTERN_YYYYMMDD, FORMATTER_YYYYMMDD);
FORMATTERS.put(PATTERN_YYYYMMDDHH, FORMATTER_YYYYMMDDHH);
FORMATTERS.put(PATTERN_YYYYMMDDHHMM, FORMATTER_YYYYMMDDHHMM);
FORMATTERS.put(PATTERN_YYYYMMDDHHMMSS, FORMATTER_YYYYMMDDHHMMSS);
FORMATTERS.put(PATTERN_YYYYMMDDHHMMSSSSS, FORMATTER_YYYYMMDDHHMMSSSSS);
FORMATTERS.put(PATTERN_HH_MM, FORMATTER_HH_MM);
FORMATTERS.put(PATTERN_HH_MM_SS, FORMATTER_HH_MM_SS);
FORMATTERS.put(PATTERN_HHMMSS, FORMATTER_HHMMSS);
FORMATTERS.put(PATTERN_YYYY_MM_DD_T_HH_MM_SS_SSS_Z, FORMATTER_YYYY_MM_DD_T_HH_MM_SS_SSS_Z);
}
private DateTimeUtils() {
}
/**
* 格式化日期
*
* @param temporal 日期,常见的实现类:
* {@link LocalDateTime},
* {@link LocalDate},
* {@link LocalTime},
* {@link ZonedDateTime}
* {@link Instant}
* @param pattern 格式
* @return 被格式化后的日期字符串
* @see LocalDateTime
* @see LocalDate
* @see LocalTime
* @see Instant
* @see ZonedDateTime
*/
public static String format(TemporalAccessor temporal, String pattern) {
return FORMATTERS.getOrDefault(pattern, DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault())).format(temporal);
}
/**
* 解析字符串日期
*
* @param dateStr 日期字符串
* @param pattern 格式
* @return LocalDateTime
*/
public static LocalDateTime parseLocalDateTime(String dateStr, String pattern) {
return LocalDateTime.parse(dateStr, FORMATTERS.getOrDefault(pattern, DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.of("Asia/Shanghai"))));
}
/**
* 解析字符串日期
*
* @param dateStr 日期字符串
* @param pattern 格式
* @return LocalDate
*/
public static LocalDate parseLocalDate(String dateStr, String pattern) {
return LocalDate.parse(dateStr, FORMATTERS.getOrDefault(pattern, DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault())));
}
/**
* 解析字符串时间
*
* @param timeStr 时间字符串
* @param pattern 格式
* @return LocalTime
*/
public static LocalTime parseLocalTime(String timeStr, String pattern) {
return LocalTime.parse(timeStr, FORMATTERS.getOrDefault(pattern, DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault())));
}
/**
* 相差多少年
*
* @param from 日期1 inclusive
* @param to 日期2 exclusive
* @return 如果from大于to则会返回负数
* @see LocalDateTime
* @see LocalDate
* @see Instant
* @see ZonedDateTime
*/
public static long betweenYears(Temporal from, Temporal to) {
return ChronoUnit.YEARS.between(from, to);
}
/**
* 相差多少月
*
* @param from 日期1 inclusive
* @param to 日期2 exclusive
* @return 如果from大于to则会返回负数
* @see LocalDateTime
* @see LocalDate
* @see Instant
* @see ZonedDateTime
*/
public static long betweenMonths(Temporal from, Temporal to) {
return ChronoUnit.MONTHS.between(from, to);
}
/**
* 相差多少周
*
* @param from 日期1 inclusive
* @param to 日期2 exclusive
* @return 如果from大于to则会返回负数
* @see LocalDateTime
* @see LocalDate
* @see Instant
* @see ZonedDateTime
*/
public static long betweenWeeks(Temporal from, Temporal to) {
return ChronoUnit.WEEKS.between(from, to);
}
/**
* 相差多少天
*
* @param from 日期1 inclusive
* @param to 日期2 exclusive
* @return 如果from大于to则会返回负数
* @see LocalDateTime
* @see LocalDate
* @see Instant
* @see ZonedDateTime
*/
public static long betweenDays(Temporal from, Temporal to) {
return ChronoUnit.DAYS.between(from, to);
}
/**
* 相差多少小时
*
* @param from 日期1 inclusive
* @param to 日期2 exclusive
* @return 如果from大于to则会返回负数
* @see LocalDateTime
* @see Instant
* @see ZonedDateTime
* @see LocalTime
*/
public static long betweenHours(Temporal from, Temporal to) {
return ChronoUnit.HOURS.between(from, to);
}
/**
* 相差多少分钟
*
* @param from 日期1 inclusive
* @param to 日期2 exclusive
* @return 如果from大于to则会返回负数
* @see LocalDateTime
* @see Instant
* @see ZonedDateTime
* @see LocalTime
*/
public static long betweenMinutes(Temporal from, Temporal to) {
return ChronoUnit.MINUTES.between(from, to);
}
/**
* 相差多少秒
*
* @param from 日期1 inclusive
* @param to 日期2 exclusive
* @return 如果from大于to则会返回负数
* @see LocalDateTime
* @see Instant
* @see ZonedDateTime
* @see LocalTime
*/
public static long betweenSeconds(Temporal from, Temporal to) {
return ChronoUnit.SECONDS.between(from, to);
}
/**
* {@param from} 和 {@param to} 是否同一天
*
* @param localDate1 日期1
* @param localDate2 日期2
* @return true {@param from} 和 {@param to} 同一天,否则 false
*/
public static boolean isSameDay(LocalDate localDate1, LocalDate localDate2) {
return localDate1.compareTo(localDate2) == 0;
}
/**
* {@param from} 和 {@param to} 是否同一天
*
* @param localDateTime1 日期1
* @param localDateTime2 日期2
* @return true {@param from} 和 {@param to} 同一天,否则 false
*/
public static boolean isSameDay(LocalDateTime localDateTime1, LocalDateTime localDateTime2) {
return isSameDay(localDateTime1.toLocalDate(), localDateTime2.toLocalDate());
}
/**
* 返回只包含日期,不包含时间属性的日期
*
* @return 只包含日期的日期
*/
public static LocalDateTime getOnlyDay() {
return LocalDateTime.now().truncatedTo(ChronoUnit.DAYS);
}
/**
* 返回只包含日期,不包含时间属性的日期
*
* @param localDateTime 原始日期
* @return 只包含日期的日期
*/
public static LocalDateTime getOnlyDay(LocalDateTime localDateTime) {
return localDateTime.truncatedTo(ChronoUnit.DAYS);
}
/**
* LocalDateTime 转 Date
*
* @param localDateTime 需要转换的日期
* @return Date 类型的日期
*/
public static Date toDate(LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
/**
* LocalDate 转 Date,时间部分初始化为00:00:00.0000000
*
* @param localDate 需要转换的日期
* @return Date 类型的日期
*/
public static Date toDate(LocalDate localDate) {
return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
}
/**
* Date 转 LocalDateTime
*
* @param date 需要转换的日期
* @return LocalDateTime 类型的日期
*/
public static LocalDateTime toLocalDateTime(Date date) {
return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}
/**
* 毫秒转LocalDateTime
*
* @param millis 毫秒数
* @return LocalDateTime 类型的日期
*/
public static LocalDateTime toLocalDateTime(long millis) {
return LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault());
}
/**
* LocalDate转LocalDateTime
*
* @param localDate LocalDate
* @return LocalDateTime 类型的日期
*/
public static LocalDateTime toLocalDateTime(LocalDate localDate) {
return LocalDateTime.of(localDate, LocalTime.MIN);
}
/**
* Date 转 LocalDate
*
* @param date 需要转换的日期
* @return LocalDate 类型的日期
*/
public static LocalDate toLocalDate(Date date) {
return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).toLocalDate();
}
/**
* 毫秒 转 LocalDate
*
* @param millis 需要转换的日期
* @return LocalDate 类型的日期
*/
public static LocalDate toLocalDate(long millis) {
return LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault()).toLocalDate();
}
/**
* 获取毫秒
*
* @param localDateTime 日期
* @return 毫秒
*/
public static long toMillis(LocalDateTime localDateTime) {
return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}
/**
* 获取毫秒(处在00:00:00.0000000时刻的毫秒)
*
* @param localDate 日期
* @return 毫秒
*/
public static long toMillis(LocalDate localDate) {
return localDate.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();
}
/**
* 判断是否是合法的日期
*
* @param dateStr 日期字符串
* @param pattern 日期的格式
* @return true 合法,false 不合法
*/
public static boolean isValid(String dateStr, String pattern) {
try {
DateTimeFormatter formatter = FORMATTERS.getOrDefault(pattern, DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault()));
//之所以最后比较一遍是为了处理2月份的情况
//比如,dateStr=2020-02-30 12:12:56, pattern=yyyy-MM-dd HH:mm:ss,
//当使用parse方法时是不报错的,因为会自动处理为2020-02-29 12:12:56,
//但是上面的情况不是我们想要的,因此最后比较一下即可
return dateStr.equals(formatter.format(formatter.parse(dateStr)));
} catch (Exception e) {
//ignore
}
return false;
}
/**
* 在指定日期上增加天数,然后返回只包含日期属性的日期
*
* @param localDateTime 日期
* @param days 需要增加的天数
* @return 只包含日期属性的日期
*/
public static LocalDateTime getOnlyDay4FutureDate(LocalDateTime localDateTime, long days) {
return localDateTime.plusDays(days).truncatedTo(ChronoUnit.DAYS);
}
/**
* 是否是今天
*
* @param localDateTime 日期
* @return true 是今天,false 不是今天
*/
public static boolean isToday(LocalDateTime localDateTime) {
return isSameDay(localDateTime.toLocalDate(), LocalDate.now());
}
/**
* 是否是今天
*
* @param localDate 日期
* @return true 是今天,false 不是今天
*/
public static boolean isToday(LocalDate localDate) {
return isSameDay(localDate, LocalDate.now());
}
/**
* 判断目标日期是否在日期区间内
*
* @param target 目标日期
* @param left 左边界日期,exclusive
* @param right 右边界日期,exclusive
* @return true 在,false 不在
*/
public static boolean isInRange(LocalDate target, LocalDate left, LocalDate right) {
return target.isAfter(left) && target.isBefore(right);
}
/**
* 判断目标日期是否在日期区间内
*
* @param target 目标日期
* @param left 左边界日期,exclusive
* @param right 右边界日期,exclusive
* @return true 在,false 不在
*/
public static boolean isInRange(LocalDateTime target, LocalDateTime left, LocalDateTime right) {
return target.isAfter(left) && target.isBefore(right);
}
/**
* 比较目标时间点是否在区间中
* 注意:此方法会涉及到次日逻辑,也就说{@param left} 可能大于 {@param right}
* 比如:left:22:0,right:08:00,则表示时间段段是昨天22:00到次日08:00,因此target=03:00 也是合理的
*
* @param target 目标时间
* @param left 左边界,格式HH:mm,exclusive
* @param right 右边界,格式HH:mm,exclusive
* @return true 在,false 不在
* @see #PATTERN_HH_MM
*/
public static boolean isInRange(LocalTime target, LocalTime left, LocalTime right) {
return (target.isAfter(left) && target.isBefore(right))
|| (left.isAfter(right) && (target.isBefore(right) || target.isAfter(left)));
}
/**
* 比较目标时间点是否在区间中
* 注意:此方法会涉及到隔天逻辑,也就说{@param left} 可能大于 {@param right}
* 比如:left:22:0,right:08:00,则表示时间段段是昨天22:00到次日08:00,因此target=03:00 也是合理的
*
* @param target 目标时间
* @param left 左边界,格式HH:mm,exclusive
* @param right 右边界,格式HH:mm,exclusive
* @return true 在,false 不在
* @see #PATTERN_HH_MM
*/
public static boolean isInRange(LocalDateTime target, String left, String right) {
LocalTime tt = target.toLocalTime();
LocalTime lt = parseLocalTime(left, PATTERN_HH_MM);
LocalTime rt = parseLocalTime(right, PATTERN_HH_MM);
return isInRange(tt, lt, rt);
}
/**
* 比较目标时间点是否在区间中
* 注意:此方法会涉及到隔天逻辑,也就说{@param left} 可能大于 {@param right}
* 比如:left:22:0,right:08:00,则表示时间段段是昨天22:00到次日08:00,因此target=03:00 也是合理的
*
* @param target 目标时间
* @param left 左边界,格式HH:mm,exclusive
* @param right 右边界,格式HH:mm,exclusive
* @return true 在,false 不在
* @see #PATTERN_HH_MM
*/
public static boolean isInRange(String target, String left, String right) {
LocalTime tt = parseLocalTime(target, PATTERN_HH_MM);
LocalTime lt = parseLocalTime(left, PATTERN_HH_MM);
LocalTime rt = parseLocalTime(right, PATTERN_HH_MM);
return isInRange(tt, lt, rt);
}
/**
* 返回指定小时和分钟的日期
*
* @param time 时间 HH:mm
* @return 指定小时和分钟的日期
* @see #PATTERN_HH_MM
*/
public static LocalDateTime getDateTimeByHourMinute(String time) {
LocalTime localTime = parseLocalTime(time, PATTERN_HH_MM);
return getDateTimeByHourMinute(localTime.getHour(), localTime.getMinute());
}
/**
* 返回指定小时和分钟的日期
*
* @param hour 小时
* @param minute 分钟
* @return
*/
public static LocalDateTime getDateTimeByHourMinute(int hour, int minute) {
return LocalDateTime.of(LocalDateTime.now().toLocalDate(), LocalTime.of(hour, minute));
}
/**
* 获取某月的第一天,时间是午夜
*
* @param year 年份
* @param month 月份,1-12
* @return 返回该月的第一天,时间是午夜
*/
public static LocalDateTime getStartDayOfMonth(int year, int month) {
return LocalDateTime.of(
LocalDate.of(year, month, 1),
LocalTime.MIN);
}
/**
* 获取某月的第一天,时间是午夜
*
* @param localDateTime 日期
* @return 返回该月的第一天,时间是午夜
*/
public static LocalDateTime getStartDayOfMonth(LocalDateTime localDateTime) {
return LocalDateTime.of(
localDateTime
.withDayOfMonth(1)
.toLocalDate(),
LocalTime.MIN);
}
/**
* 获取某月的第一天
*
* @param localDate 日期
* @return 返回该月的第一天
*/
public static LocalDate getStartDayOfMonth(LocalDate localDate) {
return localDate.withDayOfMonth(1);
}
/**
* 获取每月的最后一天
*
* @param year 年份
* @param month 月份,1-12
* @return 返回该月的最后一天
*/
public static LocalDateTime getEndDayOfMonth(int year, int month) {
return LocalDateTime.of(
LocalDate.now()
.withYear(year)
.withMonth(month)
.with(TemporalAdjusters.lastDayOfMonth()),
LocalTime.MAX);
}
/**
* 获取某月的最后一天
*
* @param localDateTime 日期
* @return 返回该月的最后一天
*/
public static LocalDateTime getEndDayOfMonth(LocalDateTime localDateTime) {
return LocalDateTime.of(
localDateTime
.with(TemporalAdjusters.lastDayOfMonth())
.toLocalDate(),
LocalTime.MAX);
}
/**
* 获取某月的最后一天
*
* @param localDate 日期
* @return 返回该月的最后一天
*/
public static LocalDate getEndDayOfMonth(LocalDate localDate) {
return localDate.with(TemporalAdjusters.lastDayOfMonth());
}
/**
* 时间字符串转时间戳,时间以半点为分界:
* 小于半点(=30),向上取整
*
* @param time 时间,格式 yyyy-MM-dd HH:mm,如 2020-10-30 17:20
* @return 毫秒数
* @see #PATTERN_YYYY_MM_DD_HH_MM
*/
public static long truncateByHalfHour(String time) {
LocalDateTime localDateTime = parseLocalDateTime(time, PATTERN_YYYY_MM_DD_HH_MM);
return toMillis(truncateByHalfHour(localDateTime));
}
/**
* 时间以半点(30分)为分界:
* 小于半点(=30),向上取整
*
* @param localDateTime
* @return LocalDateTime
*/
public static LocalDateTime truncateByHalfHour(LocalDateTime localDateTime) {
LocalDateTime resultTime = localDateTime.getMinute()
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?