mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
fix FastDateParser
This commit is contained in:
parent
81dbc75ba3
commit
8ba988e028
@ -6,6 +6,7 @@
|
||||
## 5.2.1
|
||||
|
||||
### 新特性
|
||||
* 【core 】 修改FastDateParser策略,与JDK保持一致(issue#I1AXIN@Gitee)
|
||||
### Bug修复
|
||||
* 【setting】 修复Props.toBean方法null的问题
|
||||
* 【core 】 修复DataUtil.parseLocalDateTime无时间部分报错问题(issue#I1B18H@Gitee)
|
||||
|
@ -10,6 +10,7 @@ import java.util.TimeZone;
|
||||
* @since 2.16.2
|
||||
*/
|
||||
public interface DateBasic {
|
||||
|
||||
/**
|
||||
* 获得日期格式化或者转换的格式
|
||||
*
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
* 使用默认的pattern、timezone和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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user