mirror of
https://gitee.com/dromara/hutool.git
synced 2025-05-02 20:02:49 +08:00
add CalendarUtil
This commit is contained in:
parent
bc486cdac4
commit
4a574e3241
@ -24,6 +24,7 @@
|
||||
* 【json 】 解析Object中对是否为bean单独判断,而不是直接解析
|
||||
* 【core 】 SimHash锁改为StampedLock
|
||||
* 【core 】 Singleton改为SimpleCache实现
|
||||
* 【core 】 增加CalendarUtil,DateUtil相关方法全部迁移到此
|
||||
|
||||
### Bug修复
|
||||
* 【extra 】 修复SpringUtil使用devtools重启报错问题
|
||||
|
File diff suppressed because it is too large
Load Diff
430
hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java
Normal file
430
hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java
Normal file
@ -0,0 +1,430 @@
|
||||
package cn.hutool.core.date;
|
||||
|
||||
import cn.hutool.core.comparator.CompareUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
/**
|
||||
* 针对{@link Calendar} 对象封装工具类
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.3.0
|
||||
*/
|
||||
public class CalendarUtil {
|
||||
|
||||
/**
|
||||
* 创建Calendar对象,时间为默认时区的当前时间
|
||||
*
|
||||
* @return Calendar对象
|
||||
* @since 4.6.6
|
||||
*/
|
||||
public static Calendar calendar() {
|
||||
return Calendar.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Calendar对象
|
||||
*
|
||||
* @param date 日期对象
|
||||
* @return Calendar对象
|
||||
*/
|
||||
public static Calendar calendar(Date date) {
|
||||
if (date instanceof DateTime) {
|
||||
return ((DateTime) date).toCalendar();
|
||||
} else {
|
||||
return calendar(date.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Calendar对象
|
||||
*
|
||||
* @param millis 时间戳
|
||||
* @return Calendar对象
|
||||
*/
|
||||
public static Calendar calendar(long millis) {
|
||||
final Calendar cal = Calendar.getInstance();
|
||||
cal.setTimeInMillis(millis);
|
||||
return cal;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为上午
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @return 是否为上午
|
||||
*/
|
||||
public static boolean isAM(Calendar calendar) {
|
||||
return Calendar.AM == calendar.get(Calendar.AM_PM);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为下午
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @return 是否为下午
|
||||
*/
|
||||
public static boolean isPM(Calendar calendar) {
|
||||
return Calendar.PM == calendar.get(Calendar.AM_PM);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改日期为某个时间字段起始时间
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField 时间字段
|
||||
* @return 原{@link Calendar}
|
||||
*/
|
||||
public static Calendar truncate(Calendar calendar, DateField dateField) {
|
||||
return DateModifier.modify(calendar, dateField.getValue(), DateModifier.ModifyType.TRUNCATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改日期为某个时间字段四舍五入时间
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField 时间字段
|
||||
* @return 原{@link Calendar}
|
||||
*/
|
||||
public static Calendar round(Calendar calendar, DateField dateField) {
|
||||
return DateModifier.modify(calendar, dateField.getValue(), DateModifier.ModifyType.ROUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改日期为某个时间字段结束时间
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField 时间字段
|
||||
* @return 原{@link Calendar}
|
||||
*/
|
||||
public static Calendar ceiling(Calendar calendar, DateField dateField) {
|
||||
return DateModifier.modify(calendar, dateField.getValue(), DateModifier.ModifyType.CEILING);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒级别的开始时间,即忽略毫秒部分
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
* @since 4.6.2
|
||||
*/
|
||||
public static Calendar beginOfSecond(Calendar calendar) {
|
||||
return truncate(calendar, DateField.SECOND);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒级别的结束时间,即毫秒设置为999
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
* @since 4.6.2
|
||||
*/
|
||||
public static Calendar endOfSecond(Calendar calendar) {
|
||||
return ceiling(calendar, DateField.SECOND);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某天的开始时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar beginOfDay(Calendar calendar) {
|
||||
return truncate(calendar, DateField.DAY_OF_MONTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某天的结束时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar endOfDay(Calendar calendar) {
|
||||
return ceiling(calendar, DateField.DAY_OF_MONTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取给定日期当前周的开始时间,周一定为一周的开始时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar beginOfWeek(Calendar calendar) {
|
||||
return beginOfWeek(calendar, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取给定日期当前周的开始时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @param isMondayAsFirstDay 是否周一做为一周的第一天(false表示周日做为第一天)
|
||||
* @return {@link Calendar}
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public static Calendar beginOfWeek(Calendar calendar, boolean isMondayAsFirstDay) {
|
||||
calendar.setFirstDayOfWeek(isMondayAsFirstDay ? Calendar.MONDAY : Calendar.SUNDAY);
|
||||
// WEEK_OF_MONTH为上限的字段(不包括),实际调整的为DAY_OF_MONTH
|
||||
return truncate(calendar, DateField.WEEK_OF_MONTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某周的结束时间,周日定为一周的结束
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar endOfWeek(Calendar calendar) {
|
||||
return endOfWeek(calendar, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某周的结束时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @param isSundayAsLastDay 是否周日做为一周的最后一天(false表示周六做为最后一天)
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar endOfWeek(Calendar calendar, boolean isSundayAsLastDay) {
|
||||
calendar.setFirstDayOfWeek(isSundayAsLastDay ? Calendar.MONDAY : Calendar.SUNDAY);
|
||||
// WEEK_OF_MONTH为上限的字段(不包括),实际调整的为DAY_OF_MONTH
|
||||
return ceiling(calendar, DateField.WEEK_OF_MONTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某月的开始时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar beginOfMonth(Calendar calendar) {
|
||||
return truncate(calendar, DateField.MONTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某月的结束时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar endOfMonth(Calendar calendar) {
|
||||
return ceiling(calendar, DateField.MONTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某季度的开始时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
* @since 4.1.0
|
||||
*/
|
||||
public static Calendar beginOfQuarter(Calendar calendar) {
|
||||
//noinspection MagicConstant
|
||||
calendar.set(Calendar.MONTH, calendar.get(DateField.MONTH.getValue()) / 3 * 3);
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
||||
return beginOfDay(calendar);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某季度的结束时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
* @since 4.1.0
|
||||
*/
|
||||
public static Calendar endOfQuarter(Calendar calendar) {
|
||||
//noinspection MagicConstant
|
||||
calendar.set(Calendar.MONTH, calendar.get(DateField.MONTH.getValue()) / 3 * 3 + 2);
|
||||
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
|
||||
return endOfDay(calendar);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某年的开始时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar beginOfYear(Calendar calendar) {
|
||||
return truncate(calendar, DateField.YEAR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某年的结束时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar endOfYear(Calendar calendar) {
|
||||
return ceiling(calendar, DateField.YEAR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较两个日期是否为同一天
|
||||
*
|
||||
* @param cal1 日期1
|
||||
* @param cal2 日期2
|
||||
* @return 是否为同一天
|
||||
*/
|
||||
public static boolean isSameDay(Calendar cal1, Calendar cal2) {
|
||||
if (cal1 == null || cal2 == null) {
|
||||
throw new IllegalArgumentException("The date must not be null");
|
||||
}
|
||||
return cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR) && //
|
||||
cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && //
|
||||
cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得指定日期区间内的年份和季节<br>
|
||||
*
|
||||
* @param startDate 起始日期(包含)
|
||||
* @param endDate 结束日期(包含)
|
||||
* @return 季度列表 ,元素类似于 20132
|
||||
* @since 4.1.15
|
||||
*/
|
||||
public static LinkedHashSet<String> yearAndQuarter(long startDate, long endDate) {
|
||||
LinkedHashSet<String> quarters = new LinkedHashSet<>();
|
||||
final Calendar cal = calendar(startDate);
|
||||
while (startDate <= endDate) {
|
||||
// 如果开始时间超出结束时间,让结束时间为开始时间,处理完后结束循环
|
||||
quarters.add(yearAndQuarter(cal));
|
||||
|
||||
cal.add(Calendar.MONTH, 3);
|
||||
startDate = cal.getTimeInMillis();
|
||||
}
|
||||
|
||||
return quarters;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得指定日期年份和季节<br>
|
||||
* 格式:[20131]表示2013年第一季度
|
||||
*
|
||||
* @param cal 日期
|
||||
*/
|
||||
public static String yearAndQuarter(Calendar cal) {
|
||||
return StrUtil.builder().append(cal.get(Calendar.YEAR)).append(cal.get(Calendar.MONTH) / 3 + 1).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定日期字段的最小值,例如分钟的最小值是0
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField {@link DateField}
|
||||
* @return 字段最小值
|
||||
* @see Calendar#getActualMinimum(int)
|
||||
* @since 4.5.7
|
||||
*/
|
||||
public static int getBeginValue(Calendar calendar, int dateField) {
|
||||
if (Calendar.DAY_OF_WEEK == dateField) {
|
||||
return calendar.getFirstDayOfWeek();
|
||||
}
|
||||
return calendar.getActualMinimum(dateField);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定日期字段的最大值,例如分钟的最大值是59
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField {@link DateField}
|
||||
* @return 字段最大值
|
||||
* @see Calendar#getActualMaximum(int)
|
||||
* @since 4.5.7
|
||||
*/
|
||||
public static int getEndValue(Calendar calendar, int dateField) {
|
||||
if (Calendar.DAY_OF_WEEK == dateField) {
|
||||
return (calendar.getFirstDayOfWeek() + 6) % 7;
|
||||
}
|
||||
return calendar.getActualMaximum(dateField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calendar{@link Instant}对象
|
||||
*
|
||||
* @param calendar Date对象
|
||||
* @return {@link Instant}对象
|
||||
* @since 5.0.5
|
||||
*/
|
||||
public static Instant toInstant(Calendar calendar) {
|
||||
return null == calendar ? null : calendar.toInstant();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Calendar} 转换为 {@link LocalDateTime},使用系统默认时区
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @return {@link LocalDateTime}
|
||||
* @since 5.0.5
|
||||
*/
|
||||
public static LocalDateTime toLocalDateTime(Calendar calendar) {
|
||||
return LocalDateTime.ofInstant(calendar.toInstant(), calendar.getTimeZone().toZoneId());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code null}安全的{@link Calendar}比较,{@code null}小于任何日期
|
||||
*
|
||||
* @param calendar1 日期1
|
||||
* @param calendar2 日期2
|
||||
* @return 比较结果,如果calendar1 < calendar2,返回数小于0,calendar1==calendar2返回0,calendar1 > calendar2 大于0
|
||||
* @since 4.6.2
|
||||
*/
|
||||
public static int compare(Calendar calendar1, Calendar calendar2) {
|
||||
return CompareUtil.compare(calendar1, calendar2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算相对于dateToCompare的年龄,长用于计算指定生日在某年的年龄
|
||||
*
|
||||
* @param birthday 生日
|
||||
* @param dateToCompare 需要对比的日期
|
||||
* @return 年龄
|
||||
*/
|
||||
public static int age(Calendar birthday, Calendar dateToCompare) {
|
||||
return age(birthday.getTimeInMillis(), dateToCompare.getTimeInMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算相对于dateToCompare的年龄,长用于计算指定生日在某年的年龄
|
||||
*
|
||||
* @param birthday 生日
|
||||
* @param dateToCompare 需要对比的日期
|
||||
* @return 年龄
|
||||
*/
|
||||
protected static int age(long birthday, long dateToCompare) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTimeInMillis(dateToCompare);
|
||||
|
||||
if (cal.before(birthday)) {
|
||||
throw new IllegalArgumentException("Birthday is after dateToCompare!");
|
||||
}
|
||||
|
||||
final int year = cal.get(Calendar.YEAR);
|
||||
final int month = cal.get(Calendar.MONTH);
|
||||
final int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
|
||||
final boolean isLastDayOfMonth = dayOfMonth == cal.getActualMaximum(Calendar.DAY_OF_MONTH);
|
||||
|
||||
cal.setTimeInMillis(birthday);
|
||||
int age = year - cal.get(Calendar.YEAR);
|
||||
|
||||
final int monthBirth = cal.get(Calendar.MONTH);
|
||||
if (month == monthBirth) {
|
||||
|
||||
final int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
|
||||
final boolean isLastDayOfMonthBirth = dayOfMonthBirth == cal.getActualMaximum(Calendar.DAY_OF_MONTH);
|
||||
if ((false == isLastDayOfMonth || false == isLastDayOfMonthBirth) && dayOfMonth < dayOfMonthBirth) {
|
||||
// 如果生日在当月,但是未达到生日当天的日期,年龄减一
|
||||
age--;
|
||||
}
|
||||
} else if (month < monthBirth) {
|
||||
// 如果当前月份未达到生日的月份,年龄计算减一
|
||||
age--;
|
||||
}
|
||||
|
||||
return age;
|
||||
}
|
||||
}
|
@ -3,10 +3,10 @@ package cn.hutool.core.date;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.comparator.CompareUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.date.DateModifier.ModifyType;
|
||||
import cn.hutool.core.date.format.DateParser;
|
||||
import cn.hutool.core.date.format.DatePrinter;
|
||||
import cn.hutool.core.date.format.FastDateFormat;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.lang.PatternPool;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
@ -39,7 +39,7 @@ import java.util.concurrent.TimeUnit;
|
||||
*
|
||||
* @author xiaoleilu
|
||||
*/
|
||||
public class DateUtil {
|
||||
public class DateUtil extends CalendarUtil {
|
||||
|
||||
/**
|
||||
* java.util.Date EEE MMM zzz 缩写数组
|
||||
@ -129,42 +129,6 @@ public class DateUtil {
|
||||
return new DateTime(temporalAccessor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Calendar对象,时间为默认时区的当前时间
|
||||
*
|
||||
* @return Calendar对象
|
||||
* @since 4.6.6
|
||||
*/
|
||||
public static Calendar calendar() {
|
||||
return Calendar.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Calendar对象
|
||||
*
|
||||
* @param date 日期对象
|
||||
* @return Calendar对象
|
||||
*/
|
||||
public static Calendar calendar(Date date) {
|
||||
if (date instanceof DateTime) {
|
||||
return ((DateTime) date).toCalendar();
|
||||
} else {
|
||||
return calendar(date.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为Calendar对象
|
||||
*
|
||||
* @param millis 时间戳
|
||||
* @return Calendar对象
|
||||
*/
|
||||
public static Calendar calendar(long millis) {
|
||||
final Calendar cal = Calendar.getInstance();
|
||||
cal.setTimeInMillis(millis);
|
||||
return cal;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前时间的时间戳
|
||||
*
|
||||
@ -359,17 +323,6 @@ public class DateUtil {
|
||||
return DateTime.of(date).isAM();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为上午
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @return 是否为上午
|
||||
* @since 4.5.7
|
||||
*/
|
||||
public static boolean isAM(Calendar calendar) {
|
||||
return Calendar.AM == calendar.get(Calendar.AM_PM);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为下午
|
||||
*
|
||||
@ -490,29 +443,6 @@ public class DateUtil {
|
||||
}
|
||||
return yearAndQuarter(startDate.getTime(), endDate.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得指定日期区间内的年份和季节<br>
|
||||
*
|
||||
* @param startDate 起始日期(包含)
|
||||
* @param endDate 结束日期(包含)
|
||||
* @return 季度列表 ,元素类似于 20132
|
||||
* @since 4.1.15
|
||||
*/
|
||||
public static LinkedHashSet<String> yearAndQuarter(long startDate, long endDate) {
|
||||
LinkedHashSet<String> quarters = new LinkedHashSet<>();
|
||||
final Calendar cal = calendar(startDate);
|
||||
while (startDate <= endDate) {
|
||||
// 如果开始时间超出结束时间,让结束时间为开始时间,处理完后结束循环
|
||||
quarters.add(yearAndQuarter(cal));
|
||||
|
||||
cal.add(Calendar.MONTH, 3);
|
||||
startDate = cal.getTimeInMillis();
|
||||
}
|
||||
|
||||
return quarters;
|
||||
}
|
||||
|
||||
// ------------------------------------ Format start ----------------------------------------------
|
||||
|
||||
/**
|
||||
@ -986,18 +916,6 @@ public class DateUtil {
|
||||
return new DateTime(truncate(calendar(date), dateField));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改日期为某个时间字段起始时间
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField 时间字段
|
||||
* @return 原{@link Calendar}
|
||||
* @since 4.5.7
|
||||
*/
|
||||
public static Calendar truncate(Calendar calendar, DateField dateField) {
|
||||
return DateModifier.modify(calendar, dateField.getValue(), ModifyType.TRUNCATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改日期为某个时间字段四舍五入时间
|
||||
*
|
||||
@ -1010,18 +928,6 @@ public class DateUtil {
|
||||
return new DateTime(round(calendar(date), dateField));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改日期为某个时间字段四舍五入时间
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField 时间字段
|
||||
* @return 原{@link Calendar}
|
||||
* @since 4.5.7
|
||||
*/
|
||||
public static Calendar round(Calendar calendar, DateField dateField) {
|
||||
return DateModifier.modify(calendar, dateField.getValue(), ModifyType.ROUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改日期为某个时间字段结束时间
|
||||
*
|
||||
@ -1034,18 +940,6 @@ public class DateUtil {
|
||||
return new DateTime(ceiling(calendar(date), dateField));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改日期为某个时间字段结束时间
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField 时间字段
|
||||
* @return 原{@link Calendar}
|
||||
* @since 4.5.7
|
||||
*/
|
||||
public static Calendar ceiling(Calendar calendar, DateField dateField) {
|
||||
return DateModifier.modify(calendar, dateField.getValue(), ModifyType.CEILING);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒级别的开始时间,即忽略毫秒部分
|
||||
*
|
||||
@ -1068,28 +962,6 @@ public class DateUtil {
|
||||
return new DateTime(endOfSecond(calendar(date)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒级别的开始时间,即忽略毫秒部分
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
* @since 4.6.2
|
||||
*/
|
||||
public static Calendar beginOfSecond(Calendar calendar) {
|
||||
return truncate(calendar, DateField.SECOND);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒级别的结束时间,即毫秒设置为999
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
* @since 4.6.2
|
||||
*/
|
||||
public static Calendar endOfSecond(Calendar calendar) {
|
||||
return ceiling(calendar, DateField.SECOND);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某天的开始时间
|
||||
*
|
||||
@ -1110,26 +982,6 @@ public class DateUtil {
|
||||
return new DateTime(endOfDay(calendar(date)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某天的开始时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar beginOfDay(Calendar calendar) {
|
||||
return truncate(calendar, DateField.DAY_OF_MONTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某天的结束时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar endOfDay(Calendar calendar) {
|
||||
return ceiling(calendar, DateField.DAY_OF_MONTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某周的开始时间,周一定为一周的开始时间
|
||||
*
|
||||
@ -1150,54 +1002,6 @@ public class DateUtil {
|
||||
return new DateTime(endOfWeek(calendar(date)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取给定日期当前周的开始时间,周一定为一周的开始时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar beginOfWeek(Calendar calendar) {
|
||||
return beginOfWeek(calendar, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取给定日期当前周的开始时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @param isMondayAsFirstDay 是否周一做为一周的第一天(false表示周日做为第一天)
|
||||
* @return {@link Calendar}
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public static Calendar beginOfWeek(Calendar calendar, boolean isMondayAsFirstDay) {
|
||||
calendar.setFirstDayOfWeek(isMondayAsFirstDay ? Calendar.MONDAY : Calendar.SUNDAY);
|
||||
// WEEK_OF_MONTH为上限的字段(不包括),实际调整的为DAY_OF_MONTH
|
||||
return truncate(calendar, DateField.WEEK_OF_MONTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某周的结束时间,周日定为一周的结束
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar endOfWeek(Calendar calendar) {
|
||||
return endOfWeek(calendar, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某周的结束时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @param isSundayAsLastDay 是否周日做为一周的最后一天(false表示周六做为最后一天)
|
||||
* @return {@link Calendar}
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public static Calendar endOfWeek(Calendar calendar, boolean isSundayAsLastDay) {
|
||||
calendar.setFirstDayOfWeek(isSundayAsLastDay ? Calendar.MONDAY : Calendar.SUNDAY);
|
||||
// WEEK_OF_MONTH为上限的字段(不包括),实际调整的为DAY_OF_MONTH
|
||||
return ceiling(calendar, DateField.WEEK_OF_MONTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某月的开始时间
|
||||
*
|
||||
@ -1218,26 +1022,6 @@ public class DateUtil {
|
||||
return new DateTime(endOfMonth(calendar(date)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某月的开始时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar beginOfMonth(Calendar calendar) {
|
||||
return truncate(calendar, DateField.MONTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某月的结束时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar endOfMonth(Calendar calendar) {
|
||||
return ceiling(calendar, DateField.MONTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某季度的开始时间
|
||||
*
|
||||
@ -1258,34 +1042,6 @@ public class DateUtil {
|
||||
return new DateTime(endOfQuarter(calendar(date)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某季度的开始时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
* @since 4.1.0
|
||||
*/
|
||||
public static Calendar beginOfQuarter(Calendar calendar) {
|
||||
//noinspection MagicConstant
|
||||
calendar.set(Calendar.MONTH, calendar.get(DateField.MONTH.getValue()) / 3 * 3);
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
||||
return beginOfDay(calendar);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某季度的结束时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
* @since 4.1.0
|
||||
*/
|
||||
public static Calendar endOfQuarter(Calendar calendar) {
|
||||
//noinspection MagicConstant
|
||||
calendar.set(Calendar.MONTH, calendar.get(DateField.MONTH.getValue()) / 3 * 3 + 2);
|
||||
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
|
||||
return endOfDay(calendar);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某年的开始时间
|
||||
*
|
||||
@ -1305,27 +1061,6 @@ public class DateUtil {
|
||||
public static DateTime endOfYear(Date date) {
|
||||
return new DateTime(endOfYear(calendar(date)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某年的开始时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar beginOfYear(Calendar calendar) {
|
||||
return truncate(calendar, DateField.YEAR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某年的结束时间
|
||||
*
|
||||
* @param calendar 日期 {@link Calendar}
|
||||
* @return {@link Calendar}
|
||||
*/
|
||||
public static Calendar endOfYear(Calendar calendar) {
|
||||
return ceiling(calendar, DateField.YEAR);
|
||||
}
|
||||
|
||||
// --------------------------------------------------- Offset for now
|
||||
|
||||
/**
|
||||
@ -1554,9 +1289,9 @@ public class DateUtil {
|
||||
/**
|
||||
* 计算指定指定时间区间内的周数
|
||||
*
|
||||
* @param beginDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @param isReset 是否重置时间为起始时间
|
||||
* @param beginDate 开始时间
|
||||
* @param endDate 结束时间
|
||||
* @param isReset 是否重置时间为起始时间
|
||||
* @return 周数
|
||||
*/
|
||||
public static long betweenWeek(Date beginDate, Date endDate, boolean isReset) {
|
||||
@ -1686,23 +1421,6 @@ public class DateUtil {
|
||||
return isSameDay(calendar(date1), calendar(date2));
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较两个日期是否为同一天
|
||||
*
|
||||
* @param cal1 日期1
|
||||
* @param cal2 日期2
|
||||
* @return 是否为同一天
|
||||
* @since 4.1.13
|
||||
*/
|
||||
public static boolean isSameDay(Calendar cal1, Calendar cal2) {
|
||||
if (cal1 == null || cal2 == null) {
|
||||
throw new IllegalArgumentException("The date must not be null");
|
||||
}
|
||||
return cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR) && //
|
||||
cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && //
|
||||
cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计时,常用于记录某段代码的执行时间,单位:纳秒
|
||||
*
|
||||
@ -1863,41 +1581,16 @@ public class DateUtil {
|
||||
/**
|
||||
* 计算相对于dateToCompare的年龄,长用于计算指定生日在某年的年龄
|
||||
*
|
||||
* @param birthDay 生日
|
||||
* @param birthday 生日
|
||||
* @param dateToCompare 需要对比的日期
|
||||
* @return 年龄
|
||||
*/
|
||||
public static int age(Date birthDay, Date dateToCompare) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(dateToCompare);
|
||||
|
||||
if (cal.before(birthDay)) {
|
||||
throw new IllegalArgumentException(StrUtil.format("Birthday is after date {}!", formatDate(dateToCompare)));
|
||||
public static int age(Date birthday, Date dateToCompare) {
|
||||
Assert.notNull(birthday, "Birthday can not be null !");
|
||||
if (null == dateToCompare) {
|
||||
dateToCompare = date();
|
||||
}
|
||||
|
||||
final int year = cal.get(Calendar.YEAR);
|
||||
final int month = cal.get(Calendar.MONTH);
|
||||
final int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
|
||||
final boolean isLastDayOfMonth = dayOfMonth == cal.getActualMaximum(Calendar.DAY_OF_MONTH);
|
||||
|
||||
cal.setTime(birthDay);
|
||||
int age = year - cal.get(Calendar.YEAR);
|
||||
|
||||
final int monthBirth = cal.get(Calendar.MONTH);
|
||||
if (month == monthBirth) {
|
||||
|
||||
final int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
|
||||
final boolean isLastDayOfMonthBirth = dayOfMonthBirth == cal.getActualMaximum(Calendar.DAY_OF_MONTH);
|
||||
if ((false == isLastDayOfMonth || false == isLastDayOfMonthBirth) && dayOfMonth < dayOfMonthBirth) {
|
||||
// 如果生日在当月,但是未达到生日当天的日期,年龄减一
|
||||
age--;
|
||||
}
|
||||
} else if (month < monthBirth) {
|
||||
// 如果当前月份未达到生日的月份,年龄计算减一
|
||||
age--;
|
||||
}
|
||||
|
||||
return age;
|
||||
return age(birthday.getTime(), dateToCompare.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2042,38 +1735,6 @@ public class DateUtil {
|
||||
return Zodiac.getChineseZodiac(year);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定日期字段的最小值,例如分钟的最小值是0
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField {@link DateField}
|
||||
* @return 字段最小值
|
||||
* @see Calendar#getActualMinimum(int)
|
||||
* @since 4.5.7
|
||||
*/
|
||||
public static int getBeginValue(Calendar calendar, int dateField) {
|
||||
if (Calendar.DAY_OF_WEEK == dateField) {
|
||||
return calendar.getFirstDayOfWeek();
|
||||
}
|
||||
return calendar.getActualMinimum(dateField);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定日期字段的最大值,例如分钟的最大值是59
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField {@link DateField}
|
||||
* @return 字段最大值
|
||||
* @see Calendar#getActualMaximum(int)
|
||||
* @since 4.5.7
|
||||
*/
|
||||
public static int getEndValue(Calendar calendar, int dateField) {
|
||||
if (Calendar.DAY_OF_WEEK == dateField) {
|
||||
return (calendar.getFirstDayOfWeek() + 6) % 7;
|
||||
}
|
||||
return calendar.getActualMaximum(dateField);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code null}安全的日期比较,{@code null}对象排在末尾
|
||||
*
|
||||
@ -2086,18 +1747,6 @@ public class DateUtil {
|
||||
return CompareUtil.compare(date1, date2);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code null}安全的{@link Calendar}比较,{@code null}小于任何日期
|
||||
*
|
||||
* @param calendar1 日期1
|
||||
* @param calendar2 日期2
|
||||
* @return 比较结果,如果calendar1 < calendar2,返回数小于0,calendar1==calendar2返回0,calendar1 > calendar2 大于0
|
||||
* @since 4.6.2
|
||||
*/
|
||||
public static int compare(Calendar calendar1, Calendar calendar2) {
|
||||
return CompareUtil.compare(calendar1, calendar2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 纳秒转毫秒
|
||||
*
|
||||
@ -2131,17 +1780,6 @@ public class DateUtil {
|
||||
return null == date ? null : date.toInstant();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calendar{@link Instant}对象
|
||||
*
|
||||
* @param calendar Date对象
|
||||
* @return {@link Instant}对象
|
||||
* @since 5.0.5
|
||||
*/
|
||||
public static Instant toInstant(Calendar calendar) {
|
||||
return null == calendar ? null : calendar.toInstant();
|
||||
}
|
||||
|
||||
/**
|
||||
* Date对象转换为{@link Instant}对象
|
||||
*
|
||||
@ -2189,21 +1827,10 @@ public class DateUtil {
|
||||
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Calendar} 转换为 {@link LocalDateTime},使用系统默认时区
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @return {@link LocalDateTime}
|
||||
* @since 5.0.5
|
||||
*/
|
||||
public static LocalDateTime toLocalDateTime(Calendar calendar) {
|
||||
return LocalDateTime.ofInstant(calendar.toInstant(), calendar.getTimeZone().toZoneId());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Date} 转换为 {@link LocalDateTime},使用系统默认时区
|
||||
*
|
||||
* @param date {@link Calendar}
|
||||
* @param date {@link Date}
|
||||
* @return {@link LocalDateTime}
|
||||
* @since 5.0.5
|
||||
*/
|
||||
@ -2214,16 +1841,6 @@ public class DateUtil {
|
||||
|
||||
// ------------------------------------------------------------------------ Private method start
|
||||
|
||||
/**
|
||||
* 获得指定日期年份和季节<br>
|
||||
* 格式:[20131]表示2013年第一季度
|
||||
*
|
||||
* @param cal 日期
|
||||
*/
|
||||
private static String yearAndQuarter(Calendar cal) {
|
||||
return StrUtil.builder().append(cal.get(Calendar.YEAR)).append(cal.get(Calendar.MONTH) / 3 + 1).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 标准化日期,默认处理以空格区分的日期时间格式,空格前为日期,空格后为时间:<br>
|
||||
* 将以下字符替换为"-"
|
||||
|
@ -329,28 +329,36 @@ public class DateUtilTest {
|
||||
Assert.assertEquals("20190321", ymd);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Test
|
||||
public void parseTest5() {
|
||||
// 测试时间解析
|
||||
//noinspection ConstantConditions
|
||||
String time = DateUtil.parse("22:12:12").toString(DatePattern.NORM_TIME_FORMAT);
|
||||
Assert.assertEquals("22:12:12", time);
|
||||
//noinspection ConstantConditions
|
||||
time = DateUtil.parse("2:12:12").toString(DatePattern.NORM_TIME_FORMAT);
|
||||
Assert.assertEquals("02:12:12", time);
|
||||
//noinspection ConstantConditions
|
||||
time = DateUtil.parse("2:2:12").toString(DatePattern.NORM_TIME_FORMAT);
|
||||
Assert.assertEquals("02:02:12", time);
|
||||
//noinspection ConstantConditions
|
||||
time = DateUtil.parse("2:2:1").toString(DatePattern.NORM_TIME_FORMAT);
|
||||
Assert.assertEquals("02:02:01", time);
|
||||
//noinspection ConstantConditions
|
||||
time = DateUtil.parse("22:2:1").toString(DatePattern.NORM_TIME_FORMAT);
|
||||
Assert.assertEquals("22:02:01", time);
|
||||
//noinspection ConstantConditions
|
||||
time = DateUtil.parse("2:22:1").toString(DatePattern.NORM_TIME_FORMAT);
|
||||
Assert.assertEquals("02:22:01", time);
|
||||
|
||||
// 测试两位时间解析
|
||||
//noinspection ConstantConditions
|
||||
time = DateUtil.parse("2:22").toString(DatePattern.NORM_TIME_FORMAT);
|
||||
Assert.assertEquals("02:22:00", time);
|
||||
//noinspection ConstantConditions
|
||||
time = DateUtil.parse("12:22").toString(DatePattern.NORM_TIME_FORMAT);
|
||||
Assert.assertEquals("12:22:00", time);
|
||||
//noinspection ConstantConditions
|
||||
time = DateUtil.parse("12:2").toString(DatePattern.NORM_TIME_FORMAT);
|
||||
Assert.assertEquals("12:02:00", time);
|
||||
|
||||
@ -688,6 +696,14 @@ public class DateUtilTest {
|
||||
Assert.assertEquals(18, age);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void ageTest2(){
|
||||
String d1 = "2019-02-29";
|
||||
String d2 = "2018-02-28";
|
||||
final int age = DateUtil.age(DateUtil.parseDate(d1), DateUtil.parseDate(d2));
|
||||
Assert.assertEquals(18, age);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isExpiredTest(){
|
||||
DateTime startDate = DateUtil.parse("2019-12-01 17:02:30");
|
||||
|
Loading…
Reference in New Issue
Block a user