最近打开了尘封较久的项目,发现原来旧的项目中,在处理日期/时间的方法中,都是使用java.util.Date,而且发现在计算2个日期相差的天数,相差的月数的代码是相当的纠结,需要将Date转换成long类型的时间戳,然后将2个时间戳相减的结果,在除以1000 x 60 x 60 x 24,(别问我为什么要这样),因为long类型的时间戳是毫秒级的,对应到前面的公式的说明是(毫秒 x 秒 x 分 x 小时),这样应该就好理解,一天有24小时,一小时有60分钟,一分钟有60秒,一秒等1000毫秒。
/**
* 返回自1970年1月1日00:00:00 GMT以来由该【日期】对象显示的毫秒数
*
* @return 自1970年1月1日00:00:00 GMT以来与该日期相对应的毫秒数
*/
public long getTime() {
return getTimeImpl();
}
Date类型算是JDK中比较久远的一种类型,从JDK1.0开始就提供了,对于大部分的Java开发人员来说,并不陌生,是开发中经常会使用到的(还有一个叫SimpleDateFormat),比如获取当前的日期,格式化日期为字符串形式(如yyyy-MM-dd),将字符串的日期格式变成Date的类型,还有就是上面说的计算2个日期间隔的天/月数,得取月的第一天,最后一天等。
先来看下旧代码(比较过时的写法):
/**
* 日期工具类
*/
public final class DateUtils {
private DateUtils() {
}
/**
* 获得当前日期
*/
public static Date now() {
return new Date();
}
/**
* 返回以【formatString 】格式的当前日期
* @param formatString
* 时间格式(如yyyy-MM-dd)
*/
public static String getNowStrFormat(String formatString) {
return format(now(), formatString);
}
/**
* 返回以【formatString 】格式的【日期】
* @param date
* 输入的日期
* @param formatString
* 时间格式(如yyyy-MM-dd)
*/
public static String format(Date date, String formatString) {
return format(date, formatString, Locale.PRC);
}
/**
* 返回以【formatString 】格式的【日期】
* @param date
* 输入的日期
* @param formatString
* 时间格式(如yyyy-MM-dd)
* @param locale
* 指定的地区
*/
private static String format(Date date, String formatString, Locale locale) {
if (date == null) {
return null;
} else {
SimpleDateFormat dateFormat = new SimpleDateFormat(formatString, locale);
return dateFormat.format(date);
}
}
/**
* 将日期字符串【dateString 】按【format】的格式转换成 Date类型
* @param dateString
* 输入的日期字符串
* @param format
* 时间格式(如yyyy-MM-dd)
*/
public static Date parse(String dateString, String format) {
Date date = null;
try {
SimpleDateFormat df = new SimpleDateFormat(format);
date = df.parse(dateString);
} catch (ParseException e) {
LOG.error("日期转换错误,日期格式不正确", e);
throw new IllegallArgumentException("输入的字符串【" + dateString + "】"与格式【" + format + "】不匹配);
}
return date;
}
/**
* 获取指定year(年),month(月)的第一天
* @param year
* 输入年份
* @param month
* 输入的月份
*/
public static String getFirstDayOfMonth(Integer year, Integer month){
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, (month - 1));
//c.add(Calendar.MONTH, 0);
c.set(Calendar.DAY_OF_MONTH,1);//设置为1号,当前日期既为本月第一天
return format(c.getTime(), "yyyy-MM-dd");
}
/**
* 获取指定year(年),month(月)的最后一天
* @param year
* 输入年份
* @param month
* 输入的月份
*/
public static String getLastDayOfMonth(Integer year, Integer month){
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, (month - 1));
//c.add(Calendar.MONTH, 0);
c.set(Calendar.DAY_OF_MONTH,c.getActualMaximum(Calendar.DAY_OF_MONTH));//设置为1号,当前日期既为本月第一天
return format(c.getTime(), "yyyy-MM-dd");
}
/**
* 得取某个日期(date)在月中是第几天
* @param date
* 输入的日期
*/
public static int dayOfMonth(Date date){
Calendar c = Calendar.getInstance();
c.setTime(date);
return c.get(Calendar.DAY_OF_MONTH);
}
/**
* 得取某个日期(date)在月中是周几
* @param date
* 输入的日期
*/
public static int dayOfWeek(Date date){
Calendar c = Calendar.getInstance();
c.setTime(date);
return c.get(Calendar.DAY_OF_WEEK);
}
/**
* 得取某个日期(date)是一年中的第几个月(注意结果要 + 1)
* @param date
* 输入的日期
*/
public static int month(Date date){
Calendar c = Calendar.getInstance();
c.setTime(date);
return c.get(Calendar.MONTH);
}
/**
* 得取某个日期(date)的年份
* @param date
* 输入的日期
*/
public static int year(Date date){
Calendar c = Calendar.getInstance();
c.setTime(date);
return c.get(Calendar.YEAR);
}
/**
* 得到指定时间,在添加/减少的分钟后的时间(减用 负数)
* @param date
* 输入的日期
* @param minute
* 输入的分钟数(可以用负数)
*/
public static Date dayByAddMin(Date date, int minute) {
return addDay(date, Calendar.MINUTE, minute);
}
/**
* 得到指定时间,在添加/减少的小时后的时间(减用 负数)
* @param date
* 输入的日期
* @param hour
* 输入的小时数(可以用负数)
*/
public static Date dayByAddHour(Date date, int hour) {
return addDay(date, Calendar.HOUR_OF_DAY, hour);
}
/**
* 得到指定时间,在添加/减少的天后的时间(减用 负数)
* @param date
* 输入的日期
* @param day
* 输入的天数(可以用负数)
*/
public static Date dayByAddDay(Date date, int day) {
return addDay(date, Calendar.DAY_OF_MONTH, day);
}
/**
* 得到指定时间,在添加/减少的月后的时间(减用 负数)
* @param date
* 输入的日期
* @param month
* 输入的月数(可以用负数)
*/
public static Date dayByAddMonth(Date date, int month) {
return addDay(date, Calendar.MONTH, month);
}
/**
* 得到指定时间,在添加/减少对应类型的间隔数后的时间(减用 负数)
* @param date
* 输入的日期
* @param type
* 输入的时间类型(详细参考Calendar中的常量)
* @param interval
* 输入的间隔数(可以用负数)
*/
private static Date addDay(Date date, int type, int interval) {
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(type, interval);
return c.getTime();
}
/**
* 计算2个日期之间相差的天数
* @param date
* 输入的日期1
* @param date2
* 输入的日期2
* @return int
* 2个日期间隔的天数
*/
public static int diff2days(Date date, Date date2) {
if (date2.compareTo(date) <= 0) {
return 0;
} else {
long interval = date2.getTime() - date.getTime();
return (int)(interval / (1000 * 60 * 60 * 24));
}
}
/**
* 得到2个日期之间的天数的数组
* @param start
* 开始时间
* @param end
* 结束时间
* @return
*/
public static List<Date> dayBetween(Date start, Date end){
int interval = diff2days(start, end);
List<Date> result = Utils.newList();
result.add(start);
if(interval == 0){
//同一天
return result;
}
for(int i = 1; i < interval; i ++){
result.add(dayByAddDay(start, i));
}
return result;
}
/**
* 得到2个日期之间的天数的数组
* @param startStr
* 开始时间
* @param endStr
* 结束时间
* @return
*/
public static List<Date> dayBetween(String startStr, String endStr){
Date start = parse(startStr, "yyyy-MM-dd");
Date end = parse(endStr, "yyyy-MM-dd");
return dayBetween(start, end);
}
/**
* 计算2个日期之间相隔的月数
* @param date
* 开始时间
* @param target
* 结束时间
* @return
* 返回2个日期之间相差的月数
*/
public static Integer intervalMonths(Date date, Date target){
Calendar c1 = Calendar.getInstance();
c1.setTime(date);
int fromMonth = c1.get(Calendar.MONTH);
Calendar c2 = Calendar.getInstance();
c2.setTime(target);
int targetMonth = c2.get(Calendar.MONTH);
return targetMonth - fromMonth;
}
//省略其他....
}
对于上面的代码,相信很多开发的小伙伴应该都比较熟悉,无论从教程或者网上的例子来说,都基本上是使用Date、SimpleDateFormat、Calendar 这三个API工具类来处理。
- Date : 表示特定的瞬间,精确到毫秒。Date类用于表示日期和时间(注意这里是java.util.Date,不是java.sql.Date),以1970年1⽉1⽇ 8点0分0秒为起始点(为什么选择1970年?小伙伴可以去查下)
- SimpleDateFormat : 日期格式化工具类(在java.text包下),比如yyyy-MM-dd这样的格式,(注意:这是线程不安全的)
- Calendar : 日历工具类(在java.util包下),常用于计算日历上的某一天/月中,比如下个月的今天是几,或者还有多久。
至于具体API方法,可以点开源码进行查看,不是太难。
回归正题,即然Date及Calendar在计算时间间隔或者其他场景下都比较麻烦,那么有没有更好的API使用呢?当然是有的,JDK1.8中,就更新了新的日期/时间处理工具类。具体的包在java.time目录下,有兴趣的小伙伴可以打开进行查看。
java.time包下提供了日期、时间、周期、时区等工具类及API,它是基于ISO日历系统,遵循 Gregorian规则的,并且类都是不可变的,线程安全的,比较常用的类主要是:
- Instant :本质上是一个时间戳。
- LocalDate :存储了日期,如:2010-12-03。可以用来存储生日。
- LocalTime :存储了时间,如:11:30。
- LocalDateTime :存储了日期和时间,如:2010-12-03T11:30。
- ZonedDateTime :存储一个带时区的日期和时间。
- DateTimeFormatter:在日期对象与字符串之间进行转换。
- ChronoUnit:计算出两个时间点之间的时间距离,可按多种时间单位计算。
- TemporalAdjuster:各种日期计算功能。
- Period:用于测量以年,月和日为单位的时间。
- Duration:用于以秒和纳秒为单位测量时间。
这个包下包括了很多API,而且都有比较好的命名规则:
- of:静态工厂方法。
- parse:静态工厂方法,关注于解析。
- get:获取值。
- is:用于比较。
- with:不可变的setter等价物。
- plus:加一些量到某个对象。
- minus:从某个对象减去一些量。
- to:转换到另一个类型。
- at:把这个对象与另一个对象组合起来,例如:date.atTime(time)。
学习了上面的这种工具类及api方法,来看一下例子:
@Slf4j
public class DateTest {
@Test
public void testNewDate(){
//获取当前时间
LocalDateTime now = LocalDateTime.now();
log.info("当前时间为:{}", now);
//格式化当前时间
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
log.info("当前时间的yyyy-MM-dd HH:mm:ss为:{}", now.format(dateTimeFormatter));
//得到某年的某一天
Year year = Year.of(2022);
LocalDate localDate = year.atDay(52);
log.info("2022年的第52天的日期是:{}", localDate);
log.info("是否是闰年:{}", localDate.isLeapYear());
// 解析字符串形式的日期时间
DateTimeFormatter dateTimeFormatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
TemporalAccessor temporalAccessor = dateTimeFormatter2.parse("2022-05-06");
log.info("字符串转为日期:{}", LocalDate.from(temporalAccessor));
LocalDateTime with = now.with(TemporalAdjusters.firstDayOfMonth());
log.info("得到当前月份:{}的第一天:{}", localDate.getMonthValue(), with.toLocalDate());
// 计算某月的第一个星期一的日期
TemporalAdjuster temporalAdjuster = TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY);
LocalDate firstDayOfWeek = now.toLocalDate().with(temporalAdjuster);
log.info("当前月的第一个星期一的日期:{}", firstDayOfWeek);
//计算localDate的下一个星期一的日期
LocalDate nextMonday = now.toLocalDate().with(TemporalAdjusters.next(DayOfWeek.MONDAY));
log.info("当前月的下一个星期一的日期:{}", nextMonday);
//计算2个日期相差的天数,月数
LocalDateTime localDate1 = LocalDateTime.of(2022, 1, 1, 16, 12, 0);
LocalDateTime localDate2 = LocalDateTime.of(2022, 4, 22, 16, 12, 0);
long dayBetween = ChronoUnit.DAYS.between(localDate1, localDate2);
long monthBetween = ChronoUnit.MONTHS.between(localDate1, localDate2);
log.info("间隔的天数为:{}", dayBetween);
log.info("间隔的月数为:{}", monthBetween);
//除了用ChronoUnit来计算外,还可以用Duration, Period
Duration duration = Duration.between(localDate1, localDate2);
log.info("间隔的天数为:{}", duration.toDays());
Period period = Period.between(localDate1.toLocalDate(), localDate2.toLocalDate());
log.info("间隔的月数为:{}", period.toTotalMonths());
}
}
输出结果为:
17:02:44.344 [main] INFO net.jhelp.easyql.demo.tests.DateTest - 当前时间为:2022-05-06T17:02:44.341
17:02:44.373 [main] INFO net.jhelp.easyql.demo.tests.DateTest - 当前时间的yyyy-MM-dd HH:mm:ss为:2022-05-06 17:02:44
17:02:44.374 [main] INFO net.jhelp.easyql.demo.tests.DateTest - 2022年的第52天的日期是:2022-02-21
17:02:44.375 [main] INFO net.jhelp.easyql.demo.tests.DateTest - 是否是闰年:false
17:02:44.380 [main] INFO net.jhelp.easyql.demo.tests.DateTest - 字符串转为日期:2022-05-06
17:02:44.382 [main] INFO net.jhelp.easyql.demo.tests.DateTest - 得到当前月份:2的第一天:2022-05-01
17:02:44.388 [main] INFO net.jhelp.easyql.demo.tests.DateTest - 当前月的第一个星期一的日期:2022-05-02
17:02:44.393 [main] INFO net.jhelp.easyql.demo.tests.DateTest - 当前月的下一个星期一的日期:2022-05-09
17:02:44.393 [main] INFO net.jhelp.easyql.demo.tests.DateTest - 间隔的天数为:111
17:02:44.393 [main] INFO net.jhelp.easyql.demo.tests.DateTest - 间隔的月数为:3
17:02:44.393 [main] INFO net.jhelp.easyql.demo.tests.DateTest - 间隔的天数为:111
17:02:44.393 [main] INFO net.jhelp.easyql.demo.tests.DateTest - 间隔的月数为:3
通过上面的测试用例,新的API是不是简单很多,尤其在计算时间差方面,测试例子保是列举了一些常用的API的使用,具体的例子,可以打开源码进行查阅。
好了,学习了这么多,旧项目的日期工具类,可以进行一翻新的重构(又可以吹了),重写后的内容如下,觉得用的小伙伴可以拿去项目中使用。
/**
* 获得当前日期
*/
public static LocalDateTime now() {
return LocalDateTime.now();
}
/**
* 将java.util.Date转换成 LocalDateTime
* @param date
* 输入的时间
* @return
*/
public static LocalDateTime from(Date date){
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
}
/**
* 将localDateTime转换成Date
* @param localDateTime
* 输入的时间
* @return
*/
public static Date to(LocalDateTime localDateTime){
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
/**
* 返回以【formatString 】格式的当前日期
* @param formatString
* 时间格式(如yyyy-MM-dd)
*/
public static String getNowStrFormat(String formatString) {
return format(now(), formatString);
}
public static String formatByNumber(Long date, String formatString) {
Date date1 = new Date(date);
LocalDateTime localDateTime = date1.toInstant().atZone(
ZoneId.systemDefault()).toLocalDateTime();
return format(localDateTime, formatString);
}
/**
* 返回以【formatString 】格式的【日期】
* @param date
* 输入的日期
* @param formatString
* 时间格式(如yyyy-MM-dd)
*/
public static String format(LocalDateTime date, String formatString) {
if (date == null) {
return "";
} else {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(formatString);
return date.format(dateTimeFormatter);
}
}
/**
* 将日期字符串【dateString 】按【format】的格式转换成 Date类型
* @param datetime
* 输入的日期字符串
* @param format
* 时间格式(如yyyy-MM-dd)
*/
public static LocalDateTime parse(String datetime, String format) {
SimpleDateFormat df = new SimpleDateFormat(format);
try {
Date date = df.parse(datetime);
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
} catch (ParseException e1) {
log.error("日期转换错误,日期格式不正确", e1);
}
return null;
}
public static Long dateToLong(String dateString, String format){
try {
SimpleDateFormat df = new SimpleDateFormat(format);
Date date = df.parse(dateString);
return date.getTime();
} catch (ParseException var4) {
log.error("日期转换错误,日期格式不正确", var4);
}
return null;
}
/**
* 获取指定year(年),month(月)的第一天
* @param year
* 输入年份
* @param month
* 输入的月份
*/
public static String getFirstDayOfMonth(Integer year, Integer month){
//设置为1号,当前日期既为本月第一天
LocalDate localDate = LocalDate.of(year, month, 1);
return localDate.format(YYYY_MM_DD);
}
/**
* 获取指定year(年),month(月)的最后一天
* @param year
* 输入年份
* @param month
* 输入的月份
*/
public static String getLastDayOfMonth(Integer year, Integer month){
LocalDate localDate = LocalDate.of(year, month, 1);
LocalDate lastDayOfMonth = localDate.with(TemporalAdjusters.lastDayOfMonth());
return lastDayOfMonth.format(YYYY_MM_DD);
}
/**
* 得取某个日期(date)在月中是第几天
* @param date
* 输入的日期
*/
public static int dayOfMonth(LocalDate date){
return date.getDayOfMonth();
}
/**
* 得取某个日期(date)在月中是周几
* @param date
* 输入的日期
*/
public static int dayOfWeek(LocalDate date){
return date.getDayOfWeek().getValue();
}
/**
* 得取某个日期(date)是一年中的第几个月(注意结果要 + 1)
* @param date
* 输入的日期
*/
public static int month(LocalDate date){
return date.getMonthValue();
}
/**
* 得取某个日期(date)的年份
* @param date
* 输入的日期
*/
public static int year(LocalDate date){
return date.getYear();
}
/**
* 得到指定时间,在添加/减少的分钟后的时间(减用 负数)
* @param date
* 输入的日期
* @param minute
* 输入的分钟数(可以用负数)
*/
public static LocalDateTime dayByAddMin(LocalDateTime date, int minute) {
return addDay(date, ChronoUnit.MINUTES, minute);
}
/**
* 得到指定时间,在添加/减少的小时后的时间(减用 负数)
* @param date
* 输入的日期
* @param hour
* 输入的小时数(可以用负数)
*/
public static LocalDateTime dayByAddHour(LocalDateTime date, int hour) {
return addDay(date, ChronoUnit.HOURS, hour);
}
/**
* 得到指定时间,在添加/减少的天后的时间(减用 负数)
* @param date
* 输入的日期
* @param day
* 输入的天数(可以用负数)
*/
public static LocalDateTime dayByAddDay(LocalDateTime date, int day) {
return addDay(date, ChronoUnit.DAYS, day);
}
/**
* 得到指定时间,在添加/减少的月后的时间(减用 负数)
* @param date
* 输入的日期
* @param month
* 输入的月数(可以用负数)
*/
public static LocalDateTime dayByAddMonth(LocalDateTime date, int month) {
return addDay(date, ChronoUnit.MONTHS, month);
}
public static LocalDateTime dayByAddYear(LocalDateTime cur, int n) {
return addDay(cur, ChronoUnit.YEARS, n);
}
/**
* 得到指定时间,在添加/减少对应类型的间隔数后的时间(减用 负数)
* @param date
* 输入的日期
* @param type
* 输入的时间类型(详细参考Calendar中的常量)
* @param interval
* 输入的间隔数(可以用负数)
*/
private static LocalDateTime addDay(LocalDateTime date, ChronoUnit type, int interval) {
return date.plus(interval, type);
}
/**
* 得到当前时间的24小时格式的小时数
*
* @return
*/
public static int getCurHour24() {
return LocalDateTime.now().getHour();
}
/**
* 得到2个日期之间的天数的数组
* @param start
* 开始时间
* @param end
* 结束时间
* @return
*/
public static List<LocalDate> dayBetween(LocalDate start, LocalDate end){
Long interval = intervalDays(start, end);
List<LocalDate> result = Utils.newList();
for(int i = 0; i <= interval; i ++){
result.add(start.plusDays(i));
}
return result;
}
/**
* 得到2个日期之间的天数的数组
* @param startStr
* 开始时间
* @param endStr
* 结束时间
* @return
*/
public static List<LocalDate> dayBetween(String startStr, String endStr){
LocalDate start = LocalDate.parse(startStr, YYYY_MM_DD);
LocalDate end = LocalDate.parse(endStr, YYYY_MM_DD);
return dayBetween(start, end);
}
/**
* 得到2个日期之间的天数的数组
* @param start
* 开始时间
* @param end
* 结束时间
* @return
*/
public static List<String> dayStrBetween(LocalDate start, LocalDate end){
Long interval = intervalDays(start, end);
List<String> result = Utils.newList();
for(int i = 0; i <= interval; i ++){
LocalDate tmp = start.plusDays(i);
result.add(tmp.format(YYYY_MM_DD));
}
return result;
}
/**
* 得到2个日期之间的天数的数组
* @param startStr
* 开始时间
* @param endStr
* 结束时间
* @return
*/
public static List<String> dayStrBetween(String startStr, String endStr){
LocalDate localDate1 = LocalDate.parse(startStr, YYYY_MM_DD);
LocalDate localDate2 = LocalDate.parse(endStr, YYYY_MM_DD);
return dayStrBetween(localDate1, localDate2);
}
/**
* 得到2个日期之间相差的月份,并用数组返回
* @param startStr
* @param endStr
* @return
*/
public static List<LocalDateTime> monthBetween(String startStr, String endStr){
List<LocalDateTime> result = Utils.newList();
LocalDateTime start = LocalDateTime.parse(startStr, YYYY_MM_DD);
Temporal temporal1 = LocalDate.parse(startStr);
Temporal temporal2 = LocalDate.parse(endStr);
Long interval = ChronoUnit.MONTHS.between(temporal1, temporal2);
for(int i = 0; i <= interval; i ++){
LocalDateTime tmp = start.plusMonths(i);
result.add(tmp);
}
return result;
}
/**
* 得到2个日期之间相差的月份,并用数组返回
* @param startStr
* @param endStr
* @return
*/
public static List<String> monthStrBetween(String startStr, String endStr){
List<String> result = Utils.newList();
LocalDateTime start = LocalDateTime.parse(startStr, YYYY_MM_DD);
Temporal temporal1 = LocalDate.parse(startStr);
Temporal temporal2 = LocalDate.parse(endStr);
Long interval = ChronoUnit.MONTHS.between(temporal1, temporal2);
for(int i = 0; i <= interval; i ++){
LocalDateTime tmp = start.plusMonths(i);
result.add(tmp.format(DateTimeFormatter.ofPattern("yyyy-MM-01")));
}
return result;
}
/**
* 2个日期之间相关的天数(输入的参数要求:yyyy-MM-dd)
* @param target
* 结束日期
* @param source
* 开始日期
* @return
*/
public static Long intervalDays(String source, String target) {
LocalDate localDate1 = LocalDate.parse(source, YYYY_MM_DD);
LocalDate localDate2 = LocalDate.parse(target, YYYY_MM_DD);
return intervalDays(localDate1, localDate2);
}
/**
* 2个日期之间相关的天数
* @param target
* 结束日期
* @param source
* 开始日期
* @return
*/
public static Long intervalDays(LocalDate source, LocalDate target) {
return ChronoUnit.DAYS.between(source, target);
}
/**
* 计算2个日期之间相隔的月数
* @param date
* 开始时间
* @param target
* 结束时间
* @return
*/
public static Long intervalMonths(LocalDateTime date, LocalDateTime target){
Period period = Period.between(date.toLocalDate(),target.toLocalDate());
return period.toTotalMonths();
}
/**
* 判断输入的日期是否大于当前日期
* @param targetTime
* 输入的日期
* @return
* true : 输入日期大于等于当前日期
* false : 输入日期小于当前日期
*/
public static Boolean afterNow(String targetTime){
Temporal now = LocalDate.now();
Temporal target = LocalDate.parse(targetTime);
Long interval = ChronoUnit.DAYS.between(now, target);
return interval >= 0 ;
}
是不是看上去简单清晰了很多,JDK其实已经想到了Date存在的不足,多看看JDK版本更新带来的改动,会有意想不到的收获,比如JDK1.8中的Stream、Lamda等。优化后的程序有没有问题,还跑一下测试例子看看。
long timeMillis = System.currentTimeMillis();
log.info("当前时间:{}", now());
log.info("当前时间yyyy-MM-dd: {}", getNowStrFormat("yyyy-MM-dd"));
log.info("当前时间yyyy-MM-dd HH:mm:ss: {}", getNowStrFormat("yyyy-MM-dd HH:mm:ss"));
log.info("formatByNumber : {}", formatByNumber(timeMillis, "yyyy-MM-dd"));
log.info("format(xx, xx): {}", format(LocalDateTime.now(), "yyyy-MM-dd"));
log.info("字符串转日期: {}", parse("2022-03-11 14:13:31", "yyyy-MM-dd"));
log.info("字符串日期输出数字:{}", dateToLong("2022-02-11 11:11:11", "yyyy-MM-dd HH:mm:ss"));
log.info("2022/4月的第一天:{}", getFirstDayOfMonth(2022,4));
log.info("2022/2月的最后一天:{}", getLastDayOfMonth(2022, 2));
log.info("dayOfMonth : {}", dayOfMonth(LocalDate.now()));
log.info("dayOfWeek : {}", dayOfWeek(LocalDate.now()));
log.info("month : {}", month(LocalDate.now()));
log.info("year : {}", year(LocalDate.now()));
log.info("dayByAddMin : {}", dayByAddMin(LocalDateTime.now(), 30));
log.info("dayByAddHour : {}", dayByAddHour(LocalDateTime.now(), 1));
log.info("dayByAddDay : {}", dayByAddDay(LocalDateTime.now(), 1));
log.info("dayByAddMonth : {}", dayByAddMonth(LocalDateTime.now(), 1));
log.info("dayByAddYear : {}", dayByAddYear(LocalDateTime.now(), 1));
log.info("getCurHour24 : {}", getCurHour24());
String startStr = "2022-03-01";
String endStr = "2022-03-22";
List<String> tmp = dayStrBetween(startStr, endStr);
for(String d : tmp){
log.info("dayStrBetween : {}", d);
}
log.info("afterNow: {}", afterNow("2022-04-30"));
log.info("intervalDays: {}", intervalDays("2021-11-01", "2022-03-22"));
输出结果:
09:56:58.976 [main] INFO net.jhelp.easyql.kits.time.DateUtils - 当前时间:2022-05-07T09:56:58.970
09:56:58.996 [main] INFO net.jhelp.easyql.kits.time.DateUtils - 当前时间yyyy-MM-dd: 2022-05-07
09:56:58.997 [main] INFO net.jhelp.easyql.kits.time.DateUtils - 当前时间yyyy-MM-dd HH:mm:ss: 2022-05-07 09:56:58
09:56:58.999 [main] INFO net.jhelp.easyql.kits.time.DateUtils - formatByNumber : 2022-05-07
09:56:58.999 [main] INFO net.jhelp.easyql.kits.time.DateUtils - format(xx, xx): 2022-05-07
09:56:59.000 [main] INFO net.jhelp.easyql.kits.time.DateUtils - 字符串转日期: 2022-03-11T00:00
09:56:59.001 [main] INFO net.jhelp.easyql.kits.time.DateUtils - 字符串日期输出数字:1644549071000
09:56:59.001 [main] INFO net.jhelp.easyql.kits.time.DateUtils - 2022/4月的第一天:2022-04-01
09:56:59.003 [main] INFO net.jhelp.easyql.kits.time.DateUtils - 2022/2月的最后一天:2022-02-28
09:56:59.004 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayOfMonth : 7
09:56:59.005 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayOfWeek : 6
09:56:59.005 [main] INFO net.jhelp.easyql.kits.time.DateUtils - month : 5
09:56:59.005 [main] INFO net.jhelp.easyql.kits.time.DateUtils - year : 2022
09:56:59.006 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayByAddMin : 2022-05-07T10:26:59.005
09:56:59.006 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayByAddHour : 2022-05-07T10:56:59.006
09:56:59.007 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayByAddDay : 2022-05-08T09:56:59.006
09:56:59.007 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayByAddMonth : 2022-06-07T09:56:59.007
09:56:59.007 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayByAddYear : 2023-05-07T09:56:59.007
09:56:59.007 [main] INFO net.jhelp.easyql.kits.time.DateUtils - getCurHour24 : 9
09:56:59.022 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-01
09:56:59.022 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-02
09:56:59.022 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-03
09:56:59.022 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-04
09:56:59.022 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-05
09:56:59.022 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-06
09:56:59.022 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-07
09:56:59.022 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-08
09:56:59.022 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-09
09:56:59.022 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-10
09:56:59.022 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-11
09:56:59.022 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-12
09:56:59.023 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-13
09:56:59.023 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-14
09:56:59.023 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-15
09:56:59.023 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-16
09:56:59.023 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-17
09:56:59.023 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-18
09:56:59.023 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-19
09:56:59.023 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-20
09:56:59.023 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-21
09:56:59.023 [main] INFO net.jhelp.easyql.kits.time.DateUtils - dayStrBetween : 2022-03-22
09:56:59.024 [main] INFO net.jhelp.easyql.kits.time.DateUtils - afterNow: false
09:56:59.024 [main] INFO net.jhelp.easyql.kits.time.DateUtils - intervalDays: 141
总结
这个文章没有说java.util.Date不好,这是Java技术发展的必经之路,没办法一始就考虑全面,技术的发展是一步一步前进,只有不断地去思考、去实践、去重构、去考虑效率才能有更好的提升,这也是技术人员的成长之路,从初级、中级、高级、架构师这样的路发展,而如果不去思考与研究,可能就十年如一日,原地踏步,技术水平得不到提升。
建议在新的项目中多使用java.time中新的日期和时间处理的工具类及api,慢慢减少java.util.Date、Calendar、SimpleDateFormat的使用。
在下一篇中,会整理java中有关日期和时间的工具类及API的说明,及使用的例子(目前还未整理好),方便更多的称发小伙伴进行参考与使用,会提供PDF文档出来(可以点击查看:https://juejin.cn/post/7095672865785118750)。
想得到最新的文章内容,可以关注我的公众号:技术老男孩。