diff --git a/CHANGELOG.md b/CHANGELOG.md index c6778ddbb..caba2aed1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -# 5.7.16 (2021-10-27) +# 5.7.16 (2021-10-28) ### 🐣新特性 * 【core 】 增加DateTime.toLocalDateTime @@ -13,6 +13,8 @@ * 【core 】 NumberUtil.compare修正注释说明(issue#I4FAJ1@Gitee) * 【core 】 增加RFC3986类 * 【extra 】 Sftp增加put和upload重载(issue#I4FGDH@Gitee) +* 【core 】 TemporalUtil增加toChronoUnit、toTimeUnit方法(issue#I4FGDH@Gitee) +* 【core 】 StopWatch增加prettyPrint重载(issue#1910@Github) ### 🐞Bug修复 * 【core 】 修复UrlBuilder.addPath歧义问题(issue#1912@Github) diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java b/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java index 2475cb022..5cac6c295 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java @@ -20,6 +20,7 @@ import cn.hutool.core.convert.impl.EnumConverter; import cn.hutool.core.convert.impl.LocaleConverter; import cn.hutool.core.convert.impl.MapConverter; import cn.hutool.core.convert.impl.NumberConverter; +import cn.hutool.core.convert.impl.OptConverter; import cn.hutool.core.convert.impl.OptionalConverter; import cn.hutool.core.convert.impl.PathConverter; import cn.hutool.core.convert.impl.PeriodConverter; @@ -33,6 +34,7 @@ import cn.hutool.core.convert.impl.URIConverter; import cn.hutool.core.convert.impl.URLConverter; import cn.hutool.core.convert.impl.UUIDConverter; import cn.hutool.core.date.DateTime; +import cn.hutool.core.lang.Opt; import cn.hutool.core.lang.TypeReference; import cn.hutool.core.util.ClassUtil; import cn.hutool.core.util.ObjectUtil; @@ -444,6 +446,7 @@ public class ConverterRegistry implements Serializable { defaultConverterMap.put(UUID.class, new UUIDConverter());// since 4.0.10 defaultConverterMap.put(StackTraceElement.class, new StackTraceElementConverter());// since 4.5.2 defaultConverterMap.put(Optional.class, new OptionalConverter());// since 5.0.0 + defaultConverterMap.put(Opt.class, new OptConverter());// since 5.7.16 return this; } diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/OptConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/OptConverter.java new file mode 100644 index 000000000..cf79c179e --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/OptConverter.java @@ -0,0 +1,21 @@ +package cn.hutool.core.convert.impl; + +import cn.hutool.core.convert.AbstractConverter; +import cn.hutool.core.lang.Opt; + +/** + * + * {@link Opt}对象转换器 + * + * @author Looly + * @since 5.7.16 + */ +public class OptConverter extends AbstractConverter> { + private static final long serialVersionUID = 1L; + + @Override + protected Opt convertInternal(Object value) { + return Opt.ofNullable(value); + } + +} diff --git a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java index 4ba6d7a9b..37c935d04 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java @@ -2059,6 +2059,32 @@ public class DateUtil extends CalendarUtil { return format; } + /** + * 获取时长单位简写 + * + * @param unit 单位 + * @return 单位简写名称 + * @since 5.7.16 + */ + public static String getShotName(TimeUnit unit) { + switch (unit) { + case NANOSECONDS: + return "ns"; + case MICROSECONDS: + return "μs"; + case MILLISECONDS: + return "ms"; + case SECONDS: + return "s"; + case MINUTES: + return "min"; + case HOURS: + return "h"; + default: + return unit.name().toLowerCase(); + } + } + // ------------------------------------------------------------------------ Private method start /** diff --git a/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java b/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java index 7bf6b3401..7338644ed 100755 --- a/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/StopWatch.java @@ -6,6 +6,7 @@ import cn.hutool.core.util.StrUtil; import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; /** * 秒表封装
@@ -48,7 +49,7 @@ public class StopWatch { * @return StopWatch * @since 5.5.2 */ - public static StopWatch create(String id){ + public static StopWatch create(String id) { return new StopWatch(id); } @@ -251,6 +252,17 @@ public class StopWatch { return this.lastTaskInfo; } + /** + * 获取所有任务的总花费时间 + * + * @param unit 时间单位,{@code null}表示默认{@link TimeUnit#NANOSECONDS} + * @return 花费时间 + * @since 5.7.16 + */ + public long getTotal(TimeUnit unit){ + return unit.convert(this.totalTimeNanos, TimeUnit.NANOSECONDS); + } + /** * 获取所有任务的总花费时间(纳秒) * @@ -270,7 +282,7 @@ public class StopWatch { * @see #getTotalTimeSeconds() */ public long getTotalTimeMillis() { - return DateUtil.nanosToMillis(this.totalTimeNanos); + return getTotal(TimeUnit.MILLISECONDS); } /** @@ -306,27 +318,61 @@ public class StopWatch { } /** - * 获取任务信息 + * 获取任务信息,类似于: + *
+	 *     StopWatch '[id]': running time = [total] ns
+	 * 
* * @return 任务信息 */ public String shortSummary() { - return StrUtil.format("StopWatch '{}': running time = {} ns", this.id, this.totalTimeNanos); + return shortSummary(null); + } + + /** + * 获取任务信息,类似于: + *
+	 *     StopWatch '[id]': running time = [total] [unit]
+	 * 
+ * + * @return 任务信息 + */ + public String shortSummary(TimeUnit unit) { + if(null == unit){ + unit = TimeUnit.NANOSECONDS; + } + return StrUtil.format("StopWatch '{}': running time = {} {}", + this.id, getTotal(unit), DateUtil.getShotName(unit)); + } + + /** + * 生成所有任务的一个任务花费时间表,单位纳秒 + * + * @return 任务时间表 + */ + public String prettyPrint() { + return prettyPrint(null); } /** * 生成所有任务的一个任务花费时间表 * + * @param unit 时间单位,{@code null}则默认{@link TimeUnit#NANOSECONDS} 纳秒 * @return 任务时间表 + * @since 5.7.16 */ - public String prettyPrint() { - StringBuilder sb = new StringBuilder(shortSummary()); + public String prettyPrint(TimeUnit unit) { + if (null == unit) { + unit = TimeUnit.NANOSECONDS; + } + + final StringBuilder sb = new StringBuilder(shortSummary(unit)); sb.append(FileUtil.getLineSeparator()); if (null == this.taskList) { sb.append("No task info kept"); } else { sb.append("---------------------------------------------").append(FileUtil.getLineSeparator()); - sb.append("ns % Task name").append(FileUtil.getLineSeparator()); + sb.append(DateUtil.getShotName(unit)).append(" % Task name").append(FileUtil.getLineSeparator()); sb.append("---------------------------------------------").append(FileUtil.getLineSeparator()); final NumberFormat nf = NumberFormat.getNumberInstance(); @@ -334,11 +380,12 @@ public class StopWatch { nf.setGroupingUsed(false); final NumberFormat pf = NumberFormat.getPercentInstance(); - pf.setMinimumIntegerDigits(3); + pf.setMinimumIntegerDigits(2); pf.setGroupingUsed(false); + for (TaskInfo task : getTaskInfo()) { - sb.append(nf.format(task.getTimeNanos())).append(" "); - sb.append(pf.format((double) task.getTimeNanos() / getTotalTimeNanos())).append(" "); + sb.append(nf.format(task.getTime(unit))).append(" "); + sb.append(pf.format((double) task.getTimeNanos() / getTotalTimeNanos())).append(" "); sb.append(task.getTaskName()).append(FileUtil.getLineSeparator()); } } @@ -370,6 +417,12 @@ public class StopWatch { private final String taskName; private final long timeNanos; + /** + * 构造 + * + * @param taskName 任务名称 + * @param timeNanos 花费时间(纳秒) + */ TaskInfo(String taskName, long timeNanos) { this.taskName = taskName; this.timeNanos = timeNanos; @@ -384,6 +437,17 @@ public class StopWatch { return this.taskName; } + /** + * 获取指定单位的任务花费时间 + * + * @param unit 单位 + * @return 任务花费时间 + * @since 5.7.16 + */ + public long getTime(TimeUnit unit) { + return unit.convert(this.timeNanos, TimeUnit.NANOSECONDS); + } + /** * 获取任务花费时间(单位:纳秒) * @@ -403,7 +467,7 @@ public class StopWatch { * @see #getTimeSeconds() */ public long getTimeMillis() { - return DateUtil.nanosToMillis(this.timeNanos); + return getTime(TimeUnit.MILLISECONDS); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/date/TemporalUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/TemporalUtil.java index 28878b69a..d003f4971 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/TemporalUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/TemporalUtil.java @@ -3,6 +3,7 @@ package cn.hutool.core.date; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.time.temporal.Temporal; +import java.util.concurrent.TimeUnit; /** * {@link Temporal} 工具类封装 @@ -38,4 +39,67 @@ public class TemporalUtil { public static long between(Temporal startTimeInclude, Temporal endTimeExclude, ChronoUnit unit) { return unit.between(startTimeInclude, endTimeExclude); } + + /** + * 将 {@link TimeUnit} 转换为 {@link ChronoUnit}. + * + * @param unit 被转换的{@link TimeUnit}单位,如果为{@code null}返回{@code null} + * @return {@link ChronoUnit} + * @since 5.7.16 + */ + public static ChronoUnit toChronoUnit(TimeUnit unit) throws IllegalArgumentException { + if (null == unit) { + return null; + } + switch (unit) { + case NANOSECONDS: + return ChronoUnit.NANOS; + case MICROSECONDS: + return ChronoUnit.MICROS; + case MILLISECONDS: + return ChronoUnit.MILLIS; + case SECONDS: + return ChronoUnit.SECONDS; + case MINUTES: + return ChronoUnit.MINUTES; + case HOURS: + return ChronoUnit.HOURS; + case DAYS: + return ChronoUnit.DAYS; + default: + throw new IllegalArgumentException("Unknown TimeUnit constant"); + } + } + + /** + * 转换 {@link ChronoUnit} 到 {@link TimeUnit}. + * + * @param unit {@link ChronoUnit},如果为{@code null}返回{@code null} + * @return {@link TimeUnit} + * @throws IllegalArgumentException 如果{@link TimeUnit}没有对应单位抛出 + * @since 5.7.16 + */ + public static TimeUnit toTimeUnit(ChronoUnit unit) throws IllegalArgumentException { + if (null == unit) { + return null; + } + switch (unit) { + case NANOS: + return TimeUnit.NANOSECONDS; + case MICROS: + return TimeUnit.MICROSECONDS; + case MILLIS: + return TimeUnit.MILLISECONDS; + case SECONDS: + return TimeUnit.SECONDS; + case MINUTES: + return TimeUnit.MINUTES; + case HOURS: + return TimeUnit.HOURS; + case DAYS: + return TimeUnit.DAYS; + default: + throw new IllegalArgumentException("ChronoUnit cannot be converted to TimeUnit: " + unit); + } + } }