From 4b5d556f3286ab8e450c5edd773032556dda2b77 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 10 Oct 2024 17:15:54 +0800 Subject: [PATCH] add DatePattern --- .../org/dromara/hutool/core/data/CIN.java | 4 +- .../{DatePattern.java => DateFormatPool.java} | 4 +- .../dromara/hutool/core/date/DateTime.java | 26 +- .../dromara/hutool/core/date/DateUtil.java | 22 +- .../dromara/hutool/core/date/TimeUtil.java | 14 +- .../hutool/core/date/format/DateBasic.java | 1 - .../hutool/core/date/format/DatePattern.java | 1120 ++++++++++++++++ .../hutool/core/date/format/DatePrinter.java | 14 +- .../core/date/format/FastDateFormat.java | 5 +- .../core/date/format/FastDatePrinter.java | 1129 +---------------- .../date/format/parser/FastDateParser.java | 26 +- .../core/date/format/parser/TimeParser.java | 6 +- .../hutool/core/date/CalendarUtilTest.java | 2 +- .../hutool/core/date/DateModifierTest.java | 56 +- .../hutool/core/date/DateTimeTest.java | 28 +- .../hutool/core/date/DateUtilTest.java | 76 +- .../core/date/TemporalAccessorUtilTest.java | 12 +- .../hutool/core/date/TimeUtilTest.java | 14 +- .../hutool/core/date/TimeZoneTest.java | 2 +- .../core/text/CharSequenceUtilTest.java | 10 +- .../dromara/hutool/json/JSONObjectTest.java | 6 +- .../org/dromara/hutool/json/jwt/JWTTest.java | 4 +- 22 files changed, 1299 insertions(+), 1282 deletions(-) rename hutool-core/src/main/java/org/dromara/hutool/core/date/{DatePattern.java => DateFormatPool.java} (99%) create mode 100644 hutool-core/src/main/java/org/dromara/hutool/core/date/format/DatePattern.java diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/data/CIN.java b/hutool-core/src/main/java/org/dromara/hutool/core/data/CIN.java index e68ffabcc..772351c4e 100755 --- a/hutool-core/src/main/java/org/dromara/hutool/core/data/CIN.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/data/CIN.java @@ -16,7 +16,7 @@ package org.dromara.hutool.core.data; -import org.dromara.hutool.core.date.DatePattern; +import org.dromara.hutool.core.date.DateFormatPool; import org.dromara.hutool.core.date.DateTime; import org.dromara.hutool.core.date.DateUtil; import org.dromara.hutool.core.lang.Assert; @@ -188,7 +188,7 @@ public class CIN { */ public DateTime getBirthDate() { final String birth = getBirth(); - return DateUtil.parse(birth, DatePattern.PURE_DATE_FORMAT); + return DateUtil.parse(birth, DateFormatPool.PURE_DATE_FORMAT); } /** diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/date/DatePattern.java b/hutool-core/src/main/java/org/dromara/hutool/core/date/DateFormatPool.java similarity index 99% rename from hutool-core/src/main/java/org/dromara/hutool/core/date/DatePattern.java rename to hutool-core/src/main/java/org/dromara/hutool/core/date/DateFormatPool.java index 7f6e6c3bc..1a7cbd75a 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/date/DatePattern.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/date/DateFormatPool.java @@ -81,7 +81,7 @@ import java.util.TimeZone; * * @author Looly */ -public class DatePattern { +public class DateFormatPool { // region Normal //================================================== Normal ================================================== @@ -275,7 +275,7 @@ public class DatePattern { * jdk8 bug at: https://bugs.openjdk.java.net/browse/JDK-8031085 */ public static final DateTimeFormatter PURE_DATETIME_MS_FORMATTER = new DateTimeFormatterBuilder() - .appendPattern(DatePattern.PURE_DATETIME_PATTERN) + .appendPattern(DateFormatPool.PURE_DATETIME_PATTERN) .appendValue(ChronoField.MILLI_OF_SECOND, 3) .toFormatter(); // endregion diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/date/DateTime.java b/hutool-core/src/main/java/org/dromara/hutool/core/date/DateTime.java index e3bf3b777..0f936c147 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/date/DateTime.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/date/DateTime.java @@ -127,7 +127,7 @@ public class DateTime extends Date { * @param dateStr Date字符串 * @param format 格式 * @return this - * @see DatePattern + * @see DateFormatPool */ public static DateTime of(final String dateStr, final String format) { return new DateTime(dateStr, format); @@ -294,7 +294,7 @@ public class DateTime extends Date { * * @param dateStr Date字符串 * @param format 格式 - * @see DatePattern + * @see DateFormatPool */ public DateTime(final CharSequence dateStr, final String format) { this(GlobalCustomFormat.isCustomFormat(format) @@ -307,7 +307,7 @@ public class DateTime extends Date { * * @param dateStr Date字符串 * @param dateFormat 格式化器 {@link SimpleDateFormat} - * @see DatePattern + * @see DateFormatPool */ public DateTime(final CharSequence dateStr, final DateFormat dateFormat) { this(parse(dateStr, dateFormat), dateFormat.getTimeZone()); @@ -329,7 +329,7 @@ public class DateTime extends Date { * * @param dateStr Date字符串 * @param dateParser 格式化器 {@link DateParser},可以使用 {@link FastDateFormat} - * @see DatePattern + * @see DateFormatPool */ public DateTime(final CharSequence dateStr, final PositionDateParser dateParser) { this(dateStr, dateParser, SystemUtil.getBoolean(SystemUtil.HUTOOL_DATE_LENIENT, true)); @@ -341,7 +341,7 @@ public class DateTime extends Date { * @param dateStr Date字符串 * @param dateParser 格式化器 {@link DateParser},可以使用 {@link FastDateFormat} * @param lenient 是否宽容模式 - * @see DatePattern + * @see DateFormatPool */ public DateTime(final CharSequence dateStr, final PositionDateParser dateParser, final boolean lenient) { this(parse(dateStr, dateParser, lenient)); @@ -1004,9 +1004,9 @@ public class DateTime extends Date { */ public String toString(final TimeZone timeZone) { if (null != timeZone) { - return toString(DateUtil.newSimpleFormat(DatePattern.NORM_DATETIME_PATTERN, null, timeZone)); + return toString(DateUtil.newSimpleFormat(DateFormatPool.NORM_DATETIME_PATTERN, null, timeZone)); } - return toString(DatePattern.NORM_DATETIME_FORMAT); + return toString(DateFormatPool.NORM_DATETIME_FORMAT); } /** @@ -1017,9 +1017,9 @@ public class DateTime extends Date { */ public String toDateStr() { if (null != this.timeZone) { - return toString(DateUtil.newSimpleFormat(DatePattern.NORM_DATE_PATTERN, null, timeZone)); + return toString(DateUtil.newSimpleFormat(DateFormatPool.NORM_DATE_PATTERN, null, timeZone)); } - return toString(DatePattern.NORM_DATE_FORMAT); + return toString(DateFormatPool.NORM_DATE_FORMAT); } /** @@ -1030,15 +1030,15 @@ public class DateTime extends Date { */ public String toTimeStr() { if (null != this.timeZone) { - return toString(DateUtil.newSimpleFormat(DatePattern.NORM_TIME_PATTERN, null, timeZone)); + return toString(DateUtil.newSimpleFormat(DateFormatPool.NORM_TIME_PATTERN, null, timeZone)); } - return toString(DatePattern.NORM_TIME_FORMAT); + return toString(DateFormatPool.NORM_TIME_FORMAT); } /** * 转为字符串 * - * @param format 日期格式,常用格式见: {@link DatePattern} + * @param format 日期格式,常用格式见: {@link DateFormatPool} * @return String */ public String toString(final String format) { @@ -1072,7 +1072,7 @@ public class DateTime extends Date { * @return 输出精确到毫秒的标准日期形式 */ public String toMsStr() { - return toString(DatePattern.NORM_DATETIME_MS_FORMAT); + return toString(DateFormatPool.NORM_DATETIME_MS_FORMAT); } // -------------------------------------------------------------------- toString end diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/date/DateUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/date/DateUtil.java index 53b94efd0..15c4b3454 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/date/DateUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/date/DateUtil.java @@ -46,7 +46,7 @@ import java.util.stream.Collectors; * * @author Looly * @see TimeUtil java8日志工具类 - * @see DatePattern 日期常用格式工具类 + * @see DateFormatPool 日期常用格式工具类 */ public class DateUtil { @@ -526,7 +526,7 @@ public class DateUtil { * 根据特定格式格式化日期 * * @param localDateTime 被格式化的日期 - * @param format 日期格式,常用格式见: {@link DatePattern} + * @param format 日期格式,常用格式见: {@link DateFormatPool} * @return 格式化后的字符串 */ public static String format(final LocalDateTime localDateTime, final String format) { @@ -537,7 +537,7 @@ public class DateUtil { * 根据特定格式格式化日期 * * @param date 被格式化的日期 - * @param format 日期格式,常用格式见: {@link DatePattern} {@link DatePattern#NORM_DATETIME_PATTERN} + * @param format 日期格式,常用格式见: {@link DateFormatPool} {@link DateFormatPool#NORM_DATETIME_PATTERN} * @return 格式化后的字符串 */ public static String format(final Date date, final String format) { @@ -561,7 +561,7 @@ public class DateUtil { * 根据特定格式格式化日期 * * @param date 被格式化的日期 - * @param format {@link DatePrinter} 或 {@link FastDateFormat} {@link DatePattern#NORM_DATETIME_FORMAT} + * @param format {@link DatePrinter} 或 {@link FastDateFormat} {@link DateFormatPool#NORM_DATETIME_FORMAT} * @return 格式化后的字符串 */ public static String format(final Date date, final DatePrinter format) { @@ -589,7 +589,7 @@ public class DateUtil { * 根据特定格式格式化日期 * * @param date 被格式化的日期 - * @param format {@link SimpleDateFormat} {@link DatePattern#NORM_DATETIME_FORMATTER} + * @param format {@link SimpleDateFormat} {@link DateFormatPool#NORM_DATETIME_FORMATTER} * @return 格式化后的字符串 * @since 5.0.0 */ @@ -613,7 +613,7 @@ public class DateUtil { if (null == date) { return null; } - return DatePattern.NORM_DATETIME_FORMAT.format(date); + return DateFormatPool.NORM_DATETIME_FORMAT.format(date); } /** @@ -627,7 +627,7 @@ public class DateUtil { if (null == date) { return null; } - return DatePattern.NORM_DATE_FORMAT.format(date); + return DateFormatPool.NORM_DATE_FORMAT.format(date); } /** @@ -642,7 +642,7 @@ public class DateUtil { if (null == date) { return null; } - return DatePattern.NORM_TIME_FORMAT.format(date); + return DateFormatPool.NORM_TIME_FORMAT.format(date); } /** @@ -656,7 +656,7 @@ public class DateUtil { if (null == date) { return null; } - return DatePattern.HTTP_DATETIME_FORMAT_GMT.format(date); + return DateFormatPool.HTTP_DATETIME_FORMAT_GMT.format(date); } /** @@ -674,7 +674,7 @@ public class DateUtil { } if (!isUppercase) { - return (withTime ? DatePattern.CHINESE_DATE_TIME_FORMAT : DatePattern.CHINESE_DATE_FORMAT).format(date); + return (withTime ? DateFormatPool.CHINESE_DATE_TIME_FORMAT : DateFormatPool.CHINESE_DATE_FORMAT).format(date); } return CalendarUtil.formatChineseDate(CalendarUtil.calendar(date), withTime); @@ -1814,7 +1814,7 @@ public class DateUtil { * * @param date1 日期1 * @param date2 日期2 - * @param format 日期格式,常用格式见: {@link DatePattern}; 允许为空; date1 date2; eg: yyyy-MM-dd + * @param format 日期格式,常用格式见: {@link DateFormatPool}; 允许为空; date1 date2; eg: yyyy-MM-dd * @return 比较结果,如果date1 < date2,返回数小于0,date1==date2返回0,date1 > date2 大于0 * @author dazer * @since 5.6.4 diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/date/TimeUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/date/TimeUtil.java index bbd5c2c27..6699ec9a4 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/date/TimeUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/date/TimeUtil.java @@ -40,7 +40,7 @@ import java.util.function.Function; * * @author looly * @see DateUtil java7及其以下版本,使用Date工具类 - * @see DatePattern 常用格式工具类 + * @see DateFormatPool 常用格式工具类 * @since 6.0.0 */ public class TimeUtil extends TemporalAccessorUtil { @@ -298,7 +298,7 @@ public class TimeUtil extends TemporalAccessorUtil { if (StrUtil.contains(text, 'T')) { return parse(text, DateTimeFormatter.ISO_LOCAL_DATE_TIME); } else { - return parse(text, DatePattern.NORM_DATETIME_FORMATTER); + return parse(text, DateFormatPool.NORM_DATETIME_FORMATTER); } } @@ -343,14 +343,14 @@ public class TimeUtil extends TemporalAccessorUtil { // fix issue#1082 //see https://stackoverflow.com/questions/22588051/is-java-time-failing-to-parse-fraction-of-second // jdk8 bug at: https://bugs.openjdk.java.net/browse/JDK-8031085 - if (StrUtil.startWithIgnoreEquals(format, DatePattern.PURE_DATETIME_PATTERN) && format.endsWith("S")) { + if (StrUtil.startWithIgnoreEquals(format, DateFormatPool.PURE_DATETIME_PATTERN) && format.endsWith("S")) { // 需要填充的0的个数 - final int paddingWidth = 3 - (format.length() - DatePattern.PURE_DATETIME_PATTERN.length()); + final int paddingWidth = 3 - (format.length() - DateFormatPool.PURE_DATETIME_PATTERN.length()); if (paddingWidth > 0) { //将yyyyMMddHHmmssS、yyyyMMddHHmmssSS的日期统一替换为yyyyMMddHHmmssSSS格式,用0补 text += StrUtil.repeat('0', paddingWidth); } - formatter = DatePattern.PURE_DATETIME_MS_FORMATTER; + formatter = DateFormatPool.PURE_DATETIME_MS_FORMATTER; } else { formatter = DateTimeFormatter.ofPattern(format); } @@ -411,7 +411,7 @@ public class TimeUtil extends TemporalAccessorUtil { * @since 5.3.11 */ public static String formatNormal(final ChronoLocalDateTime time) { - return format(time, DatePattern.NORM_DATETIME_FORMATTER); + return format(time, DateFormatPool.NORM_DATETIME_FORMATTER); } /** @@ -422,7 +422,7 @@ public class TimeUtil extends TemporalAccessorUtil { * @since 5.3.11 */ public static String formatNormal(final ChronoLocalDate date) { - return format(date, DatePattern.NORM_DATE_FORMATTER); + return format(date, DateFormatPool.NORM_DATE_FORMATTER); } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/date/format/DateBasic.java b/hutool-core/src/main/java/org/dromara/hutool/core/date/format/DateBasic.java index c4f133742..c971c368e 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/date/format/DateBasic.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/date/format/DateBasic.java @@ -23,7 +23,6 @@ import java.util.TimeZone; * 日期基本信息获取接口 * * @author Looly - * @since 2.16.2 */ public interface DateBasic { diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/date/format/DatePattern.java b/hutool-core/src/main/java/org/dromara/hutool/core/date/format/DatePattern.java new file mode 100644 index 000000000..e8363813e --- /dev/null +++ b/hutool-core/src/main/java/org/dromara/hutool/core/date/format/DatePattern.java @@ -0,0 +1,1120 @@ +/* + * Copyright (c) 2024 Hutool Team and hutool.cn + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.hutool.core.date.format; + +import org.dromara.hutool.core.date.DateException; +import org.dromara.hutool.core.map.concurrent.SafeConcurrentHashMap; + +import java.io.IOException; +import java.text.DateFormatSymbols; +import java.util.*; +import java.util.concurrent.ConcurrentMap; + +/** + * 日期格式表达式,用于解析和格式化日期时间。 + * + * @author Looly + * @since 6.0.0 + */ +public class DatePattern { + + private static final int MAX_DIGITS = 10; // log10(Integer.MAX_VALUE) ~= 9.3 + + /** + * 规则列表. + */ + private final Rule[] rules; + /** + * 估算长度 + */ + private int estimateLength; + + /** + * 获取估算日期长度 + * + * @return 日期格式表达式长度 + */ + public int getEstimateLength() { + return this.estimateLength; + } + + /** + * 构造 + * + * @param patternStr 日期表达式字符串 + * @param locale 地域信息 + * @param timeZone 时区 + */ + public DatePattern(final String patternStr, final Locale locale, final TimeZone timeZone) { + this.rules = parsePattern(patternStr, locale, timeZone).toArray(new Rule[0]); + } + + /** + * 根据指定格式,格式化日期时间 + * + * @param calendar {@link Calendar} + * @param buf 格式化后写出的{@link Appendable} + * @param {@link Appendable}实现类, 一般为 StringBuilder 或 StringBuffer. + * @return 定义的Appendable + */ + public B applyRules(final Calendar calendar, final B buf) { + try { + for (final Rule rule : this.rules) { + rule.appendTo(buf, calendar); + } + } catch (final IOException e) { + throw new DateException(e); + } + return buf; + } + + /** + *

+ * Returns a list of Rules given a pattern. + *

+ * + * @return a {@code List} of Rule objects + * @throws IllegalArgumentException if pattern is invalid + */ + private List parsePattern(final String patternStr, final Locale locale, final TimeZone timeZone) { + final DateFormatSymbols symbols = new DateFormatSymbols(locale); + final List rules = new ArrayList<>(); + + final String[] ERAs = symbols.getEras(); + final String[] months = symbols.getMonths(); + final String[] shortMonths = symbols.getShortMonths(); + final String[] weekdays = symbols.getWeekdays(); + final String[] shortWeekdays = symbols.getShortWeekdays(); + final String[] AmPmStrings = symbols.getAmPmStrings(); + + final int length = patternStr.length(); + final int[] indexRef = new int[1]; + + for (int i = 0; i < length; i++) { + indexRef[0] = i; + final String token = parseToken(patternStr, indexRef); + i = indexRef[0]; + + final int tokenLen = token.length(); + if (tokenLen == 0) { + break; + } + + Rule rule; + final char c = token.charAt(0); + + switch (c) { + case 'G': // era designator (text) + rule = new TextField(Calendar.ERA, ERAs); + break; + case 'y': // year (number) + case 'Y': // week year + if (tokenLen == 2) { + rule = TwoDigitYearField.INSTANCE; + } else { + rule = selectNumberRule(Calendar.YEAR, Math.max(tokenLen, 4)); + } + if (c == 'Y') { + rule = new WeekYear((NumberRule) rule); + } + break; + case 'M': // month in year (text and number) + if (tokenLen >= 4) { + rule = new TextField(Calendar.MONTH, months); + } else if (tokenLen == 3) { + rule = new TextField(Calendar.MONTH, shortMonths); + } else if (tokenLen == 2) { + rule = TwoDigitMonthField.INSTANCE; + } else { + rule = UnpaddedMonthField.INSTANCE; + } + break; + case 'd': // day in month (number) + rule = selectNumberRule(Calendar.DAY_OF_MONTH, tokenLen); + break; + case 'h': // hour in am/pm (number, 1..12) + rule = new TwelveHourField(selectNumberRule(Calendar.HOUR, tokenLen)); + break; + case 'H': // hour in day (number, 0..23) + rule = selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen); + break; + case 'm': // minute in hour (number) + rule = selectNumberRule(Calendar.MINUTE, tokenLen); + break; + case 's': // second in minute (number) + rule = selectNumberRule(Calendar.SECOND, tokenLen); + break; + case 'S': // millisecond (number) + rule = selectNumberRule(Calendar.MILLISECOND, tokenLen); + break; + case 'E': // day in week (text) + rule = new TextField(Calendar.DAY_OF_WEEK, tokenLen < 4 ? shortWeekdays : weekdays); + break; + case 'u': // day in week (number) + rule = new DayInWeekField(selectNumberRule(Calendar.DAY_OF_WEEK, tokenLen)); + break; + case 'D': // day in year (number) + rule = selectNumberRule(Calendar.DAY_OF_YEAR, tokenLen); + break; + case 'F': // day of week in month (number) + rule = selectNumberRule(Calendar.DAY_OF_WEEK_IN_MONTH, tokenLen); + break; + case 'w': // week in year (number) + rule = selectNumberRule(Calendar.WEEK_OF_YEAR, tokenLen); + break; + case 'W': // week in month (number) + rule = selectNumberRule(Calendar.WEEK_OF_MONTH, tokenLen); + break; + case 'a': // am/pm marker (text) + rule = new TextField(Calendar.AM_PM, AmPmStrings); + break; + case 'k': // hour in day (1..24) + rule = new TwentyFourHourField(selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen)); + break; + case 'K': // hour in am/pm (0..11) + rule = selectNumberRule(Calendar.HOUR, tokenLen); + break; + case 'X': // ISO 8601 + rule = Iso8601_Rule.getRule(tokenLen); + break; + case 'z': // time zone (text) + if (tokenLen >= 4) { + rule = new TimeZoneNameRule(timeZone, locale, TimeZone.LONG); + } else { + rule = new TimeZoneNameRule(timeZone, locale, TimeZone.SHORT); + } + break; + case 'Z': // time zone (value) + if (tokenLen == 1) { + rule = TimeZoneNumberRule.INSTANCE_NO_COLON; + } else if (tokenLen == 2) { + rule = Iso8601_Rule.ISO8601_HOURS_COLON_MINUTES; + } else { + rule = TimeZoneNumberRule.INSTANCE_COLON; + } + break; + case '\'': // literal text + final String sub = token.substring(1); + if (sub.length() == 1) { + rule = new CharacterLiteral(sub.charAt(0)); + } else { + rule = new StringLiteral(sub); + } + break; + default: + throw new IllegalArgumentException("Illegal pattern component: " + token); + } + + this.estimateLength += rule.estimateLength(); + rules.add(rule); + } + + return rules; + } + + /** + *

+ * Performs the parsing of tokens. + *

+ * + * @param pattern the pattern + * @param indexRef index references + * @return parsed token + */ + protected static String parseToken(final String pattern, final int[] indexRef) { + final StringBuilder buf = new StringBuilder(); + + int i = indexRef[0]; + final int length = pattern.length(); + + char c = pattern.charAt(i); + if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') { + // Scan a run of the same character, which indicates a time + // pattern. + buf.append(c); + + while (i + 1 < length) { + final char peek = pattern.charAt(i + 1); + if (peek == c) { + buf.append(c); + i++; + } else { + break; + } + } + } else { + // This will identify token as text. + buf.append('\''); + + boolean inLiteral = false; + + for (; i < length; i++) { + c = pattern.charAt(i); + + if (c == '\'') { + if (i + 1 < length && pattern.charAt(i + 1) == '\'') { + // '' is treated as escaped ' + i++; + buf.append(c); + } else { + inLiteral = !inLiteral; + } + } else if (!inLiteral && (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')) { + i--; + break; + } else { + buf.append(c); + } + } + } + + indexRef[0] = i; + return buf.toString(); + } + + /** + *

+ * Gets an appropriate rule for the padding required. + *

+ * + * @param field the field to get a rule for + * @param padding the padding required + * @return a new rule with the correct padding + */ + protected static NumberRule selectNumberRule(final int field, final int padding) { + switch (padding) { + case 1: + return new UnpaddedNumberField(field); + case 2: + return new TwoDigitNumberField(field); + default: + return new PaddedNumberField(field, padding); + } + } + + // Rules + // ----------------------------------------------------------------------- + + /** + * 规则 + */ + public interface Rule { + /** + * Returns the estimated length of the result. + * + * @return the estimated length + */ + int estimateLength(); + + /** + * Appends the value of the specified calendar to the output buffer based on the rule implementation. + * + * @param buf the output buffer + * @param calendar calendar to be appended + * @throws IOException if an I/O error occurs + */ + void appendTo(Appendable buf, Calendar calendar) throws IOException; + } + + /** + *

+ * Inner class defining a numeric rule. + *

+ */ + public interface NumberRule extends Rule { + /** + * Appends the specified value to the output buffer based on the rule implementation. + * + * @param buffer the output buffer + * @param value the value to be appended + * @throws IOException if an I/O error occurs + */ + void appendTo(Appendable buffer, int value) throws IOException; + } + + /** + *

+ * Inner class to output a constant single character. + *

+ */ + private static class CharacterLiteral implements Rule { + private final char mValue; + + /** + * Constructs a new instance of {@code CharacterLiteral} to hold the specified value. + * + * @param value the character literal + */ + CharacterLiteral(final char value) { + mValue = value; + } + + @Override + public int estimateLength() { + return 1; + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + buffer.append(mValue); + } + } + + /** + *

+ * Inner class to output a constant string. + *

+ */ + private static class StringLiteral implements Rule { + private final String mValue; + + /** + * Constructs a new instance of {@code StringLiteral} to hold the specified value. + * + * @param value the string literal + */ + StringLiteral(final String value) { + mValue = value; + } + + @Override + public int estimateLength() { + return mValue.length(); + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + buffer.append(mValue); + } + } + + /** + *

+ * Inner class to output one of a set of values. + *

+ */ + private static class TextField implements Rule { + private final int mField; + private final String[] mValues; + + /** + * Constructs an instance of {@code TextField} with the specified field and values. + * + * @param field the field + * @param values the field values + */ + TextField(final int field, final String[] values) { + mField = field; + mValues = values; + } + + @Override + public int estimateLength() { + int max = 0; + for (int i = mValues.length; --i >= 0; ) { + final int len = mValues[i].length(); + if (len > max) { + max = len; + } + } + return max; + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + buffer.append(mValues[calendar.get(mField)]); + } + } + + /** + *

+ * Inner class to output an unpadded number. + *

+ */ + private static class UnpaddedNumberField implements NumberRule { + private final int mField; + + /** + * Constructs an instance of {@code UnpadedNumberField} with the specified field. + * + * @param field the field + */ + UnpaddedNumberField(final int field) { + mField = field; + } + + @Override + public int estimateLength() { + return 4; + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + appendTo(buffer, calendar.get(mField)); + } + + @Override + public final void appendTo(final Appendable buffer, final int value) throws IOException { + if (value < 10) { + buffer.append((char) (value + '0')); + } else if (value < 100) { + appendDigits(buffer, value); + } else { + appendFullDigits(buffer, value, 1); + } + } + } + + /** + *

+ * Inner class to output an unpadded month. + *

+ */ + private static class UnpaddedMonthField implements NumberRule { + static final UnpaddedMonthField INSTANCE = new UnpaddedMonthField(); + + /** + * Constructs an instance of {@code UnpaddedMonthField}. + */ + UnpaddedMonthField() { + } + + @Override + public int estimateLength() { + return 2; + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + appendTo(buffer, calendar.get(Calendar.MONTH) + 1); + } + + @Override + public final void appendTo(final Appendable buffer, final int value) throws IOException { + if (value < 10) { + buffer.append((char) (value + '0')); + } else { + appendDigits(buffer, value); + } + } + } + + /** + *

+ * Inner class to output a padded number. + *

+ */ + private static class PaddedNumberField implements NumberRule { + private final int mField; + private final int mSize; + + /** + * Constructs an instance of {@code PaddedNumberField}. + * + * @param field the field + * @param size size of the output field + */ + PaddedNumberField(final int field, final int size) { + if (size < 3) { + // Should use UnpaddedNumberField or TwoDigitNumberField. + throw new IllegalArgumentException(); + } + mField = field; + mSize = size; + } + + @Override + public int estimateLength() { + return mSize; + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + appendTo(buffer, calendar.get(mField)); + } + + @Override + public final void appendTo(final Appendable buffer, final int value) throws IOException { + appendFullDigits(buffer, value, mSize); + } + } + + /** + *

+ * Inner class to output a two digit number. + *

+ */ + private static class TwoDigitNumberField implements NumberRule { + private final int mField; + + /** + * Constructs an instance of {@code TwoDigitNumberField} with the specified field. + * + * @param field the field + */ + TwoDigitNumberField(final int field) { + mField = field; + } + + @Override + public int estimateLength() { + return 2; + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + appendTo(buffer, calendar.get(mField)); + } + + @Override + public final void appendTo(final Appendable buffer, final int value) throws IOException { + if (value < 100) { + appendDigits(buffer, value); + } else { + appendFullDigits(buffer, value, 2); + } + } + } + + /** + *

+ * Inner class to output a two digit year. + *

+ */ + private static class TwoDigitYearField implements NumberRule { + static final TwoDigitYearField INSTANCE = new TwoDigitYearField(); + + /** + * Constructs an instance of {@code TwoDigitYearField}. + */ + TwoDigitYearField() { + } + + @Override + public int estimateLength() { + return 2; + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + appendTo(buffer, calendar.get(Calendar.YEAR) % 100); + } + + @Override + public final void appendTo(final Appendable buffer, final int value) throws IOException { + appendDigits(buffer, value); + } + } + + /** + *

+ * Inner class to output a two digit month. + *

+ */ + private static class TwoDigitMonthField implements NumberRule { + static final TwoDigitMonthField INSTANCE = new TwoDigitMonthField(); + + /** + * Constructs an instance of {@code TwoDigitMonthField}. + */ + TwoDigitMonthField() { + } + + @Override + public int estimateLength() { + return 2; + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + appendTo(buffer, calendar.get(Calendar.MONTH) + 1); + } + + @Override + public final void appendTo(final Appendable buffer, final int value) throws IOException { + appendDigits(buffer, value); + } + } + + /** + *

+ * Inner class to output the twelve hour field. + *

+ */ + private static class TwelveHourField implements NumberRule { + private final NumberRule mRule; + + /** + * Constructs an instance of {@code TwelveHourField} with the specified {@code NumberRule}. + * + * @param rule the rule + */ + TwelveHourField(final NumberRule rule) { + mRule = rule; + } + + @Override + public int estimateLength() { + return mRule.estimateLength(); + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + int value = calendar.get(Calendar.HOUR); + if (value == 0) { + value = calendar.getLeastMaximum(Calendar.HOUR) + 1; + } + mRule.appendTo(buffer, value); + } + + @Override + public void appendTo(final Appendable buffer, final int value) throws IOException { + mRule.appendTo(buffer, value); + } + } + + /** + *

+ * Inner class to output the twenty four hour field. + *

+ */ + private static class TwentyFourHourField implements NumberRule { + private final NumberRule mRule; + + /** + * Constructs an instance of {@code TwentyFourHourField} with the specified {@code NumberRule}. + * + * @param rule the rule + */ + TwentyFourHourField(final NumberRule rule) { + mRule = rule; + } + + @Override + public int estimateLength() { + return mRule.estimateLength(); + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + int value = calendar.get(Calendar.HOUR_OF_DAY); + if (value == 0) { + value = calendar.getMaximum(Calendar.HOUR_OF_DAY) + 1; + } + mRule.appendTo(buffer, value); + } + + @Override + public void appendTo(final Appendable buffer, final int value) throws IOException { + mRule.appendTo(buffer, value); + } + } + + /** + *

+ * Inner class to output the numeric day in week. + *

+ */ + private static class DayInWeekField implements NumberRule { + private final NumberRule mRule; + + DayInWeekField(final NumberRule rule) { + mRule = rule; + } + + @Override + public int estimateLength() { + return mRule.estimateLength(); + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + final int value = calendar.get(Calendar.DAY_OF_WEEK); + mRule.appendTo(buffer, value != Calendar.SUNDAY ? value - 1 : 7); + } + + @Override + public void appendTo(final Appendable buffer, final int value) throws IOException { + mRule.appendTo(buffer, value); + } + } + + /** + *

+ * Inner class to output the numeric day in week. + *

+ */ + private static class WeekYear implements NumberRule { + private final NumberRule mRule; + + WeekYear(final NumberRule rule) { + mRule = rule; + } + + @Override + public int estimateLength() { + return mRule.estimateLength(); + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + int weekYear = calendar.getWeekYear(); + if (mRule instanceof TwoDigitYearField) { + // issue#3641 + weekYear %= 100; + } + mRule.appendTo(buffer, weekYear); + } + + @Override + public void appendTo(final Appendable buffer, final int value) throws IOException { + mRule.appendTo(buffer, value); + } + } + + /** + *

+ * Inner class to output a time zone name. + *

+ */ + private static class TimeZoneNameRule implements Rule { + private final Locale mLocale; + private final int mStyle; + private final String mStandard; + private final String mDaylight; + + /** + * Constructs an instance of {@code TimeZoneNameRule} with the specified properties. + * + * @param timeZone the time zone + * @param locale the locale + * @param style the style + */ + TimeZoneNameRule(final TimeZone timeZone, final Locale locale, final int style) { + mLocale = locale; + mStyle = style; + + mStandard = getTimeZoneDisplay(timeZone, false, style, locale); + mDaylight = getTimeZoneDisplay(timeZone, true, style, locale); + } + + @Override + public int estimateLength() { + // We have no access to the Calendar object that will be passed to + // appendTo so base estimate on the TimeZone passed to the + // constructor + return Math.max(mStandard.length(), mDaylight.length()); + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + final TimeZone zone = calendar.getTimeZone(); + if (calendar.get(Calendar.DST_OFFSET) != 0) { + buffer.append(getTimeZoneDisplay(zone, true, mStyle, mLocale)); + } else { + buffer.append(getTimeZoneDisplay(zone, false, mStyle, mLocale)); + } + } + } + + /** + *

+ * Inner class to output a time zone as a number {@code +/-HHMM} or {@code +/-HH:MM}. + *

+ */ + private static class TimeZoneNumberRule implements Rule { + static final TimeZoneNumberRule INSTANCE_COLON = new TimeZoneNumberRule(true); + static final TimeZoneNumberRule INSTANCE_NO_COLON = new TimeZoneNumberRule(false); + + final boolean mColon; + + /** + * Constructs an instance of {@code TimeZoneNumberRule} with the specified properties. + * + * @param colon add colon between HH and MM in the output if {@code true} + */ + TimeZoneNumberRule(final boolean colon) { + mColon = colon; + } + + @Override + public int estimateLength() { + return 5; + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + + int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET); + + if (offset < 0) { + buffer.append('-'); + offset = -offset; + } else { + buffer.append('+'); + } + + final int hours = offset / (60 * 60 * 1000); + appendDigits(buffer, hours); + + if (mColon) { + buffer.append(':'); + } + + final int minutes = offset / (60 * 1000) - 60 * hours; + appendDigits(buffer, minutes); + } + } + + /** + *

+ * Inner class to output a time zone as a number {@code +/-HHMM} or {@code +/-HH:MM}. + *

+ */ + private static class Iso8601_Rule implements Rule { + + // Sign TwoDigitHours or Z + static final Iso8601_Rule ISO8601_HOURS = new Iso8601_Rule(3); + // Sign TwoDigitHours Minutes or Z + static final Iso8601_Rule ISO8601_HOURS_MINUTES = new Iso8601_Rule(5); + // Sign TwoDigitHours : Minutes or Z + static final Iso8601_Rule ISO8601_HOURS_COLON_MINUTES = new Iso8601_Rule(6); + + /** + * Factory method for Iso8601_Rules. + * + * @param tokenLen a token indicating the length of the TimeZone String to be formatted. + * @return a Iso8601_Rule that can format TimeZone String of length {@code tokenLen}. If no such rule exists, an IllegalArgumentException will be thrown. + */ + static Iso8601_Rule getRule(final int tokenLen) { + switch (tokenLen) { + case 1: + return Iso8601_Rule.ISO8601_HOURS; + case 2: + return Iso8601_Rule.ISO8601_HOURS_MINUTES; + case 3: + return Iso8601_Rule.ISO8601_HOURS_COLON_MINUTES; + default: + throw new IllegalArgumentException("invalid number of X"); + } + } + + final int length; + + /** + * Constructs an instance of {@code Iso8601_Rule} with the specified properties. + * + * @param length The number of characters in output (unless Z is output) + */ + Iso8601_Rule(final int length) { + this.length = length; + } + + @Override + public int estimateLength() { + return length; + } + + @Override + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { + int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET); + if (offset == 0) { + buffer.append("Z"); + return; + } + + if (offset < 0) { + buffer.append('-'); + offset = -offset; + } else { + buffer.append('+'); + } + + final int hours = offset / (60 * 60 * 1000); + appendDigits(buffer, hours); + + if (length < 5) { + return; + } + + if (length == 6) { + buffer.append(':'); + } + + final int minutes = offset / (60 * 1000) - 60 * hours; + appendDigits(buffer, minutes); + } + } + + // ----------------------------------------------------------------------- + + /** + * Appends two digits to the given buffer. + * + * @param buffer the buffer to append to. + * @param value the value to append digits from. + */ + private static void appendDigits(final Appendable buffer, final int value) throws IOException { + buffer.append((char) (value / 10 + '0')); + buffer.append((char) (value % 10 + '0')); + } + + /** + * Appends all digits to the given buffer. + * + * @param buffer the buffer to append to. + * @param value the value to append digits from. + */ + private static void appendFullDigits(final Appendable buffer, int value, int minFieldWidth) throws IOException { + // specialized paths for 1 to 4 digits -> avoid the memory allocation from the temporary work array + // see LANG-1248 + if (value < 10000) { + // less memory allocation path works for four digits or less + + int nDigits = 4; + if (value < 1000) { + --nDigits; + if (value < 100) { + --nDigits; + if (value < 10) { + --nDigits; + } + } + } + // left zero pad + for (int i = minFieldWidth - nDigits; i > 0; --i) { + buffer.append('0'); + } + + switch (nDigits) { + case 4: + buffer.append((char) (value / 1000 + '0')); + value %= 1000; + case 3: + if (value >= 100) { + buffer.append((char) (value / 100 + '0')); + value %= 100; + } else { + buffer.append('0'); + } + case 2: + if (value >= 10) { + buffer.append((char) (value / 10 + '0')); + value %= 10; + } else { + buffer.append('0'); + } + case 1: + buffer.append((char) (value + '0')); + } + } else { + // more memory allocation path works for any digits + + // build up decimal representation in reverse + final char[] work = new char[MAX_DIGITS]; + int digit = 0; + while (value != 0) { + work[digit++] = (char) (value % 10 + '0'); + value = value / 10; + } + + // pad with zeros + while (digit < minFieldWidth) { + buffer.append('0'); + --minFieldWidth; + } + + // reverse + while (--digit >= 0) { + buffer.append(work[digit]); + } + } + } + + private static final ConcurrentMap C_TIME_ZONE_DISPLAY_CACHE = new SafeConcurrentHashMap<>(7); + + /** + *

+ * Gets the time zone display name, using a cache for performance. + *

+ * + * @param tz the zone to query + * @param daylight true if daylight savings + * @param style the style to use {@code TimeZone.LONG} or {@code TimeZone.SHORT} + * @param locale the locale to use + * @return the textual name of the time zone + */ + static String getTimeZoneDisplay(final TimeZone tz, final boolean daylight, final int style, final Locale locale) { + final TimeZoneDisplayKey key = new TimeZoneDisplayKey(tz, daylight, style, locale); + String value = C_TIME_ZONE_DISPLAY_CACHE.get(key); + if (value == null) { + // This is a very slow call, so cache the results. + value = tz.getDisplayName(daylight, style, locale); + final String prior = C_TIME_ZONE_DISPLAY_CACHE.putIfAbsent(key, value); + if (prior != null) { + value = prior; + } + } + return value; + } + + /** + *

+ * Inner class that acts as a compound key for time zone names. + *

+ */ + private static class TimeZoneDisplayKey { + private final TimeZone mTimeZone; + private final int mStyle; + private final Locale mLocale; + + /** + * Constructs an instance of {@code TimeZoneDisplayKey} with the specified properties. + * + * @param timeZone the time zone + * @param daylight adjust the style for daylight saving time if {@code true} + * @param style the timezone style + * @param locale the timezone locale + */ + TimeZoneDisplayKey(final TimeZone timeZone, final boolean daylight, final int style, final Locale locale) { + mTimeZone = timeZone; + if (daylight) { + mStyle = style | 0x80000000; + } else { + mStyle = style; + } + mLocale = locale; + } + + @Override + public int hashCode() { + return (mStyle * 31 + mLocale.hashCode()) * 31 + mTimeZone.hashCode(); + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof TimeZoneDisplayKey) { + final TimeZoneDisplayKey other = (TimeZoneDisplayKey) obj; + return mTimeZone.equals(other.mTimeZone) && mStyle == other.mStyle && mLocale.equals(other.mLocale); + } + return false; + } + } +} diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/date/format/DatePrinter.java b/hutool-core/src/main/java/org/dromara/hutool/core/date/format/DatePrinter.java index 6bcc2bd61..41f5ec0e5 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/date/format/DatePrinter.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/date/format/DatePrinter.java @@ -22,8 +22,8 @@ import java.util.Date; /** * 日期格式化输出接口
* Thanks to Apache Commons Lang 3.5 + * * @author Looly - * @since 2.16.2 */ public interface DatePrinter extends DateBasic { @@ -61,8 +61,8 @@ public interface DatePrinter extends DateBasic { *

* * @param millis the millisecond value to format - * @param buf the buffer to format into - * @param the Appendable class type, usually StringBuilder or StringBuffer. + * @param buf the buffer to format into + * @param the Appendable class type, usually StringBuilder or StringBuffer. * @return the specified string buffer */ B format(long millis, B buf); @@ -73,8 +73,8 @@ public interface DatePrinter extends DateBasic { *

* * @param date the date to format - * @param buf the buffer to format into - * @param the Appendable class type, usually StringBuilder or StringBuffer. + * @param buf the buffer to format into + * @param the Appendable class type, usually StringBuilder or StringBuffer. * @return the specified string buffer */ B format(Date date, B buf); @@ -86,8 +86,8 @@ public interface DatePrinter extends DateBasic { * The TimeZone set on the Calendar is only used to adjust the time offset. The TimeZone specified during the construction of the Parser will determine the TimeZone used in the formatted string. * * @param calendar the calendar to format - * @param buf the buffer to format into - * @param the Appendable class type, usually StringBuilder or StringBuffer. + * @param buf the buffer to format into + * @param the Appendable class type, usually StringBuilder or StringBuffer. * @return the specified string buffer */ B format(Calendar calendar, B buf); diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/date/format/FastDateFormat.java b/hutool-core/src/main/java/org/dromara/hutool/core/date/format/FastDateFormat.java index 91feb8442..0303d7746 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/date/format/FastDateFormat.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/date/format/FastDateFormat.java @@ -17,7 +17,7 @@ package org.dromara.hutool.core.date.format; import org.dromara.hutool.core.date.DateException; -import org.dromara.hutool.core.date.DatePattern; +import org.dromara.hutool.core.date.DateFormatPool; import org.dromara.hutool.core.date.format.parser.FastDateParser; import org.dromara.hutool.core.date.format.parser.PositionDateParser; @@ -47,7 +47,6 @@ import java.util.TimeZone; *

* Thanks to Apache Commons Lang 3.5 * - * @since 2.16.2 */ public class FastDateFormat extends Format implements PositionDateParser, DatePrinter { private static final long serialVersionUID = 8097890768636183236L; @@ -413,7 +412,7 @@ public class FastDateFormat extends Format implements PositionDateParser, DatePr /** * 便捷获取 DateTimeFormatter - * 由于 {@link DatePattern} 很大一部分的格式没有提供 {@link DateTimeFormatter},因此这里提供快捷获取方式 + * 由于 {@link DateFormatPool} 很大一部分的格式没有提供 {@link DateTimeFormatter},因此这里提供快捷获取方式 * * @return DateTimeFormatter * @author dazer neusoft diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/date/format/FastDatePrinter.java b/hutool-core/src/main/java/org/dromara/hutool/core/date/format/FastDatePrinter.java index 79376a5d0..8468ff5bb 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/date/format/FastDatePrinter.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/date/format/FastDatePrinter.java @@ -16,20 +16,12 @@ package org.dromara.hutool.core.date.format; -import org.dromara.hutool.core.date.DateException; import org.dromara.hutool.core.date.format.parser.FastDateParser; -import org.dromara.hutool.core.map.concurrent.SafeConcurrentHashMap; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.text.DateFormatSymbols; -import java.util.ArrayList; import java.util.Calendar; import java.util.Date; -import java.util.List; import java.util.Locale; import java.util.TimeZone; -import java.util.concurrent.ConcurrentMap; /** * {@link java.text.SimpleDateFormat} 的线程安全版本,用于将 {@link Date} 格式化输出
@@ -40,10 +32,7 @@ import java.util.concurrent.ConcurrentMap; public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { private static final long serialVersionUID = -6305750172255764887L; - /** 规则列表. */ - private transient Rule[] rules; - /** 估算最大长度. */ - private transient int mMaxLengthEstimate; + private final DatePattern datePattern; // Constructor // ----------------------------------------------------------------------- @@ -56,247 +45,7 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { */ public FastDatePrinter(final String pattern, final TimeZone timeZone, final Locale locale) { super(pattern, timeZone, locale); - init(); - } - - /** - * 初始化 - */ - private void init() { - final List rulesList = parsePattern(); - rules = rulesList.toArray(new Rule[0]); - - int len = 0; - for (int i = rules.length; --i >= 0;) { - len += rules[i].estimateLength(); - } - - mMaxLengthEstimate = len; - } - - // Parse the pattern - // ----------------------------------------------------------------------- - /** - *

- * Returns a list of Rules given a pattern. - *

- * - * @return a {@code List} of Rule objects - * @throws IllegalArgumentException if pattern is invalid - */ - protected List parsePattern() { - final DateFormatSymbols symbols = new DateFormatSymbols(locale); - final List rules = new ArrayList<>(); - - final String[] ERAs = symbols.getEras(); - final String[] months = symbols.getMonths(); - final String[] shortMonths = symbols.getShortMonths(); - final String[] weekdays = symbols.getWeekdays(); - final String[] shortWeekdays = symbols.getShortWeekdays(); - final String[] AmPmStrings = symbols.getAmPmStrings(); - - final int length = pattern.length(); - final int[] indexRef = new int[1]; - - for (int i = 0; i < length; i++) { - indexRef[0] = i; - final String token = parseToken(pattern, indexRef); - i = indexRef[0]; - - final int tokenLen = token.length(); - if (tokenLen == 0) { - break; - } - - Rule rule; - final char c = token.charAt(0); - - switch (c) { - case 'G': // era designator (text) - rule = new TextField(Calendar.ERA, ERAs); - break; - case 'y': // year (number) - case 'Y': // week year - if (tokenLen == 2) { - rule = TwoDigitYearField.INSTANCE; - } else { - rule = selectNumberRule(Calendar.YEAR, Math.max(tokenLen, 4)); - } - if (c == 'Y') { - rule = new WeekYear((NumberRule) rule); - } - break; - case 'M': // month in year (text and number) - if (tokenLen >= 4) { - rule = new TextField(Calendar.MONTH, months); - } else if (tokenLen == 3) { - rule = new TextField(Calendar.MONTH, shortMonths); - } else if (tokenLen == 2) { - rule = TwoDigitMonthField.INSTANCE; - } else { - rule = UnpaddedMonthField.INSTANCE; - } - break; - case 'd': // day in month (number) - rule = selectNumberRule(Calendar.DAY_OF_MONTH, tokenLen); - break; - case 'h': // hour in am/pm (number, 1..12) - rule = new TwelveHourField(selectNumberRule(Calendar.HOUR, tokenLen)); - break; - case 'H': // hour in day (number, 0..23) - rule = selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen); - break; - case 'm': // minute in hour (number) - rule = selectNumberRule(Calendar.MINUTE, tokenLen); - break; - case 's': // second in minute (number) - rule = selectNumberRule(Calendar.SECOND, tokenLen); - break; - case 'S': // millisecond (number) - rule = selectNumberRule(Calendar.MILLISECOND, tokenLen); - break; - case 'E': // day in week (text) - rule = new TextField(Calendar.DAY_OF_WEEK, tokenLen < 4 ? shortWeekdays : weekdays); - break; - case 'u': // day in week (number) - rule = new DayInWeekField(selectNumberRule(Calendar.DAY_OF_WEEK, tokenLen)); - break; - case 'D': // day in year (number) - rule = selectNumberRule(Calendar.DAY_OF_YEAR, tokenLen); - break; - case 'F': // day of week in month (number) - rule = selectNumberRule(Calendar.DAY_OF_WEEK_IN_MONTH, tokenLen); - break; - case 'w': // week in year (number) - rule = selectNumberRule(Calendar.WEEK_OF_YEAR, tokenLen); - break; - case 'W': // week in month (number) - rule = selectNumberRule(Calendar.WEEK_OF_MONTH, tokenLen); - break; - case 'a': // am/pm marker (text) - rule = new TextField(Calendar.AM_PM, AmPmStrings); - break; - case 'k': // hour in day (1..24) - rule = new TwentyFourHourField(selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen)); - break; - case 'K': // hour in am/pm (0..11) - rule = selectNumberRule(Calendar.HOUR, tokenLen); - break; - case 'X': // ISO 8601 - rule = Iso8601_Rule.getRule(tokenLen); - break; - case 'z': // time zone (text) - if (tokenLen >= 4) { - rule = new TimeZoneNameRule(timeZone, locale, TimeZone.LONG); - } else { - rule = new TimeZoneNameRule(timeZone, locale, TimeZone.SHORT); - } - break; - case 'Z': // time zone (value) - if (tokenLen == 1) { - rule = TimeZoneNumberRule.INSTANCE_NO_COLON; - } else if (tokenLen == 2) { - rule = Iso8601_Rule.ISO8601_HOURS_COLON_MINUTES; - } else { - rule = TimeZoneNumberRule.INSTANCE_COLON; - } - break; - case '\'': // literal text - final String sub = token.substring(1); - if (sub.length() == 1) { - rule = new CharacterLiteral(sub.charAt(0)); - } else { - rule = new StringLiteral(sub); - } - break; - default: - throw new IllegalArgumentException("Illegal pattern component: " + token); - } - - rules.add(rule); - } - - return rules; - } - - /** - *

- * Performs the parsing of tokens. - *

- * - * @param pattern the pattern - * @param indexRef index references - * @return parsed token - */ - protected String parseToken(final String pattern, final int[] indexRef) { - final StringBuilder buf = new StringBuilder(); - - int i = indexRef[0]; - final int length = pattern.length(); - - char c = pattern.charAt(i); - if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') { - // Scan a run of the same character, which indicates a time - // pattern. - buf.append(c); - - while (i + 1 < length) { - final char peek = pattern.charAt(i + 1); - if (peek == c) { - buf.append(c); - i++; - } else { - break; - } - } - } else { - // This will identify token as text. - buf.append('\''); - - boolean inLiteral = false; - - for (; i < length; i++) { - c = pattern.charAt(i); - - if (c == '\'') { - if (i + 1 < length && pattern.charAt(i + 1) == '\'') { - // '' is treated as escaped ' - i++; - buf.append(c); - } else { - inLiteral = !inLiteral; - } - } else if (!inLiteral && (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')) { - i--; - break; - } else { - buf.append(c); - } - } - } - - indexRef[0] = i; - return buf.toString(); - } - - /** - *

- * Gets an appropriate rule for the padding required. - *

- * - * @param field the field to get a rule for - * @param padding the padding required - * @return a new rule with the correct padding - */ - protected NumberRule selectNumberRule(final int field, final int padding) { - switch (padding) { - case 1: - return new UnpaddedNumberField(field); - case 2: - return new TwoDigitNumberField(field); - default: - return new PaddedNumberField(field, padding); - } + this.datePattern = new DatePattern(pattern, locale, timeZone); } // Format methods @@ -338,21 +87,21 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { @Override public String format(final Calendar calendar) { - return format(calendar, new StringBuilder(mMaxLengthEstimate)).toString(); - } - - @Override - public B format(final long millis, final B buf) { - final Calendar c = Calendar.getInstance(timeZone, locale); - c.setTimeInMillis(millis); - return applyRules(c, buf); + return format(calendar, new StringBuilder(datePattern.getEstimateLength())).toString(); } @Override public B format(final Date date, final B buf) { final Calendar c = Calendar.getInstance(timeZone, locale); c.setTime(date); - return applyRules(c, buf); + return datePattern.applyRules(c, buf); + } + + @Override + public B format(final long millis, final B buf) { + final Calendar c = Calendar.getInstance(timeZone, locale); + c.setTimeInMillis(millis); + return datePattern.applyRules(c, buf); } @Override @@ -362,7 +111,7 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { calendar = (Calendar) calendar.clone(); calendar.setTimeZone(timeZone); } - return applyRules(calendar, buf); + return datePattern.applyRules(calendar, buf); } /** @@ -372,28 +121,7 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { * @return a String representation of the given Calendar. */ private String applyRulesToString(final Calendar c) { - return applyRules(c, new StringBuilder(mMaxLengthEstimate)).toString(); - } - - /** - *

- * Performs the formatting by applying the rules to the specified calendar. - *

- * - * @param calendar the calendar to format - * @param buf the buffer to format into - * @param the Appendable class type, usually StringBuilder or StringBuffer. - * @return the specified string buffer - */ - private B applyRules(final Calendar calendar, final B buf) { - try { - for (final Rule rule : this.rules) { - rule.appendTo(buf, calendar); - } - } catch (final IOException e) { - throw new DateException(e); - } - return buf; + return datePattern.applyRules(c, new StringBuilder(datePattern.getEstimateLength())).toString(); } /** @@ -403,835 +131,6 @@ public class FastDatePrinter extends SimpleDateBasic implements DatePrinter { * @return 日期字符串长度 */ public int getMaxLengthEstimate() { - return mMaxLengthEstimate; - } - - // Serializing - // ----------------------------------------------------------------------- - /** - * Create the object after serialization. This implementation reinitializes the transient properties. - * - * @param in ObjectInputStream from which the object is being deserialized. - * @throws IOException if there is an IO issue. - * @throws ClassNotFoundException if a class cannot be found. - */ - private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - init(); - } - - /** - * Appends two digits to the given buffer. - * - * @param buffer the buffer to append to. - * @param value the value to append digits from. - */ - private static void appendDigits(final Appendable buffer, final int value) throws IOException { - buffer.append((char) (value / 10 + '0')); - buffer.append((char) (value % 10 + '0')); - } - - private static final int MAX_DIGITS = 10; // log10(Integer.MAX_VALUE) ~= 9.3 - - /** - * Appends all digits to the given buffer. - * - * @param buffer the buffer to append to. - * @param value the value to append digits from. - */ - private static void appendFullDigits(final Appendable buffer, int value, int minFieldWidth) throws IOException { - // specialized paths for 1 to 4 digits -> avoid the memory allocation from the temporary work array - // see LANG-1248 - if (value < 10000) { - // less memory allocation path works for four digits or less - - int nDigits = 4; - if (value < 1000) { - --nDigits; - if (value < 100) { - --nDigits; - if (value < 10) { - --nDigits; - } - } - } - // left zero pad - for (int i = minFieldWidth - nDigits; i > 0; --i) { - buffer.append('0'); - } - - switch (nDigits) { - case 4: - buffer.append((char) (value / 1000 + '0')); - value %= 1000; - case 3: - if (value >= 100) { - buffer.append((char) (value / 100 + '0')); - value %= 100; - } else { - buffer.append('0'); - } - case 2: - if (value >= 10) { - buffer.append((char) (value / 10 + '0')); - value %= 10; - } else { - buffer.append('0'); - } - case 1: - buffer.append((char) (value + '0')); - } - } else { - // more memory allocation path works for any digits - - // build up decimal representation in reverse - final char[] work = new char[MAX_DIGITS]; - int digit = 0; - while (value != 0) { - work[digit++] = (char) (value % 10 + '0'); - value = value / 10; - } - - // pad with zeros - while (digit < minFieldWidth) { - buffer.append('0'); - --minFieldWidth; - } - - // reverse - while (--digit >= 0) { - buffer.append(work[digit]); - } - } - } - - // Rules - // ----------------------------------------------------------------------- - /** - * 规则 - */ - public interface Rule { - /** - * Returns the estimated length of the result. - * - * @return the estimated length - */ - int estimateLength(); - - /** - * Appends the value of the specified calendar to the output buffer based on the rule implementation. - * - * @param buf the output buffer - * @param calendar calendar to be appended - * @throws IOException if an I/O error occurs - */ - void appendTo(Appendable buf, Calendar calendar) throws IOException; - } - - /** - *

- * Inner class defining a numeric rule. - *

- */ - public interface NumberRule extends Rule { - /** - * Appends the specified value to the output buffer based on the rule implementation. - * - * @param buffer the output buffer - * @param value the value to be appended - * @throws IOException if an I/O error occurs - */ - void appendTo(Appendable buffer, int value) throws IOException; - } - - /** - *

- * Inner class to output a constant single character. - *

- */ - private static class CharacterLiteral implements Rule { - private final char mValue; - - /** - * Constructs a new instance of {@code CharacterLiteral} to hold the specified value. - * - * @param value the character literal - */ - CharacterLiteral(final char value) { - mValue = value; - } - - @Override - public int estimateLength() { - return 1; - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - buffer.append(mValue); - } - } - - /** - *

- * Inner class to output a constant string. - *

- */ - private static class StringLiteral implements Rule { - private final String mValue; - - /** - * Constructs a new instance of {@code StringLiteral} to hold the specified value. - * - * @param value the string literal - */ - StringLiteral(final String value) { - mValue = value; - } - - @Override - public int estimateLength() { - return mValue.length(); - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - buffer.append(mValue); - } - } - - /** - *

- * Inner class to output one of a set of values. - *

- */ - private static class TextField implements Rule { - private final int mField; - private final String[] mValues; - - /** - * Constructs an instance of {@code TextField} with the specified field and values. - * - * @param field the field - * @param values the field values - */ - TextField(final int field, final String[] values) { - mField = field; - mValues = values; - } - - @Override - public int estimateLength() { - int max = 0; - for (int i = mValues.length; --i >= 0;) { - final int len = mValues[i].length(); - if (len > max) { - max = len; - } - } - return max; - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - buffer.append(mValues[calendar.get(mField)]); - } - } - - /** - *

- * Inner class to output an unpadded number. - *

- */ - private static class UnpaddedNumberField implements NumberRule { - private final int mField; - - /** - * Constructs an instance of {@code UnpadedNumberField} with the specified field. - * - * @param field the field - */ - UnpaddedNumberField(final int field) { - mField = field; - } - - @Override - public int estimateLength() { - return 4; - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - appendTo(buffer, calendar.get(mField)); - } - - @Override - public final void appendTo(final Appendable buffer, final int value) throws IOException { - if (value < 10) { - buffer.append((char) (value + '0')); - } else if (value < 100) { - appendDigits(buffer, value); - } else { - appendFullDigits(buffer, value, 1); - } - } - } - - /** - *

- * Inner class to output an unpadded month. - *

- */ - private static class UnpaddedMonthField implements NumberRule { - static final UnpaddedMonthField INSTANCE = new UnpaddedMonthField(); - - /** - * Constructs an instance of {@code UnpaddedMonthField}. - * - */ - UnpaddedMonthField() { - } - - @Override - public int estimateLength() { - return 2; - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - appendTo(buffer, calendar.get(Calendar.MONTH) + 1); - } - - @Override - public final void appendTo(final Appendable buffer, final int value) throws IOException { - if (value < 10) { - buffer.append((char) (value + '0')); - } else { - appendDigits(buffer, value); - } - } - } - - /** - *

- * Inner class to output a padded number. - *

- */ - private static class PaddedNumberField implements NumberRule { - private final int mField; - private final int mSize; - - /** - * Constructs an instance of {@code PaddedNumberField}. - * - * @param field the field - * @param size size of the output field - */ - PaddedNumberField(final int field, final int size) { - if (size < 3) { - // Should use UnpaddedNumberField or TwoDigitNumberField. - throw new IllegalArgumentException(); - } - mField = field; - mSize = size; - } - - @Override - public int estimateLength() { - return mSize; - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - appendTo(buffer, calendar.get(mField)); - } - - @Override - public final void appendTo(final Appendable buffer, final int value) throws IOException { - appendFullDigits(buffer, value, mSize); - } - } - - /** - *

- * Inner class to output a two digit number. - *

- */ - private static class TwoDigitNumberField implements NumberRule { - private final int mField; - - /** - * Constructs an instance of {@code TwoDigitNumberField} with the specified field. - * - * @param field the field - */ - TwoDigitNumberField(final int field) { - mField = field; - } - - @Override - public int estimateLength() { - return 2; - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - appendTo(buffer, calendar.get(mField)); - } - - @Override - public final void appendTo(final Appendable buffer, final int value) throws IOException { - if (value < 100) { - appendDigits(buffer, value); - } else { - appendFullDigits(buffer, value, 2); - } - } - } - - /** - *

- * Inner class to output a two digit year. - *

- */ - private static class TwoDigitYearField implements NumberRule { - static final TwoDigitYearField INSTANCE = new TwoDigitYearField(); - - /** - * Constructs an instance of {@code TwoDigitYearField}. - */ - TwoDigitYearField() { - } - - @Override - public int estimateLength() { - return 2; - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - appendTo(buffer, calendar.get(Calendar.YEAR) % 100); - } - - @Override - public final void appendTo(final Appendable buffer, final int value) throws IOException { - appendDigits(buffer, value); - } - } - - /** - *

- * Inner class to output a two digit month. - *

- */ - private static class TwoDigitMonthField implements NumberRule { - static final TwoDigitMonthField INSTANCE = new TwoDigitMonthField(); - - /** - * Constructs an instance of {@code TwoDigitMonthField}. - */ - TwoDigitMonthField() { - } - - @Override - public int estimateLength() { - return 2; - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - appendTo(buffer, calendar.get(Calendar.MONTH) + 1); - } - - @Override - public final void appendTo(final Appendable buffer, final int value) throws IOException { - appendDigits(buffer, value); - } - } - - /** - *

- * Inner class to output the twelve hour field. - *

- */ - private static class TwelveHourField implements NumberRule { - private final NumberRule mRule; - - /** - * Constructs an instance of {@code TwelveHourField} with the specified {@code NumberRule}. - * - * @param rule the rule - */ - TwelveHourField(final NumberRule rule) { - mRule = rule; - } - - @Override - public int estimateLength() { - return mRule.estimateLength(); - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - int value = calendar.get(Calendar.HOUR); - if (value == 0) { - value = calendar.getLeastMaximum(Calendar.HOUR) + 1; - } - mRule.appendTo(buffer, value); - } - - @Override - public void appendTo(final Appendable buffer, final int value) throws IOException { - mRule.appendTo(buffer, value); - } - } - - /** - *

- * Inner class to output the twenty four hour field. - *

- */ - private static class TwentyFourHourField implements NumberRule { - private final NumberRule mRule; - - /** - * Constructs an instance of {@code TwentyFourHourField} with the specified {@code NumberRule}. - * - * @param rule the rule - */ - TwentyFourHourField(final NumberRule rule) { - mRule = rule; - } - - @Override - public int estimateLength() { - return mRule.estimateLength(); - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - int value = calendar.get(Calendar.HOUR_OF_DAY); - if (value == 0) { - value = calendar.getMaximum(Calendar.HOUR_OF_DAY) + 1; - } - mRule.appendTo(buffer, value); - } - - @Override - public void appendTo(final Appendable buffer, final int value) throws IOException { - mRule.appendTo(buffer, value); - } - } - - /** - *

- * Inner class to output the numeric day in week. - *

- */ - private static class DayInWeekField implements NumberRule { - private final NumberRule mRule; - - DayInWeekField(final NumberRule rule) { - mRule = rule; - } - - @Override - public int estimateLength() { - return mRule.estimateLength(); - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - final int value = calendar.get(Calendar.DAY_OF_WEEK); - mRule.appendTo(buffer, value != Calendar.SUNDAY ? value - 1 : 7); - } - - @Override - public void appendTo(final Appendable buffer, final int value) throws IOException { - mRule.appendTo(buffer, value); - } - } - - /** - *

- * Inner class to output the numeric day in week. - *

- */ - private static class WeekYear implements NumberRule { - private final NumberRule mRule; - - WeekYear(final NumberRule rule) { - mRule = rule; - } - - @Override - public int estimateLength() { - return mRule.estimateLength(); - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - int weekYear = calendar.getWeekYear(); - if (mRule instanceof TwoDigitYearField) { - // issue#3641 - weekYear %= 100; - } - mRule.appendTo(buffer, weekYear); - } - - @Override - public void appendTo(final Appendable buffer, final int value) throws IOException { - mRule.appendTo(buffer, value); - } - } - - // ----------------------------------------------------------------------- - - private static final ConcurrentMap C_TIME_ZONE_DISPLAY_CACHE = new SafeConcurrentHashMap<>(7); - - /** - *

- * Gets the time zone display name, using a cache for performance. - *

- * - * @param tz the zone to query - * @param daylight true if daylight savings - * @param style the style to use {@code TimeZone.LONG} or {@code TimeZone.SHORT} - * @param locale the locale to use - * @return the textual name of the time zone - */ - static String getTimeZoneDisplay(final TimeZone tz, final boolean daylight, final int style, final Locale locale) { - final TimeZoneDisplayKey key = new TimeZoneDisplayKey(tz, daylight, style, locale); - String value = C_TIME_ZONE_DISPLAY_CACHE.get(key); - if (value == null) { - // This is a very slow call, so cache the results. - value = tz.getDisplayName(daylight, style, locale); - final String prior = C_TIME_ZONE_DISPLAY_CACHE.putIfAbsent(key, value); - if (prior != null) { - value = prior; - } - } - return value; - } - - /** - *

- * Inner class to output a time zone name. - *

- */ - private static class TimeZoneNameRule implements Rule { - private final Locale mLocale; - private final int mStyle; - private final String mStandard; - private final String mDaylight; - - /** - * Constructs an instance of {@code TimeZoneNameRule} with the specified properties. - * - * @param timeZone the time zone - * @param locale the locale - * @param style the style - */ - TimeZoneNameRule(final TimeZone timeZone, final Locale locale, final int style) { - mLocale = locale; - mStyle = style; - - mStandard = getTimeZoneDisplay(timeZone, false, style, locale); - mDaylight = getTimeZoneDisplay(timeZone, true, style, locale); - } - - @Override - public int estimateLength() { - // We have no access to the Calendar object that will be passed to - // appendTo so base estimate on the TimeZone passed to the - // constructor - return Math.max(mStandard.length(), mDaylight.length()); - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - final TimeZone zone = calendar.getTimeZone(); - if (calendar.get(Calendar.DST_OFFSET) != 0) { - buffer.append(getTimeZoneDisplay(zone, true, mStyle, mLocale)); - } else { - buffer.append(getTimeZoneDisplay(zone, false, mStyle, mLocale)); - } - } - } - - /** - *

- * Inner class to output a time zone as a number {@code +/-HHMM} or {@code +/-HH:MM}. - *

- */ - private static class TimeZoneNumberRule implements Rule { - static final TimeZoneNumberRule INSTANCE_COLON = new TimeZoneNumberRule(true); - static final TimeZoneNumberRule INSTANCE_NO_COLON = new TimeZoneNumberRule(false); - - final boolean mColon; - - /** - * Constructs an instance of {@code TimeZoneNumberRule} with the specified properties. - * - * @param colon add colon between HH and MM in the output if {@code true} - */ - TimeZoneNumberRule(final boolean colon) { - mColon = colon; - } - - @Override - public int estimateLength() { - return 5; - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - - int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET); - - if (offset < 0) { - buffer.append('-'); - offset = -offset; - } else { - buffer.append('+'); - } - - final int hours = offset / (60 * 60 * 1000); - appendDigits(buffer, hours); - - if (mColon) { - buffer.append(':'); - } - - final int minutes = offset / (60 * 1000) - 60 * hours; - appendDigits(buffer, minutes); - } - } - - /** - *

- * Inner class to output a time zone as a number {@code +/-HHMM} or {@code +/-HH:MM}. - *

- */ - private static class Iso8601_Rule implements Rule { - - // Sign TwoDigitHours or Z - static final Iso8601_Rule ISO8601_HOURS = new Iso8601_Rule(3); - // Sign TwoDigitHours Minutes or Z - static final Iso8601_Rule ISO8601_HOURS_MINUTES = new Iso8601_Rule(5); - // Sign TwoDigitHours : Minutes or Z - static final Iso8601_Rule ISO8601_HOURS_COLON_MINUTES = new Iso8601_Rule(6); - - /** - * Factory method for Iso8601_Rules. - * - * @param tokenLen a token indicating the length of the TimeZone String to be formatted. - * @return a Iso8601_Rule that can format TimeZone String of length {@code tokenLen}. If no such rule exists, an IllegalArgumentException will be thrown. - */ - static Iso8601_Rule getRule(final int tokenLen) { - switch (tokenLen) { - case 1: - return Iso8601_Rule.ISO8601_HOURS; - case 2: - return Iso8601_Rule.ISO8601_HOURS_MINUTES; - case 3: - return Iso8601_Rule.ISO8601_HOURS_COLON_MINUTES; - default: - throw new IllegalArgumentException("invalid number of X"); - } - } - - final int length; - - /** - * Constructs an instance of {@code Iso8601_Rule} with the specified properties. - * - * @param length The number of characters in output (unless Z is output) - */ - Iso8601_Rule(final int length) { - this.length = length; - } - - @Override - public int estimateLength() { - return length; - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET); - if (offset == 0) { - buffer.append("Z"); - return; - } - - if (offset < 0) { - buffer.append('-'); - offset = -offset; - } else { - buffer.append('+'); - } - - final int hours = offset / (60 * 60 * 1000); - appendDigits(buffer, hours); - - if (length < 5) { - return; - } - - if (length == 6) { - buffer.append(':'); - } - - final int minutes = offset / (60 * 1000) - 60 * hours; - appendDigits(buffer, minutes); - } - } - - // ---------------------------------------------------------------------- - /** - *

- * Inner class that acts as a compound key for time zone names. - *

- */ - private static class TimeZoneDisplayKey { - private final TimeZone mTimeZone; - private final int mStyle; - private final Locale mLocale; - - /** - * Constructs an instance of {@code TimeZoneDisplayKey} with the specified properties. - * - * @param timeZone the time zone - * @param daylight adjust the style for daylight saving time if {@code true} - * @param style the timezone style - * @param locale the timezone locale - */ - TimeZoneDisplayKey(final TimeZone timeZone, final boolean daylight, final int style, final Locale locale) { - mTimeZone = timeZone; - if (daylight) { - mStyle = style | 0x80000000; - } else { - mStyle = style; - } - mLocale = locale; - } - - @Override - public int hashCode() { - return (mStyle * 31 + mLocale.hashCode()) * 31 + mTimeZone.hashCode(); - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof TimeZoneDisplayKey) { - final TimeZoneDisplayKey other = (TimeZoneDisplayKey) obj; - return mTimeZone.equals(other.mTimeZone) && mStyle == other.mStyle && mLocale.equals(other.mLocale); - } - return false; - } + return datePattern.getEstimateLength(); } } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/date/format/parser/FastDateParser.java b/hutool-core/src/main/java/org/dromara/hutool/core/date/format/parser/FastDateParser.java index a5c2d3dc0..dd536966d 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/date/format/parser/FastDateParser.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/date/format/parser/FastDateParser.java @@ -332,23 +332,23 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse /** * 单个日期字段的分析策略 */ - private static abstract class Strategy { + interface Strategy { + boolean parse(FastDateParser parser, Calendar calendar, CharSequence source, ParsePosition pos, int maxWidth); + /** - * Is this field a number? The default implementation returns false. + * 是否为数字,默认{@code false} * - * @return true, if field is a number + * @return {@code true}表示为数字 */ - boolean isNumber() { + default boolean isNumber() { return false; } - - abstract boolean parse(FastDateParser parser, Calendar calendar, CharSequence source, ParsePosition pos, int maxWidth); } /** * A strategy to parse a single field from the parsing pattern */ - private static abstract class PatternStrategy extends Strategy { + private static abstract class PatternStrategy implements Strategy { private Pattern pattern; @@ -361,7 +361,7 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse } @Override - boolean parse(final FastDateParser parser, final Calendar calendar, final CharSequence source, final ParsePosition pos, final int maxWidth) { + public boolean parse(final FastDateParser parser, final Calendar calendar, final CharSequence source, final ParsePosition pos, final int maxWidth) { final Matcher matcher = pattern.matcher(source.subSequence(pos.getIndex(), source.length())); if (!matcher.lookingAt()) { pos.setErrorIndex(pos.getIndex()); @@ -477,7 +477,7 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse /** * A strategy that copies the static or quoted field in the parsing pattern */ - private static class CopyQuotedStrategy extends Strategy { + private static class CopyQuotedStrategy implements Strategy { final private String formatField; @@ -491,7 +491,7 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse } @Override - boolean parse(final FastDateParser parser, final Calendar calendar, final CharSequence source, final ParsePosition pos, final int maxWidth) { + public boolean parse(final FastDateParser parser, final Calendar calendar, final CharSequence source, final ParsePosition pos, final int maxWidth) { for (int idx = 0; idx < formatField.length(); ++idx) { final int sIdx = idx + pos.getIndex(); if (sIdx == source.length()) { @@ -545,7 +545,7 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse /** * A strategy that handles a number field in the parsing pattern */ - private static class NumberStrategy extends Strategy { + private static class NumberStrategy implements Strategy { private final int field; /** @@ -558,12 +558,12 @@ public class FastDateParser extends SimpleDateBasic implements PositionDateParse } @Override - boolean isNumber() { + public boolean isNumber() { return true; } @Override - boolean parse(final FastDateParser parser, final Calendar calendar, final CharSequence source, final ParsePosition pos, final int maxWidth) { + public boolean parse(final FastDateParser parser, final Calendar calendar, final CharSequence source, final ParsePosition pos, final int maxWidth) { int idx = pos.getIndex(); int last = source.length(); diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/date/format/parser/TimeParser.java b/hutool-core/src/main/java/org/dromara/hutool/core/date/format/parser/TimeParser.java index 5740994ea..fed22ebd7 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/date/format/parser/TimeParser.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/date/format/parser/TimeParser.java @@ -16,7 +16,7 @@ package org.dromara.hutool.core.date.format.parser; -import org.dromara.hutool.core.date.DatePattern; +import org.dromara.hutool.core.date.DateFormatPool; import org.dromara.hutool.core.date.DateTime; import org.dromara.hutool.core.date.DateUtil; import org.dromara.hutool.core.regex.PatternPool; @@ -57,10 +57,10 @@ public class TimeParser implements PredicateDateParser, Serializable { source = StrUtil.format("{} {}", DateUtil.formatToday(), source); if (1 == StrUtil.count(source, ':')) { // 时间格式为 HH:mm - return new DateTime(source, DatePattern.NORM_DATETIME_MINUTE_PATTERN); + return new DateTime(source, DateFormatPool.NORM_DATETIME_MINUTE_PATTERN); } else { // 时间格式为 HH:mm:ss - return new DateTime(source, DatePattern.NORM_DATETIME_FORMAT); + return new DateTime(source, DateFormatPool.NORM_DATETIME_FORMAT); } } } diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/date/CalendarUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/date/CalendarUtilTest.java index 5aeb8560a..63d00d5ed 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/date/CalendarUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/date/CalendarUtilTest.java @@ -38,7 +38,7 @@ public class CalendarUtilTest { public void parseTest(){ Assertions.assertThrows(IllegalArgumentException.class, ()->{ final Calendar calendar = CalendarUtil.parse("2021-09-27 00:00:112323", false, - DatePattern.NORM_DATETIME_FORMAT); + DateFormatPool.NORM_DATETIME_FORMAT); // https://github.com/dromara/hutool/issues/1849 // 在使用严格模式时,秒不正确,抛出异常 diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/date/DateModifierTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/date/DateModifierTest.java index fa6c28ce0..44b34e4e3 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/date/DateModifierTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/date/DateModifierTest.java @@ -30,47 +30,47 @@ public class DateModifierTest { // 毫秒 DateTime begin = DateUtil.truncate(date, DateField.MILLISECOND); - Assertions.assertEquals(dateStr, begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals(dateStr, begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 秒 begin = DateUtil.truncate(date, DateField.SECOND); - Assertions.assertEquals("2017-03-01 22:33:23.000", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 22:33:23.000", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 分 begin = DateUtil.truncate(date, DateField.MINUTE); - Assertions.assertEquals("2017-03-01 22:33:00.000", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 22:33:00.000", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 小时 begin = DateUtil.truncate(date, DateField.HOUR); - Assertions.assertEquals("2017-03-01 22:00:00.000", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 22:00:00.000", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); begin = DateUtil.truncate(date, DateField.HOUR_OF_DAY); - Assertions.assertEquals("2017-03-01 22:00:00.000", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 22:00:00.000", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 上下午,原始日期是22点,上下午的起始就是12点 begin = DateUtil.truncate(date, DateField.AM_PM); - Assertions.assertEquals("2017-03-01 12:00:00.000", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 12:00:00.000", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 天,day of xxx按照day处理 begin = DateUtil.truncate(date, DateField.DAY_OF_WEEK_IN_MONTH); - Assertions.assertEquals("2017-03-01 00:00:00.000", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 00:00:00.000", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); begin = DateUtil.truncate(date, DateField.DAY_OF_WEEK); - Assertions.assertEquals("2017-03-01 00:00:00.000", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 00:00:00.000", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); begin = DateUtil.truncate(date, DateField.DAY_OF_MONTH); - Assertions.assertEquals("2017-03-01 00:00:00.000", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 00:00:00.000", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 星期 begin = DateUtil.truncate(date, DateField.WEEK_OF_MONTH); - Assertions.assertEquals("2017-02-27 00:00:00.000", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-02-27 00:00:00.000", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); begin = DateUtil.truncate(date, DateField.WEEK_OF_YEAR); - Assertions.assertEquals("2017-02-27 00:00:00.000", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-02-27 00:00:00.000", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 月 begin = DateUtil.truncate(date, DateField.MONTH); - Assertions.assertEquals("2017-03-01 00:00:00.000", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 00:00:00.000", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 年 begin = DateUtil.truncate(date, DateField.YEAR); - Assertions.assertEquals("2017-01-01 00:00:00.000", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-01-01 00:00:00.000", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); } @Test @@ -80,7 +80,7 @@ public class DateModifierTest { // 天,day of xxx按照day处理 final DateTime begin = DateUtil.truncate(date, DateField.DAY_OF_WEEK_IN_MONTH); - Assertions.assertEquals("2017-03-01 00:00:00.000", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 00:00:00.000", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); } @Test @@ -90,47 +90,47 @@ public class DateModifierTest { // 毫秒 DateTime begin = DateUtil.ceiling(date, DateField.MILLISECOND, false); - Assertions.assertEquals(dateStr, begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals(dateStr, begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 秒 begin = DateUtil.ceiling(date, DateField.SECOND, false); - Assertions.assertEquals("2017-03-01 22:33:23.999", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 22:33:23.999", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 分 begin = DateUtil.ceiling(date, DateField.MINUTE, false); - Assertions.assertEquals("2017-03-01 22:33:59.999", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 22:33:59.999", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 小时 begin = DateUtil.ceiling(date, DateField.HOUR, false); - Assertions.assertEquals("2017-03-01 22:59:59.999", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 22:59:59.999", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); begin = DateUtil.ceiling(date, DateField.HOUR_OF_DAY, false); - Assertions.assertEquals("2017-03-01 22:59:59.999", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 22:59:59.999", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 上下午,原始日期是22点,上下午的结束就是23点 begin = DateUtil.ceiling(date, DateField.AM_PM, false); - Assertions.assertEquals("2017-03-01 23:59:59.999", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 23:59:59.999", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 天,day of xxx按照day处理 begin = DateUtil.ceiling(date, DateField.DAY_OF_WEEK_IN_MONTH, false); - Assertions.assertEquals("2017-03-01 23:59:59.999", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 23:59:59.999", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); begin = DateUtil.ceiling(date, DateField.DAY_OF_WEEK, false); - Assertions.assertEquals("2017-03-01 23:59:59.999", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 23:59:59.999", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); begin = DateUtil.ceiling(date, DateField.DAY_OF_MONTH, false); - Assertions.assertEquals("2017-03-01 23:59:59.999", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-01 23:59:59.999", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 星期 begin = DateUtil.ceiling(date, DateField.WEEK_OF_MONTH, false); - Assertions.assertEquals("2017-03-05 23:59:59.999", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-05 23:59:59.999", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); begin = DateUtil.ceiling(date, DateField.WEEK_OF_YEAR, false); - Assertions.assertEquals("2017-03-05 23:59:59.999", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-05 23:59:59.999", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 月 begin = DateUtil.ceiling(date, DateField.MONTH, false); - Assertions.assertEquals("2017-03-31 23:59:59.999", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-03-31 23:59:59.999", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); // 年 begin = DateUtil.ceiling(date, DateField.YEAR, false); - Assertions.assertEquals("2017-12-31 23:59:59.999", begin.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2017-12-31 23:59:59.999", begin.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); } @Test @@ -140,6 +140,6 @@ public class DateModifierTest { final Date date = DateUtil.parse(dateStr); final DateTime dateTime = DateUtil.round(date, DateField.SECOND); - Assertions.assertEquals("2022-08-12 14:59:21.999", dateTime.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2022-08-12 14:59:21.999", dateTime.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); } } diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/date/DateTimeTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/date/DateTimeTest.java index deffef1f9..56ac6cd3f 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/date/DateTimeTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/date/DateTimeTest.java @@ -31,7 +31,7 @@ public class DateTimeTest { @Test public void datetimeTest() { - final DateTime dateTime = new DateTime("2017-01-05 12:34:23", DatePattern.NORM_DATETIME_FORMAT); + final DateTime dateTime = new DateTime("2017-01-05 12:34:23", DateFormatPool.NORM_DATETIME_FORMAT); // 年 final int year = dateTime.year(); @@ -73,36 +73,36 @@ public class DateTimeTest { @Test public void quarterTest() { - DateTime dateTime = new DateTime("2017-01-05 12:34:23", DatePattern.NORM_DATETIME_FORMAT); + DateTime dateTime = new DateTime("2017-01-05 12:34:23", DateFormatPool.NORM_DATETIME_FORMAT); Quarter quarter = dateTime.quarterEnum(); Assertions.assertEquals(Quarter.Q1, quarter); - dateTime = new DateTime("2017-04-05 12:34:23", DatePattern.NORM_DATETIME_FORMAT); + dateTime = new DateTime("2017-04-05 12:34:23", DateFormatPool.NORM_DATETIME_FORMAT); quarter = dateTime.quarterEnum(); Assertions.assertEquals(Quarter.Q2, quarter); - dateTime = new DateTime("2017-07-05 12:34:23", DatePattern.NORM_DATETIME_FORMAT); + dateTime = new DateTime("2017-07-05 12:34:23", DateFormatPool.NORM_DATETIME_FORMAT); quarter = dateTime.quarterEnum(); Assertions.assertEquals(Quarter.Q3, quarter); - dateTime = new DateTime("2017-10-05 12:34:23", DatePattern.NORM_DATETIME_FORMAT); + dateTime = new DateTime("2017-10-05 12:34:23", DateFormatPool.NORM_DATETIME_FORMAT); quarter = dateTime.quarterEnum(); Assertions.assertEquals(Quarter.Q4, quarter); // 精确到毫秒 - final DateTime beginTime = new DateTime("2017-10-01 00:00:00.000", DatePattern.NORM_DATETIME_MS_FORMAT); + final DateTime beginTime = new DateTime("2017-10-01 00:00:00.000", DateFormatPool.NORM_DATETIME_MS_FORMAT); dateTime = DateUtil.beginOfQuarter(dateTime); Assertions.assertEquals(beginTime, dateTime); // 精确到毫秒 - final DateTime endTime = new DateTime("2017-12-31 23:59:59.999", DatePattern.NORM_DATETIME_MS_FORMAT); + final DateTime endTime = new DateTime("2017-12-31 23:59:59.999", DateFormatPool.NORM_DATETIME_MS_FORMAT); dateTime = DateUtil.endOfQuarter(dateTime, false); Assertions.assertEquals(endTime, dateTime); } @Test public void mutableTest() { - final DateTime dateTime = new DateTime("2017-01-05 12:34:23", DatePattern.NORM_DATETIME_FORMAT); + final DateTime dateTime = new DateTime("2017-01-05 12:34:23", DateFormatPool.NORM_DATETIME_FORMAT); // 默认情况下DateTime为可变对象 DateTime offsite = dateTime.offset(DateField.YEAR, 0); @@ -116,7 +116,7 @@ public class DateTimeTest { @Test public void toStringTest() { - final DateTime dateTime = new DateTime("2017-01-05 12:34:23", DatePattern.NORM_DATETIME_FORMAT); + final DateTime dateTime = new DateTime("2017-01-05 12:34:23", DateFormatPool.NORM_DATETIME_FORMAT); Assertions.assertEquals("2017-01-05 12:34:23", dateTime.toString()); final String dateStr = dateTime.toString("yyyy/MM/dd"); @@ -125,18 +125,18 @@ public class DateTimeTest { @Test public void toStringTest2() { - final DateTime dateTime = new DateTime("2017-01-05 12:34:23", DatePattern.NORM_DATETIME_FORMAT); + final DateTime dateTime = new DateTime("2017-01-05 12:34:23", DateFormatPool.NORM_DATETIME_FORMAT); - String dateStr = dateTime.toString(DatePattern.ISO8601_WITH_ZONE_OFFSET_PATTERN); + String dateStr = dateTime.toString(DateFormatPool.ISO8601_WITH_ZONE_OFFSET_PATTERN); Assertions.assertEquals("2017-01-05T12:34:23+0800", dateStr); - dateStr = dateTime.toString(DatePattern.ISO8601_WITH_XXX_OFFSET_PATTERN); + dateStr = dateTime.toString(DateFormatPool.ISO8601_WITH_XXX_OFFSET_PATTERN); Assertions.assertEquals("2017-01-05T12:34:23+08:00", dateStr); } @Test public void toStringWithTimeZoneTest() { - final DateTime dateTime = new DateTime("2017-01-05 12:34:23", DatePattern.NORM_DATETIME_FORMAT); + final DateTime dateTime = new DateTime("2017-01-05 12:34:23", DateFormatPool.NORM_DATETIME_FORMAT); final String dateStr = dateTime.toString(TimeZone.getTimeZone("UTC")); Assertions.assertEquals("2017-01-05 04:34:23", dateStr); @@ -168,7 +168,7 @@ public class DateTimeTest { public void ofTest(){ Assertions.assertThrows(IllegalArgumentException.class, ()->{ final String a = "2021-09-27 00:00:99"; - new DateTime(a, DatePattern.NORM_DATETIME_FORMAT, false); + new DateTime(a, DateFormatPool.NORM_DATETIME_FORMAT, false); }); } diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/date/DateUtilTest.java index 894747b81..ea06fede0 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/date/DateUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/date/DateUtilTest.java @@ -142,10 +142,10 @@ public class DateUtilTest { DateTime dateTime = DateUtil.ceiling(date2, DateField.MINUTE, false); - Assertions.assertEquals("2020-02-29 12:59:59.999", dateTime.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2020-02-29 12:59:59.999", dateTime.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); dateTime = DateUtil.ceiling(date2, DateField.MINUTE, true); - Assertions.assertEquals("2020-02-29 12:59:59.000", dateTime.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2020-02-29 12:59:59.000", dateTime.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); } @Test @@ -155,10 +155,10 @@ public class DateUtilTest { DateTime dateTime = DateUtil.ceiling(date2, DateField.DAY_OF_MONTH, false); - Assertions.assertEquals("2020-02-29 23:59:59.999", dateTime.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2020-02-29 23:59:59.999", dateTime.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); dateTime = DateUtil.ceiling(date2, DateField.DAY_OF_MONTH, true); - Assertions.assertEquals("2020-02-29 23:59:59.000", dateTime.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2020-02-29 23:59:59.000", dateTime.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); } @Test @@ -393,13 +393,13 @@ public class DateUtilTest { public void parseTest3() { final String dateStr = "2018-10-10 12:11:11"; final Date date = DateUtil.parse(dateStr); - final String format = DateUtil.format(date, DatePattern.NORM_DATETIME_PATTERN); + final String format = DateUtil.format(date, DateFormatPool.NORM_DATETIME_PATTERN); Assertions.assertEquals(dateStr, format); } @Test public void parseTest4() { - final String ymd = DateUtil.parse("2019-3-21 12:20:15", "yyyy-MM-dd").toString(DatePattern.PURE_DATE_PATTERN); + final String ymd = DateUtil.parse("2019-3-21 12:20:15", "yyyy-MM-dd").toString(DateFormatPool.PURE_DATE_PATTERN); Assertions.assertEquals("20190321", ymd); } @@ -407,33 +407,33 @@ public class DateUtilTest { public void parseTest5() { // 测试时间解析 //noinspection ConstantConditions - String time = DateUtil.parse("22:12:12").toString(DatePattern.NORM_TIME_FORMAT); + String time = DateUtil.parse("22:12:12").toString(DateFormatPool.NORM_TIME_FORMAT); Assertions.assertEquals("22:12:12", time); //noinspection ConstantConditions - time = DateUtil.parse("2:12:12").toString(DatePattern.NORM_TIME_FORMAT); + time = DateUtil.parse("2:12:12").toString(DateFormatPool.NORM_TIME_FORMAT); Assertions.assertEquals("02:12:12", time); //noinspection ConstantConditions - time = DateUtil.parse("2:2:12").toString(DatePattern.NORM_TIME_FORMAT); + time = DateUtil.parse("2:2:12").toString(DateFormatPool.NORM_TIME_FORMAT); Assertions.assertEquals("02:02:12", time); //noinspection ConstantConditions - time = DateUtil.parse("2:2:1").toString(DatePattern.NORM_TIME_FORMAT); + time = DateUtil.parse("2:2:1").toString(DateFormatPool.NORM_TIME_FORMAT); Assertions.assertEquals("02:02:01", time); //noinspection ConstantConditions - time = DateUtil.parse("22:2:1").toString(DatePattern.NORM_TIME_FORMAT); + time = DateUtil.parse("22:2:1").toString(DateFormatPool.NORM_TIME_FORMAT); Assertions.assertEquals("22:02:01", time); //noinspection ConstantConditions - time = DateUtil.parse("2:22:1").toString(DatePattern.NORM_TIME_FORMAT); + time = DateUtil.parse("2:22:1").toString(DateFormatPool.NORM_TIME_FORMAT); Assertions.assertEquals("02:22:01", time); // 测试两位时间解析 //noinspection ConstantConditions - time = DateUtil.parse("2:22").toString(DatePattern.NORM_TIME_FORMAT); + time = DateUtil.parse("2:22").toString(DateFormatPool.NORM_TIME_FORMAT); Assertions.assertEquals("02:22:00", time); //noinspection ConstantConditions - time = DateUtil.parse("12:22").toString(DatePattern.NORM_TIME_FORMAT); + time = DateUtil.parse("12:22").toString(DateFormatPool.NORM_TIME_FORMAT); Assertions.assertEquals("12:22:00", time); //noinspection ConstantConditions - time = DateUtil.parse("12:2").toString(DatePattern.NORM_TIME_FORMAT); + time = DateUtil.parse("12:2").toString(DateFormatPool.NORM_TIME_FORMAT); Assertions.assertEquals("12:02:00", time); } @@ -475,22 +475,22 @@ public class DateUtilTest { String str = "2020-02-06 01:58:00.000020"; DateTime dateTime = DateUtil.parse(str); Assertions.assertNotNull(dateTime); - Assertions.assertEquals("2020-02-06 01:58:00.000", dateTime.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2020-02-06 01:58:00.000", dateTime.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); str = "2020-02-06 01:58:00.00002"; dateTime = DateUtil.parse(str); Assertions.assertNotNull(dateTime); - Assertions.assertEquals("2020-02-06 01:58:00.000", dateTime.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2020-02-06 01:58:00.000", dateTime.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); str = "2020-02-06 01:58:00.111000"; dateTime = DateUtil.parse(str); Assertions.assertNotNull(dateTime); - Assertions.assertEquals("2020-02-06 01:58:00.111", dateTime.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2020-02-06 01:58:00.111", dateTime.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); str = "2020-02-06 01:58:00.111"; dateTime = DateUtil.parse(str); Assertions.assertNotNull(dateTime); - Assertions.assertEquals("2020-02-06 01:58:00.111", dateTime.toString(DatePattern.NORM_DATETIME_MS_PATTERN)); + Assertions.assertEquals("2020-02-06 01:58:00.111", dateTime.toString(DateFormatPool.NORM_DATETIME_MS_PATTERN)); } /** @@ -532,7 +532,7 @@ public class DateUtilTest { public void parseDateTest() { final String dateStr = "2018-4-10"; final Date date = DateUtil.parse(dateStr); - final String format = DateUtil.format(date, DatePattern.NORM_DATE_PATTERN); + final String format = DateUtil.format(date, DateFormatPool.NORM_DATE_PATTERN); Assertions.assertEquals("2018-04-10", format); } @@ -645,7 +645,7 @@ public class DateUtilTest { dateStr1 = "2018-09-13T13:34:36.999+0800"; dt = DateUtil.parse(dateStr1); - final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DatePattern.NORM_DATETIME_MS_PATTERN); + final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateFormatPool.NORM_DATETIME_MS_PATTERN); simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8:00")); dateStr = Objects.requireNonNull(dt).toString(simpleDateFormat); Assertions.assertEquals("2018-09-13 13:34:36.999", dateStr); @@ -705,7 +705,7 @@ public class DateUtilTest { public void parseCSTTest() { final String dateStr = "Wed Sep 16 11:26:23 +0800 2009"; - final SimpleDateFormat sdf = new SimpleDateFormat(DatePattern.JDK_DATETIME_PATTERN, Locale.US); + final SimpleDateFormat sdf = new SimpleDateFormat(DateFormatPool.JDK_DATETIME_PATTERN, Locale.US); // Asia/Shanghai是以地区命名的地区标准时,在中国叫CST,因此如果解析CST时不使用"Asia/Shanghai"而使用"GMT+08:00",会导致相差一个小时 sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); final DateTime parse = DateUtil.parse(dateStr, sdf); @@ -719,11 +719,11 @@ public class DateUtilTest { public void parseCSTTest2() { final String dateStr = "Wed Sep 16 11:26:23 CST 2009"; - final SimpleDateFormat sdf = new SimpleDateFormat(DatePattern.JDK_DATETIME_PATTERN, Locale.US); + final SimpleDateFormat sdf = new SimpleDateFormat(DateFormatPool.JDK_DATETIME_PATTERN, Locale.US); sdf.setTimeZone(TimeZone.getTimeZone("America/Chicago")); final DateTime parse = DateUtil.parse(dateStr, sdf); - final FastDateFormat fdf = FastDateFormat.getInstance(DatePattern.JDK_DATETIME_PATTERN, TimeZone.getTimeZone("America/Chicago"), Locale.US); + final FastDateFormat fdf = FastDateFormat.getInstance(DateFormatPool.JDK_DATETIME_PATTERN, TimeZone.getTimeZone("America/Chicago"), Locale.US); final DateTime parse2 = DateUtil.parse(dateStr, fdf); Assertions.assertEquals(parse, parse2); @@ -788,14 +788,14 @@ public class DateUtilTest { final Date date2 = DateUtil.parse("2021-04-13 23:59:10"); Assertions.assertEquals(1, DateUtil.compare(date1, date2)); - Assertions.assertEquals(1, DateUtil.compare(date1, date2, DatePattern.NORM_DATETIME_PATTERN)); - Assertions.assertEquals(0, DateUtil.compare(date1, date2, DatePattern.NORM_DATE_PATTERN)); - Assertions.assertEquals(0, DateUtil.compare(date1, date2, DatePattern.NORM_DATETIME_MINUTE_PATTERN)); + Assertions.assertEquals(1, DateUtil.compare(date1, date2, DateFormatPool.NORM_DATETIME_PATTERN)); + Assertions.assertEquals(0, DateUtil.compare(date1, date2, DateFormatPool.NORM_DATE_PATTERN)); + Assertions.assertEquals(0, DateUtil.compare(date1, date2, DateFormatPool.NORM_DATETIME_MINUTE_PATTERN)); final Date date11 = DateUtil.parse("2021-04-13 23:59:59.999"); final Date date22 = DateUtil.parse("2021-04-11 23:10:10"); - Assertions.assertEquals(0, DateUtil.compare(date11, date22, DatePattern.NORM_MONTH_PATTERN)); + Assertions.assertEquals(0, DateUtil.compare(date11, date22, DateFormatPool.NORM_MONTH_PATTERN)); } @Test @@ -830,7 +830,7 @@ public class DateUtilTest { final LocalDate localDate = localDateTime.toLocalDate(); final DateTime date2 = DateUtil.date(localDate); Assertions.assertEquals("2017-05-06", - DateUtil.format(date2, DatePattern.NORM_DATE_PATTERN)); + DateUtil.format(date2, DateFormatPool.NORM_DATE_PATTERN)); } @Test @@ -890,8 +890,8 @@ public class DateUtilTest { Assertions.assertEquals(strDate, strDate1); final String strDate2 = "2019-12-01 17:02:30.111"; - ldt = TimeUtil.parse(strDate2, DatePattern.NORM_DATETIME_MS_PATTERN); - strDate1 = DateUtil.format(ldt, DatePattern.NORM_DATETIME_PATTERN); + ldt = TimeUtil.parse(strDate2, DateFormatPool.NORM_DATETIME_MS_PATTERN); + strDate1 = DateUtil.format(ldt, DateFormatPool.NORM_DATETIME_PATTERN); Assertions.assertEquals(strDate, strDate1); } @@ -900,7 +900,7 @@ public class DateUtilTest { // 测试字符串与LocalDateTime的互相转换 final String strDate = "2019-12-01"; final LocalDateTime localDateTime = TimeUtil.parse(strDate, "yyyy-MM-dd"); - Assertions.assertEquals(strDate, DateUtil.format(localDateTime, DatePattern.NORM_DATE_PATTERN)); + Assertions.assertEquals(strDate, DateUtil.format(localDateTime, DateFormatPool.NORM_DATE_PATTERN)); } @Test @@ -975,7 +975,7 @@ public class DateUtilTest { Assertions.assertThrows(DateException.class, ()->{ //https://github.com/dromara/hutool/issues/1332 // 在日期格式不匹配的时候,测试是否正常报错 - DateUtil.parse("2020-12-23", DatePattern.PURE_DATE_PATTERN); + DateUtil.parse("2020-12-23", DateFormatPool.PURE_DATE_PATTERN); }); } @@ -985,14 +985,14 @@ public class DateUtilTest { calendar.set(2021, Calendar.JULY, 14, 23, 59, 59); final Date date = new DateTime(calendar); - Assertions.assertEquals("2021-07-14 23:59:59", DateUtil.format(date, DatePattern.NORM_DATETIME_FORMATTER)); - Assertions.assertEquals("2021-07-14 23:59:59", DateUtil.format(date, DatePattern.NORM_DATETIME_FORMAT)); - Assertions.assertEquals("2021-07-14 23:59:59", DateUtil.format(date, DatePattern.NORM_DATETIME_PATTERN)); + Assertions.assertEquals("2021-07-14 23:59:59", DateUtil.format(date, DateFormatPool.NORM_DATETIME_FORMATTER)); + Assertions.assertEquals("2021-07-14 23:59:59", DateUtil.format(date, DateFormatPool.NORM_DATETIME_FORMAT)); + Assertions.assertEquals("2021-07-14 23:59:59", DateUtil.format(date, DateFormatPool.NORM_DATETIME_PATTERN)); } @Test public void formatNormDateTimeFormatterTest() { - String format = DateUtil.format(DateUtil.parse("2021-07-14 10:05:38"), DatePattern.NORM_DATETIME_FORMATTER); + String format = DateUtil.format(DateUtil.parse("2021-07-14 10:05:38"), DateFormatPool.NORM_DATETIME_FORMATTER); Assertions.assertEquals("2021-07-14 10:05:38", format); format = DateUtil.format(TimeUtil.parseByISO("2021-07-14T10:05:38"), @@ -1024,7 +1024,7 @@ public class DateUtilTest { @Test public void parseByDateTimeFormatterTest() { - final DateTime parse = DateUtil.parse("2021-12-01", DatePattern.NORM_DATE_FORMATTER); + final DateTime parse = DateUtil.parse("2021-12-01", DateFormatPool.NORM_DATE_FORMATTER); Assertions.assertEquals("2021-12-01 00:00:00", parse.toString()); } diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/date/TemporalAccessorUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/date/TemporalAccessorUtilTest.java index 8e48fadf6..5d5fa2db8 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/date/TemporalAccessorUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/date/TemporalAccessorUtilTest.java @@ -26,14 +26,14 @@ public class TemporalAccessorUtilTest { @Test public void formatLocalDateTest(){ - final String format = TemporalAccessorUtil.format(LocalDate.of(2020, 12, 7), DatePattern.NORM_DATETIME_PATTERN); + final String format = TemporalAccessorUtil.format(LocalDate.of(2020, 12, 7), DateFormatPool.NORM_DATETIME_PATTERN); Assertions.assertEquals("2020-12-07 00:00:00", format); } @Test public void formatLocalTimeTest(){ - final String today = TemporalAccessorUtil.format(LocalDate.now(), DatePattern.NORM_DATE_PATTERN); - final String format = TemporalAccessorUtil.format(LocalTime.MIN, DatePattern.NORM_DATETIME_PATTERN); + final String today = TemporalAccessorUtil.format(LocalDate.now(), DateFormatPool.NORM_DATE_PATTERN); + final String format = TemporalAccessorUtil.format(LocalTime.MIN, DateFormatPool.NORM_DATETIME_PATTERN); Assertions.assertEquals(today + " 00:00:00", format); } @@ -54,9 +54,9 @@ public class TemporalAccessorUtilTest { final String startTimeStr = "2022-04-19 00:00:00"; final String endTimeStr = "2022-04-19 23:59:59"; final boolean between = TimeUtil.isIn( - TimeUtil.parse(sourceStr, DatePattern.NORM_DATETIME_FORMATTER), - TimeUtil.parse(startTimeStr, DatePattern.NORM_DATETIME_FORMATTER), - TimeUtil.parse(endTimeStr, DatePattern.NORM_DATETIME_FORMATTER)); + TimeUtil.parse(sourceStr, DateFormatPool.NORM_DATETIME_FORMATTER), + TimeUtil.parse(startTimeStr, DateFormatPool.NORM_DATETIME_FORMATTER), + TimeUtil.parse(endTimeStr, DateFormatPool.NORM_DATETIME_FORMATTER)); Assertions.assertTrue(between); } } diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/date/TimeUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/date/TimeUtilTest.java index f9ed45ff2..b2d9c9124 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/date/TimeUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/date/TimeUtilTest.java @@ -75,13 +75,13 @@ public class TimeUtilTest { @Test public void parseTest2() { - final LocalDateTime localDateTime = TimeUtil.parse("2020-01-23", DatePattern.NORM_DATE_PATTERN); + final LocalDateTime localDateTime = TimeUtil.parse("2020-01-23", DateFormatPool.NORM_DATE_PATTERN); assertEquals("2020-01-23T00:00", Objects.requireNonNull(localDateTime).toString()); } @Test public void parseTest3() { - final LocalDateTime localDateTime = TimeUtil.parse("12:23:56", DatePattern.NORM_TIME_PATTERN); + final LocalDateTime localDateTime = TimeUtil.parse("12:23:56", DateFormatPool.NORM_TIME_PATTERN); assertEquals("12:23:56", Objects.requireNonNull(localDateTime).toLocalTime().toString()); } @@ -127,20 +127,20 @@ public class TimeUtilTest { @Test public void formatTest() { final LocalDateTime localDateTime = TimeUtil.parseByISO("2020-01-23T12:23:56"); - String format = TimeUtil.format(localDateTime, DatePattern.NORM_DATETIME_PATTERN); + String format = TimeUtil.format(localDateTime, DateFormatPool.NORM_DATETIME_PATTERN); assertEquals("2020-01-23 12:23:56", format); format = TimeUtil.formatNormal(localDateTime); assertEquals("2020-01-23 12:23:56", format); - format = TimeUtil.format(localDateTime, DatePattern.NORM_DATE_PATTERN); + format = TimeUtil.format(localDateTime, DateFormatPool.NORM_DATE_PATTERN); assertEquals("2020-01-23", format); } @Test public void formatLocalDateTest() { final LocalDate date = LocalDate.parse("2020-01-23"); - String format = TimeUtil.format(date, DatePattern.NORM_DATE_PATTERN); + String format = TimeUtil.format(date, DateFormatPool.NORM_DATE_PATTERN); assertEquals("2020-01-23", format); format = TimeUtil.formatNormal(date); @@ -354,7 +354,7 @@ public class TimeUtilTest { public void formatDateFunctionTest() { final List dateStrList = Stream.of("2023-03-01", "2023-03-02") .map(LocalDate::parse) - .map(TimeUtil.formatFunc(DatePattern.CHINESE_DATE_FORMATTER)) + .map(TimeUtil.formatFunc(DateFormatPool.CHINESE_DATE_FORMATTER)) .collect(Collectors.toList()); assertEquals("2023年03月01日", dateStrList.get(0)); assertEquals("2023年03月02日", dateStrList.get(1)); @@ -364,7 +364,7 @@ public class TimeUtilTest { public void formatTimeFunctionTest() { final List dateStrList = Stream.of("2023-03-01T12:23:56", "2023-03-02T12:23:56") .map(LocalDateTime::parse) - .map(TimeUtil.formatFunc(DatePattern.CHINESE_DATE_FORMATTER)) + .map(TimeUtil.formatFunc(DateFormatPool.CHINESE_DATE_FORMATTER)) .collect(Collectors.toList()); assertEquals("2023年03月01日", dateStrList.get(0)); assertEquals("2023年03月02日", dateStrList.get(1)); diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/date/TimeZoneTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/date/TimeZoneTest.java index 811e44ad5..9d7010642 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/date/TimeZoneTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/date/TimeZoneTest.java @@ -27,7 +27,7 @@ public class TimeZoneTest { @Test public void timeZoneConvertTest() { final DateTime dt = DateUtil.parse("2018-07-10 21:44:32", // - FastDateFormat.getInstance(DatePattern.NORM_DATETIME_PATTERN, TimeZone.getTimeZone("GMT+8:00"))); + FastDateFormat.getInstance(DateFormatPool.NORM_DATETIME_PATTERN, TimeZone.getTimeZone("GMT+8:00"))); Assertions.assertEquals("2018-07-10 21:44:32", dt.toString()); dt.setTimeZone(TimeZone.getTimeZone("Europe/London")); diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/text/CharSequenceUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/text/CharSequenceUtilTest.java index 8fe064345..19d48e7f0 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/text/CharSequenceUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/text/CharSequenceUtilTest.java @@ -16,7 +16,7 @@ package org.dromara.hutool.core.text; -import org.dromara.hutool.core.date.DatePattern; +import org.dromara.hutool.core.date.DateFormatPool; import org.dromara.hutool.core.date.DateUtil; import org.dromara.hutool.core.util.CharsetUtil; import org.junit.jupiter.api.Assertions; @@ -203,12 +203,12 @@ public class CharSequenceUtilTest { public void defaultIfEmptyTest() { final String emptyValue = ""; final Instant result1 = CharSequenceUtil.defaultIfEmpty(emptyValue, - (v) -> DateUtil.parse(v, DatePattern.NORM_DATETIME_PATTERN).toInstant(), Instant::now); + (v) -> DateUtil.parse(v, DateFormatPool.NORM_DATETIME_PATTERN).toInstant(), Instant::now); Assertions.assertNotNull(result1); final String dateStr = "2020-10-23 15:12:30"; final Instant result2 = CharSequenceUtil.defaultIfEmpty(dateStr, - (v) -> DateUtil.parse(v, DatePattern.NORM_DATETIME_PATTERN).toInstant(), Instant::now); + (v) -> DateUtil.parse(v, DateFormatPool.NORM_DATETIME_PATTERN).toInstant(), Instant::now); Assertions.assertNotNull(result2); } @@ -216,12 +216,12 @@ public class CharSequenceUtilTest { public void defaultIfBlankTest() { final String emptyValue = " "; final Instant result1 = CharSequenceUtil.defaultIfBlank(emptyValue, - (v) -> DateUtil.parse(v, DatePattern.NORM_DATETIME_PATTERN).toInstant(), Instant::now); + (v) -> DateUtil.parse(v, DateFormatPool.NORM_DATETIME_PATTERN).toInstant(), Instant::now); Assertions.assertNotNull(result1); final String dateStr = "2020-10-23 15:12:30"; final Instant result2 = CharSequenceUtil.defaultIfBlank(dateStr, - (v) -> DateUtil.parse(v, DatePattern.NORM_DATETIME_PATTERN).toInstant(), Instant::now); + (v) -> DateUtil.parse(v, DateFormatPool.NORM_DATETIME_PATTERN).toInstant(), Instant::now); Assertions.assertNotNull(result2); } diff --git a/hutool-json/src/test/java/org/dromara/hutool/json/JSONObjectTest.java b/hutool-json/src/test/java/org/dromara/hutool/json/JSONObjectTest.java index 4d913d723..62a0a5b3d 100644 --- a/hutool-json/src/test/java/org/dromara/hutool/json/JSONObjectTest.java +++ b/hutool-json/src/test/java/org/dromara/hutool/json/JSONObjectTest.java @@ -20,7 +20,7 @@ import lombok.Data; import org.dromara.hutool.core.annotation.Alias; import org.dromara.hutool.core.annotation.PropIgnore; import org.dromara.hutool.core.collection.ListUtil; -import org.dromara.hutool.core.date.DatePattern; +import org.dromara.hutool.core.date.DateFormatPool; import org.dromara.hutool.core.date.DateUtil; import org.dromara.hutool.core.date.format.GlobalCustomFormat; import org.dromara.hutool.core.io.resource.ResourceUtil; @@ -74,7 +74,7 @@ public class JSONObjectTest { */ @Test public void toStringTest3() { - final JSONObject json = JSONUtil.ofObj(JSONConfig.of().setDateFormat(DatePattern.NORM_DATE_PATTERN))// + final JSONObject json = JSONUtil.ofObj(JSONConfig.of().setDateFormat(DateFormatPool.NORM_DATE_PATTERN))// .putValue("dateTime", DateUtil.parse("2019-05-02 22:12:01")); assertEquals("{\"dateTime\":\"2019-05-02\"}", json.toString()); } @@ -85,7 +85,7 @@ public class JSONObjectTest { assert json != null; assertEquals("{\"date\":1557314301000}", json.toString()); - json = JSONUtil.ofObj(JSONConfig.of().setDateFormat(DatePattern.NORM_DATE_PATTERN)) + json = JSONUtil.ofObj(JSONConfig.of().setDateFormat(DateFormatPool.NORM_DATE_PATTERN)) .putValue("date", DateUtil.parse("2019-05-08 19:18:21")); assertEquals("{\"date\":\"2019-05-08\"}", json.toString()); } diff --git a/hutool-json/src/test/java/org/dromara/hutool/json/jwt/JWTTest.java b/hutool-json/src/test/java/org/dromara/hutool/json/jwt/JWTTest.java index 0e9ff1469..ed687fb75 100644 --- a/hutool-json/src/test/java/org/dromara/hutool/json/jwt/JWTTest.java +++ b/hutool-json/src/test/java/org/dromara/hutool/json/jwt/JWTTest.java @@ -17,7 +17,7 @@ package org.dromara.hutool.json.jwt; import lombok.Data; -import org.dromara.hutool.core.date.DatePattern; +import org.dromara.hutool.core.date.DateFormatPool; import org.dromara.hutool.core.date.DateUtil; import org.dromara.hutool.core.reflect.TypeReference; import org.dromara.hutool.core.util.ByteUtil; @@ -179,7 +179,7 @@ public class JWTTest { // 签发时间早于被检查的时间 final Date date = JWT.of(token).getPayload().getClaimsJson().getDate(JWTPayload.ISSUED_AT); - Assertions.assertEquals("2022-02-02", DateUtil.format(date, DatePattern.NORM_DATE_PATTERN)); + Assertions.assertEquals("2022-02-02", DateUtil.format(date, DateFormatPool.NORM_DATE_PATTERN)); } @Test