FastDateParser改进在JDK25下三字母时区警告(issue#4100@Github)

This commit is contained in:
Looly
2026-03-02 18:57:04 +08:00
parent ab3e52ece7
commit 52603f3b12
5 changed files with 92 additions and 25 deletions

View File

@@ -8,6 +8,7 @@
* 【core 】 `BooleanUtil`新增 exactlyOneTrue 方法用于互斥条件校验issue#IDJQ15@Gitee
* 【core 】 `DateUtil.normalize`方法中正则预编译提升效率pr#4221@Gitee
* 【core 】 `AppendableWriter`增加checkNotClosedissue#IDMZ5K@Gitee
* 【core 】 `FastDateParser`改进在JDK25下三字母时区警告issue#4100@Github
### 🐞Bug修复
* 【json 】 修复`JSONUtil.wrap`忽略错误问题issue#4210@Github

View File

@@ -1,8 +1,9 @@
package cn.hutool.core.convert.impl;
import java.util.TimeZone;
import cn.hutool.core.convert.AbstractConverter;
import cn.hutool.core.date.TimeZoneUtil;
import java.util.TimeZone;
/**
* TimeZone转换器
@@ -14,7 +15,7 @@ public class TimeZoneConverter extends AbstractConverter<TimeZone>{
@Override
protected TimeZone convertInternal(Object value) {
return TimeZone.getTimeZone(convertToStr(value));
return TimeZoneUtil.getTimeZone(convertToStr(value));
}
}

View File

@@ -0,0 +1,60 @@
package cn.hutool.core.date;
import cn.hutool.core.util.JdkUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.SystemPropsUtil;
import java.time.ZoneId;
import java.util.TimeZone;
/**
* 时间时区工具类
*
* @author looly
* @since 5.8.44
*/
public class TimeZoneUtil {
/**
* A public version of {@link java.util.TimeZone}'s package private {@code GMT_ID} field.
*/
public static final String GMT_ID = "GMT";
/**
* The GMT time zone.
*/
public static final TimeZone GMT = getTimeZone(GMT_ID);
/**
* Delegates to {@link TimeZone#getTimeZone(String)} after mapping an ID if it's in {@link ZoneId#SHORT_IDS}.
* <p>
* On Java 25, calling {@link TimeZone#getTimeZone(String)} with an ID in {@link ZoneId#SHORT_IDS} writes a message to {@link System#err} in the form:
* </p>
*
* <pre>
* WARNING: Use of the three-letter time zone ID "the-short-id" is deprecated and it will be removed in a future release
* </pre>
* <p>
* You can disable mapping from {@link ZoneId#SHORT_IDS} by setting the system property {@code "TimeZones.mapShortIDs=false"}.
* </p>
*
* @param id Same as {@link TimeZone#getTimeZone(String)}.
* @return Same as {@link TimeZone#getTimeZone(String)}.
*/
public static TimeZone getTimeZone(final String id) {
return TimeZone.getTimeZone(JdkUtil.IS_AT_LEAST_JDK25 && mapShortIDs() ? ZoneId.SHORT_IDS.getOrDefault(id, id) : id);
}
private static boolean mapShortIDs() {
return SystemPropsUtil.getBoolean("TimeZones.mapShortIDs", true);
}
/**
* Returns the given TimeZone if non-{@code null}, otherwise {@link TimeZone#getDefault()}.
*
* @param timeZone a locale or {@code null}.
* @return the given locale if non-{@code null}, otherwise {@link TimeZone#getDefault()}.
*/
public static TimeZone toTimeZone(final TimeZone timeZone) {
return ObjectUtil.defaultIfNull(timeZone, TimeZone::getDefault);
}
}

View File

@@ -1,5 +1,6 @@
package cn.hutool.core.date.format;
import cn.hutool.core.date.TimeZoneUtil;
import cn.hutool.core.map.SafeConcurrentHashMap;
import java.io.IOException;
@@ -7,19 +8,7 @@ import java.io.ObjectInputStream;
import java.text.DateFormatSymbols;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeSet;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -655,6 +644,22 @@ public class FastDateParser extends AbstractDateBasic implements DateParser {
*/
private static final int ID = 0;
/**
* Tests whether to skip the given time zone, true if TimeZone.getTimeZone().
* <p>
* On Java 25 and up, skips short IDs if {@code ignoreTimeZoneShortIDs} is true.
* </p>
* <p>
* This method is package private only for testing.
* </p>
*
* @param tzId the ID to test.
* @return Whether to skip the given time zone ID.
*/
static boolean skipTimeZone(final String tzId) {
return TimeZoneUtil.GMT_ID.equalsIgnoreCase(tzId);
}
/**
* Construct a Strategy that parses a TimeZone
*
@@ -672,10 +677,10 @@ public class FastDateParser extends AbstractDateBasic implements DateParser {
for (final String[] zoneNames : zones) {
// offset 0 is the time zone ID and is not localized
final String tzId = zoneNames[ID];
if ("GMT".equalsIgnoreCase(tzId)) {
if (skipTimeZone(tzId)) {
continue;
}
final TimeZone tz = TimeZone.getTimeZone(tzId);
final TimeZone tz = TimeZoneUtil.getTimeZone(tzId);
// offset 1 is long standard name
// offset 2 is short standard name
final TzInfo standard = new TzInfo(tz, false);
@@ -712,10 +717,10 @@ public class FastDateParser extends AbstractDateBasic implements DateParser {
@Override
void setCalendar(final FastDateParser parser, final Calendar cal, final String value) {
if (value.charAt(0) == '+' || value.charAt(0) == '-') {
final TimeZone tz = TimeZone.getTimeZone("GMT" + value);
final TimeZone tz = TimeZoneUtil.getTimeZone("GMT" + value);
cal.setTimeZone(tz);
} else if (value.regionMatches(true, 0, "GMT", 0, 3)) {
final TimeZone tz = TimeZone.getTimeZone(value.toUpperCase());
final TimeZone tz = TimeZoneUtil.getTimeZone(value.toUpperCase());
cal.setTimeZone(tz);
} else {
final TzInfo tzInfo = tzNames.get(value.toLowerCase(locale));
@@ -742,9 +747,9 @@ public class FastDateParser extends AbstractDateBasic implements DateParser {
@Override
void setCalendar(final FastDateParser parser, final Calendar cal, final String value) {
if (Objects.equals(value, "Z")) {
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
cal.setTimeZone(TimeZoneUtil.getTimeZone("UTC"));
} else {
cal.setTimeZone(TimeZone.getTimeZone("GMT" + value));
cal.setTimeZone(TimeZoneUtil.getTimeZone("GMT" + value));
}
}

View File

@@ -1,15 +1,15 @@
package cn.hutool.core.convert;
import static org.junit.jupiter.api.Assertions.*;
import cn.hutool.core.date.TimeZoneUtil;
import org.junit.jupiter.api.Test;
import java.util.TimeZone;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class StringConvertTest {
@Test
public void timezoneToStrTest(){
final String s = Convert.toStr(TimeZone.getTimeZone("Asia/Shanghai"));
final String s = Convert.toStr(TimeZoneUtil.getTimeZone("Asia/Shanghai"));
assertEquals("Asia/Shanghai", s);
}
}