fix FastDateParser

This commit is contained in:
Looly 2020-03-08 09:55:31 +08:00
parent 81dbc75ba3
commit 8ba988e028
6 changed files with 66 additions and 80 deletions

View File

@ -6,6 +6,7 @@
## 5.2.1
### 新特性
* 【core 】 修改FastDateParser策略与JDK保持一致issue#I1AXIN@Gitee
### Bug修复
* 【setting】 修复Props.toBean方法null的问题
* 【core 】 修复DataUtil.parseLocalDateTime无时间部分报错问题issue#I1B18H@Gitee

View File

@ -10,6 +10,7 @@ import java.util.TimeZone;
* @since 2.16.2
*/
public interface DateBasic {
/**
* 获得日期格式化或者转换的格式
*

View File

@ -740,7 +740,9 @@ class FastDateParser extends AbstractDateBasic implements DateParser {
} else {
final TzInfo tzInfo = tzNames.get(value.toLowerCase(locale));
cal.set(Calendar.DST_OFFSET, tzInfo.dstOffset);
cal.set(Calendar.ZONE_OFFSET, tzInfo.zone.getRawOffset());
//issue#I1AXIN@Gitee
// cal.set(Calendar.ZONE_OFFSET, tzInfo.zone.getRawOffset());
cal.set(Calendar.ZONE_OFFSET, parser.getTimeZone().getRawOffset());
}
}
}

View File

@ -3,13 +3,13 @@ package cn.hutool.core.date.format;
import java.text.DateFormat;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Tuple;
/**
* 日期格式化器缓存<br>
@ -24,16 +24,16 @@ abstract class FormatCache<F extends Format> {
*/
static final int NONE = -1;
private final ConcurrentMap<MultipartKey, F> cInstanceCache = new ConcurrentHashMap<>(7);
private final ConcurrentMap<Tuple, F> cInstanceCache = new ConcurrentHashMap<>(7);
private static final ConcurrentMap<MultipartKey, String> cDateTimeInstanceCache = new ConcurrentHashMap<>(7);
private static final ConcurrentMap<Tuple, String> cDateTimeInstanceCache = new ConcurrentHashMap<>(7);
/**
* 使用默认的patterntimezone和locale获得缓存中的实例
* @return a date/time formatter
*/
public F getInstance() {
return getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, TimeZone.getDefault(), Locale.getDefault());
return getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, null, null);
}
/**
@ -53,7 +53,7 @@ abstract class FormatCache<F extends Format> {
if (locale == null) {
locale = Locale.getDefault();
}
final MultipartKey key = new MultipartKey(pattern, timeZone, locale);
final Tuple key = new Tuple(pattern, timeZone, locale);
F format = cInstanceCache.get(key);
if (format == null) {
format = createInstance(pattern, timeZone, locale);
@ -129,7 +129,7 @@ abstract class FormatCache<F extends Format> {
*/
// package protected, for access from FastDateFormat; do not make public or protected
F getDateInstance(final int dateStyle, final TimeZone timeZone, final Locale locale) {
return getDateTimeInstance(Integer.valueOf(dateStyle), null, timeZone, locale);
return getDateTimeInstance(dateStyle, null, timeZone, locale);
}
/**
@ -145,7 +145,7 @@ abstract class FormatCache<F extends Format> {
*/
// package protected, for access from FastDateFormat; do not make public or protected
F getTimeInstance(final int timeStyle, final TimeZone timeZone, final Locale locale) {
return getDateTimeInstance(null, Integer.valueOf(timeStyle), timeZone, locale);
return getDateTimeInstance(null, timeStyle, timeZone, locale);
}
/**
@ -161,18 +161,18 @@ abstract class FormatCache<F extends Format> {
*/
// package protected, for access from test code; do not make public or protected
static String getPatternForStyle(final Integer dateStyle, final Integer timeStyle, final Locale locale) {
final MultipartKey key = new MultipartKey(dateStyle, timeStyle, locale);
final Tuple key = new Tuple(dateStyle, timeStyle, locale);
String pattern = cDateTimeInstanceCache.get(key);
if (pattern == null) {
try {
DateFormat formatter;
if (dateStyle == null) {
formatter = DateFormat.getTimeInstance(timeStyle.intValue(), locale);
formatter = DateFormat.getTimeInstance(timeStyle, locale);
} else if (timeStyle == null) {
formatter = DateFormat.getDateInstance(dateStyle.intValue(), locale);
formatter = DateFormat.getDateInstance(dateStyle, locale);
} else {
formatter = DateFormat.getDateTimeInstance(dateStyle.intValue(), timeStyle.intValue(), locale);
formatter = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale);
}
pattern = ((SimpleDateFormat) formatter).toPattern();
final String previous = cDateTimeInstanceCache.putIfAbsent(key, pattern);
@ -188,62 +188,4 @@ abstract class FormatCache<F extends Format> {
}
return pattern;
}
// ----------------------------------------------------------------------
/**
* <p>
* Helper class to hold multi-part Map keys
* </p>
*/
private static class MultipartKey {
private final Object[] keys;
private int hashCode;
/**
* Constructs an instance of <code>MultipartKey</code> to hold the specified objects.
*
* @param keys the set of objects that make up the key. Each key may be null.
*/
public MultipartKey(final Object... keys) {
this.keys = keys;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final MultipartKey other = (MultipartKey) obj;
return false != Arrays.equals(keys, other.keys);
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
if (hashCode == 0) {
int rc = 0;
for (final Object key : keys) {
if (key != null) {
rc = rc * 7 + key.hashCode();
}
}
hashCode = rc;
}
return hashCode;
}
}
}

