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