mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add method
This commit is contained in:
parent
3160742be1
commit
0ed05e88ef
@ -6,6 +6,7 @@
|
||||
# 5.7.5 (2021-07-12)
|
||||
|
||||
### 🐣新特性
|
||||
* 【core 】 DateUtil增加ceiling重载,可选是否归零毫秒
|
||||
|
||||
### 🐞Bug修复
|
||||
* 【core 】 修复FileUtil.normalize处理上级路径的问题(issue#I3YPEH@Gitee)
|
||||
|
@ -113,6 +113,23 @@ public class CalendarUtil {
|
||||
return DateModifier.modify(calendar, dateField.getValue(), DateModifier.ModifyType.CEILING);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改日期为某个时间字段结束时间<br>
|
||||
* 可选是否归零毫秒。
|
||||
*
|
||||
* <p>
|
||||
* 有时候由于毫秒部分必须为0(如MySQL数据库中),因此在此加上选项。
|
||||
* </p>
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField 时间字段
|
||||
* @param truncateMillisecond 是否毫秒归零
|
||||
* @return 原{@link Calendar}
|
||||
*/
|
||||
public static Calendar ceiling(Calendar calendar, DateField dateField, boolean truncateMillisecond) {
|
||||
return DateModifier.modify(calendar, dateField.getValue(), DateModifier.ModifyType.CEILING, truncateMillisecond);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒级别的开始时间,即忽略毫秒部分
|
||||
*
|
||||
@ -655,9 +672,9 @@ public class CalendarUtil {
|
||||
calendar.setLenient(lenient);
|
||||
|
||||
for (final String parsePattern : parsePatterns) {
|
||||
if(GlobalCustomFormat.isCustomFormat(parsePattern)){
|
||||
if (GlobalCustomFormat.isCustomFormat(parsePattern)) {
|
||||
final Date parse = GlobalCustomFormat.parse(str, parsePattern);
|
||||
if(null == parse){
|
||||
if (null == parse) {
|
||||
continue;
|
||||
}
|
||||
calendar.setTime(parse);
|
||||
|
@ -1,9 +1,9 @@
|
||||
package cn.hutool.core.date;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
* 日期修改器<br>
|
||||
* 用于实现自定义某个日期字段的调整,包括:
|
||||
@ -15,12 +15,13 @@ import cn.hutool.core.util.ArrayUtil;
|
||||
* </pre>
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
public class DateModifier {
|
||||
|
||||
/** 忽略的计算的字段 */
|
||||
private static final int[] IGNORE_FIELDS = new int[] { //
|
||||
/**
|
||||
* 忽略的计算的字段
|
||||
*/
|
||||
private static final int[] IGNORE_FIELDS = new int[]{ //
|
||||
Calendar.HOUR_OF_DAY, // 与HOUR同名
|
||||
Calendar.AM_PM, // 此字段单独处理,不参与计算起始和结束
|
||||
Calendar.DAY_OF_WEEK_IN_MONTH, // 不参与计算
|
||||
@ -32,36 +33,58 @@ public class DateModifier {
|
||||
/**
|
||||
* 修改日期
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField 日期字段,即保留到哪个日期字段
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField 日期字段,即保留到哪个日期字段
|
||||
* @param modifyType 修改类型,包括舍去、四舍五入、进一等
|
||||
* @return 修改后的{@link Calendar}
|
||||
*/
|
||||
public static Calendar modify(Calendar calendar, int dateField, ModifyType modifyType) {
|
||||
return modify(calendar, dateField, modifyType, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改日期,取起始值或者结束值<br>
|
||||
* 可选是否归零毫秒。
|
||||
*
|
||||
* <p>
|
||||
* 在{@link ModifyType#TRUNCATE}模式下,毫秒始终要归零,
|
||||
* 但是在{@link ModifyType#CEILING}和{@link ModifyType#ROUND}模式下,
|
||||
* 有时候由于毫秒部分必须为0(如MySQL数据库中),因此在此加上选项。
|
||||
* </p>
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param dateField 日期字段,即保留到哪个日期字段
|
||||
* @param modifyType 修改类型,包括舍去、四舍五入、进一等
|
||||
* @param truncateMillisecond 是否归零毫秒
|
||||
* @return 修改后的{@link Calendar}
|
||||
* @since 5.7.5
|
||||
*/
|
||||
public static Calendar modify(Calendar calendar, int dateField, ModifyType modifyType, boolean truncateMillisecond) {
|
||||
// AM_PM上下午特殊处理
|
||||
if (Calendar.AM_PM == dateField) {
|
||||
boolean isAM = DateUtil.isAM(calendar);
|
||||
switch (modifyType) {
|
||||
case TRUNCATE:
|
||||
calendar.set(Calendar.HOUR_OF_DAY, isAM ? 0 : 12);
|
||||
break;
|
||||
case CEILING:
|
||||
calendar.set(Calendar.HOUR_OF_DAY, isAM ? 11 : 23);
|
||||
break;
|
||||
case ROUND:
|
||||
int min = isAM ? 0 : 12;
|
||||
int max = isAM ? 11 : 23;
|
||||
int href = (max - min) / 2 + 1;
|
||||
int value = calendar.get(Calendar.HOUR_OF_DAY);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, (value < href) ? min : max);
|
||||
break;
|
||||
case TRUNCATE:
|
||||
calendar.set(Calendar.HOUR_OF_DAY, isAM ? 0 : 12);
|
||||
break;
|
||||
case CEILING:
|
||||
calendar.set(Calendar.HOUR_OF_DAY, isAM ? 11 : 23);
|
||||
break;
|
||||
case ROUND:
|
||||
int min = isAM ? 0 : 12;
|
||||
int max = isAM ? 11 : 23;
|
||||
int href = (max - min) / 2 + 1;
|
||||
int value = calendar.get(Calendar.HOUR_OF_DAY);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, (value < href) ? min : max);
|
||||
break;
|
||||
}
|
||||
// 处理下一级别字段
|
||||
return modify(calendar, dateField + 1, modifyType);
|
||||
}
|
||||
|
||||
final int endField = truncateMillisecond ? Calendar.SECOND : Calendar.MILLISECOND;
|
||||
// 循环处理各级字段,精确到毫秒字段
|
||||
for (int i = dateField + 1; i <= Calendar.MILLISECOND; i++) {
|
||||
for (int i = dateField + 1; i <= endField; i++) {
|
||||
if (ArrayUtil.contains(IGNORE_FIELDS, i)) {
|
||||
// 忽略无关字段(WEEK_OF_MONTH)始终不做修改
|
||||
continue;
|
||||
@ -81,15 +104,21 @@ public class DateModifier {
|
||||
|
||||
modifyField(calendar, i, modifyType);
|
||||
}
|
||||
|
||||
if (truncateMillisecond) {
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
}
|
||||
|
||||
return calendar;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
* 修改日期字段值
|
||||
*
|
||||
* @param calendar {@link Calendar}
|
||||
* @param field 字段,见{@link Calendar}
|
||||
* @param calendar {@link Calendar}
|
||||
* @param field 字段,见{@link Calendar}
|
||||
* @param modifyType {@link ModifyType}
|
||||
*/
|
||||
private static void modifyField(Calendar calendar, int field, ModifyType modifyType) {
|
||||
@ -99,25 +128,25 @@ public class DateModifier {
|
||||
}
|
||||
|
||||
switch (modifyType) {
|
||||
case TRUNCATE:
|
||||
calendar.set(field, DateUtil.getBeginValue(calendar, field));
|
||||
break;
|
||||
case CEILING:
|
||||
calendar.set(field, DateUtil.getEndValue(calendar, field));
|
||||
break;
|
||||
case ROUND:
|
||||
int min = DateUtil.getBeginValue(calendar, field);
|
||||
int max = DateUtil.getEndValue(calendar, field);
|
||||
int href;
|
||||
if (Calendar.DAY_OF_WEEK == field) {
|
||||
// 星期特殊处理,假设周一是第一天,中间的为周四
|
||||
href = (min + 3) % 7;
|
||||
} else {
|
||||
href = (max - min) / 2 + 1;
|
||||
}
|
||||
int value = calendar.get(field);
|
||||
calendar.set(field, (value < href) ? min : max);
|
||||
break;
|
||||
case TRUNCATE:
|
||||
calendar.set(field, DateUtil.getBeginValue(calendar, field));
|
||||
break;
|
||||
case CEILING:
|
||||
calendar.set(field, DateUtil.getEndValue(calendar, field));
|
||||
break;
|
||||
case ROUND:
|
||||
int min = DateUtil.getBeginValue(calendar, field);
|
||||
int max = DateUtil.getEndValue(calendar, field);
|
||||
int href;
|
||||
if (Calendar.DAY_OF_WEEK == field) {
|
||||
// 星期特殊处理,假设周一是第一天,中间的为周四
|
||||
href = (min + 3) % 7;
|
||||
} else {
|
||||
href = (max - min) / 2 + 1;
|
||||
}
|
||||
int value = calendar.get(field);
|
||||
calendar.set(field, (value < href) ? min : max);
|
||||
break;
|
||||
}
|
||||
// Console.log("# {} -> {}", DateField.of(field), calendar.get(field));
|
||||
}
|
||||
@ -127,7 +156,6 @@ public class DateModifier {
|
||||
* 修改类型
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
public enum ModifyType {
|
||||
/**
|
||||
|
@ -490,7 +490,7 @@ public class DateUtil extends CalendarUtil {
|
||||
}
|
||||
|
||||
// 检查自定义格式
|
||||
if(GlobalCustomFormat.isCustomFormat(format)){
|
||||
if (GlobalCustomFormat.isCustomFormat(format)) {
|
||||
return GlobalCustomFormat.format(date, format);
|
||||
}
|
||||
|
||||
@ -702,7 +702,7 @@ public class DateUtil extends CalendarUtil {
|
||||
* @since 4.5.18
|
||||
*/
|
||||
public static DateTime parse(CharSequence dateStr, String format, Locale locale) {
|
||||
if(GlobalCustomFormat.isCustomFormat(format)){
|
||||
if (GlobalCustomFormat.isCustomFormat(format)) {
|
||||
// 自定义格式化器忽略Locale
|
||||
return new DateTime(GlobalCustomFormat.parse(dateStr, format));
|
||||
}
|
||||
@ -828,7 +828,7 @@ public class DateUtil extends CalendarUtil {
|
||||
} else if (length == DatePattern.UTC_SIMPLE_PATTERN.length() - 2) {
|
||||
// 格式类似:2018-09-13T05:34:31
|
||||
return parse(utcString, DatePattern.UTC_SIMPLE_FORMAT);
|
||||
} else if (StrUtil.contains(utcString, CharUtil.DOT)){
|
||||
} else if (StrUtil.contains(utcString, CharUtil.DOT)) {
|
||||
// 可能为: 2021-03-17T06:31:33.99
|
||||
return parse(utcString, DatePattern.UTC_SIMPLE_MS_FORMAT);
|
||||
}
|
||||
@ -983,7 +983,25 @@ public class DateUtil extends CalendarUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒级别的开始时间,即忽略毫秒部分
|
||||
* 修改日期为某个时间字段结束时间<br>
|
||||
* 可选是否归零毫秒。
|
||||
*
|
||||
* <p>
|
||||
* 有时候由于毫秒部分必须为0(如MySQL数据库中),因此在此加上选项。
|
||||
* </p>
|
||||
*
|
||||
* @param date {@link Date}
|
||||
* @param dateField 时间字段
|
||||
* @param truncateMillisecond 是否毫秒归零
|
||||
* @return {@link DateTime}
|
||||
* @since 4.5.7
|
||||
*/
|
||||
public static DateTime ceiling(Date date, DateField dateField, boolean truncateMillisecond) {
|
||||
return new DateTime(ceiling(calendar(date), dateField, truncateMillisecond));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取秒级别的开始时间,即毫秒部分设置为0
|
||||
*
|
||||
* @param date 日期
|
||||
* @return {@link DateTime}
|
||||
@ -1847,13 +1865,12 @@ public class DateUtil extends CalendarUtil {
|
||||
/**
|
||||
* {@code null}安全的日期比较,并只比较指定格式; {@code null}对象排在末尾, 并指定日期格式;
|
||||
*
|
||||
*
|
||||
* @param date1 日期1
|
||||
* @param date2 日期2
|
||||
* @param date1 日期1
|
||||
* @param date2 日期2
|
||||
* @param format 日期格式,常用格式见: {@link DatePattern}; 允许为空; date1 date2; eg: yyyy-MM-dd
|
||||
* @return 比较结果,如果date1 < date2,返回数小于0,date1==date2返回0,date1 > date2 大于0
|
||||
* @since 5.6.4
|
||||
* @author dazer
|
||||
* @since 5.6.4
|
||||
*/
|
||||
public static int compare(Date date1, Date date2, String format) {
|
||||
if (format != null) {
|
||||
|
@ -122,6 +122,32 @@ public class DateUtilTest {
|
||||
Assert.assertEquals("2020-02-29 12:59:00", dateTime.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ceilingMinuteTest(){
|
||||
String dateStr2 = "2020-02-29 12:59:34";
|
||||
Date date2 = DateUtil.parse(dateStr2);
|
||||
|
||||
|
||||
DateTime dateTime = DateUtil.ceiling(date2, DateField.MINUTE);
|
||||
Assert.assertEquals("2020-02-29 12:59:59.999", dateTime.toString(DatePattern.NORM_DATETIME_MS_PATTERN));
|
||||
|
||||
dateTime = DateUtil.ceiling(date2, DateField.MINUTE, true);
|
||||
Assert.assertEquals("2020-02-29 12:59:59.000", dateTime.toString(DatePattern.NORM_DATETIME_MS_PATTERN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ceilingDayTest(){
|
||||
String dateStr2 = "2020-02-29 12:59:34";
|
||||
Date date2 = DateUtil.parse(dateStr2);
|
||||
|
||||
|
||||
DateTime dateTime = DateUtil.ceiling(date2, DateField.DAY_OF_MONTH);
|
||||
Assert.assertEquals("2020-02-29 23:59:59.999", dateTime.toString(DatePattern.NORM_DATETIME_MS_PATTERN));
|
||||
|
||||
dateTime = DateUtil.ceiling(date2, DateField.DAY_OF_MONTH, true);
|
||||
Assert.assertEquals("2020-02-29 23:59:59.000", dateTime.toString(DatePattern.NORM_DATETIME_MS_PATTERN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beginOfWeekTest() {
|
||||
String dateStr = "2017-03-01 22:33:23";
|
||||
|
Loading…
x
Reference in New Issue
Block a user