View File

@ -1,12 +1,12 @@
package cn.hutool.core.lang;
import cn.hutool.core.clone.CloneSupport;
import cn.hutool.core.collection.ArrayIter;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Iterator;
import cn.hutool.core.clone.CloneSupport;
import cn.hutool.core.collection.ArrayIter;
/**
* 不可变数组类型用于多值返回<br>
* 多值可以支持每个元素值类型不同
@ -17,7 +17,9 @@ import cn.hutool.core.collection.ArrayIter;
public class Tuple extends CloneSupport<Tuple> implements Iterable<Object>, Serializable{
private static final long serialVersionUID = -7689304393482182157L;
private Object[] members;
private final Object[] members;
private int hashCode;
private boolean cacheHash;
/**
* 构造
@ -45,12 +47,31 @@ public class Tuple extends CloneSupport<Tuple> implements Iterable<Object>, Seri
public Object[] getMembers(){
return this.members;
}
/**
* 缓存Hash值当为true时此对象的hash值只被计算一次常用于Tuple中的值不变时使用
* 注意当为true时member变更对象后hash值不会变更
*
* @param cacheHash 是否缓存hash值
* @return this
* @since 5.2.1
*/
public Tuple setCacheHash(boolean cacheHash){
this.cacheHash = cacheHash;
return this;
}
@Override
public int hashCode() {
if(this.cacheHash && 0 != this.hashCode){
return this.hashCode;
}
final int prime = 31;
int result = 1;
result = prime * result + Arrays.deepHashCode(members);
if(this.cacheHash){
this.hashCode = result;
}
return result;
}
@ -74,8 +95,9 @@ public class Tuple extends CloneSupport<Tuple> implements Iterable<Object>, Seri
return Arrays.toString(members);
}
@SuppressWarnings("NullableProblems")
@Override
public Iterator<Object> iterator() {
return new ArrayIter<Object>(members);
return new ArrayIter<>(members);
}
}

View File

@ -2,6 +2,7 @@ package cn.hutool.core.date;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.BetweenFormater.Level;
import cn.hutool.core.date.format.FastDateFormat;
import org.junit.Assert;
import org.junit.Test;
@ -16,6 +17,7 @@ import java.util.Calendar;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.TimeZone;
@ -505,23 +507,39 @@ public class DateUtilTest {
Assert.assertEquals("2018-09-13 13:34:39.999", dateStr);
}
@SuppressWarnings("ConstantConditions")
@Test
public void parseCSTTest(){
String dateStr = "Wed Sep 16 11:26:23 CST 2009";
SimpleDateFormat sdf = new SimpleDateFormat(DatePattern.JDK_DATETIME_PATTERN, Locale.US);
final DateTime parse = DateUtil.parse(dateStr, sdf);
DateTime dateTime = DateUtil.parseCST(dateStr);
Assert.assertEquals("2009-09-17 01:26:23", dateTime.toString());
Assert.assertEquals(parse, dateTime);
dateTime = DateUtil.parse(dateStr);
Assert.assertEquals("2009-09-17 01:26:23", dateTime.toString());
Assert.assertEquals(parse, dateTime);
}
@Test
public void parseCSTTest2(){
String dateStr = "Wed Sep 16 11:26:23 CST 2009";
SimpleDateFormat sdf = new SimpleDateFormat(DatePattern.JDK_DATETIME_PATTERN, Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
final DateTime parse = DateUtil.parse(dateStr, sdf);
FastDateFormat fdf = FastDateFormat.getInstance(DatePattern.JDK_DATETIME_PATTERN, TimeZone.getTimeZone("America/Chicago"), Locale.US);
final DateTime parse2 = DateUtil.parse(dateStr, fdf);
Assert.assertEquals(parse, parse2);
}
@SuppressWarnings("ConstantConditions")
@Test
public void parseJDkTest() {
String dateStr = "Thu May 16 17:57:18 GMT+08:00 2019";
DateTime time = DateUtil.parse(dateStr);
Assert.assertEquals("2019-05-16 17:57:18", time.toString());
Assert.assertEquals("2019-05-16 17:57:18", Objects.requireNonNull(time).toString());
}
@Test