diff --git a/src/main/java/com/alibaba/fastjson/parser/deserializer/Jdk8DateCodec.java b/src/main/java/com/alibaba/fastjson/parser/deserializer/Jdk8DateCodec.java index 0769362455..a484cd5ea5 100644 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/Jdk8DateCodec.java +++ b/src/main/java/com/alibaba/fastjson/parser/deserializer/Jdk8DateCodec.java @@ -46,6 +46,9 @@ public class Jdk8DateCodec extends ContextObjectDeserializer implements ObjectSe private final static DateTimeFormatter formatter_d10_de = DateTimeFormatter.ofPattern("dd.MM.yyyy"); private final static DateTimeFormatter formatter_d10_in = DateTimeFormatter.ofPattern("dd-MM-yyyy"); + private final static DateTimeFormatter ISO_FIXED_FORMAT = + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault()); + private final static String formatter_iso8601_pattern = "yyyy-MM-dd'T'HH:mm:ss"; private final static DateTimeFormatter formatter_iso8601 = DateTimeFormatter.ofPattern(formatter_iso8601_pattern); @@ -58,7 +61,11 @@ public T deserialze(DefaultJSONParser parser, Type type, Object fieldName, S DateTimeFormatter formatter = null; if (format != null) { - formatter = DateTimeFormatter.ofPattern(format); + if (defaultPatttern.equals(format)) { + formatter = defaultFormatter; + } else { + formatter = DateTimeFormatter.ofPattern(format); + } } if (type == LocalDateTime.class) { @@ -92,7 +99,11 @@ public T deserialze(DefaultJSONParser parser, Type type, Object fieldName, S } return (T) localDate; } else if (type == ZonedDateTime.class) { - ZonedDateTime zonedDateTime = ZonedDateTime.parse(text); + if (formatter == defaultFormatter) { + formatter = ISO_FIXED_FORMAT; + } + + ZonedDateTime zonedDateTime = parseZonedDateTime(text, formatter); return (T) zonedDateTime; } else if (type == OffsetDateTime.class) { @@ -253,6 +264,76 @@ protected LocalDate parseLocalDate(String text, String format, DateTimeFormatter : LocalDate.parse(text, formatter); } + protected ZonedDateTime parseZonedDateTime(String text, DateTimeFormatter formatter) { + if (formatter == null) { + if (text.length() == 19) { + char c4 = text.charAt(4); + char c7 = text.charAt(7); + char c10 = text.charAt(10); + char c13 = text.charAt(13); + char c16 = text.charAt(16); + if (c13 == ':' && c16 == ':') { + if (c4 == '-' && c7 == '-') { + if (c10 == 'T') { + formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; + } else if (c10 == ' ') { + formatter = defaultFormatter; + } + } else if (c4 == '-' && c7 == '-') { + formatter = defaultFormatter; + } else if (c4 == '/' && c7 == '/') { // tw yyyy/mm/dd + formatter = formatter_dt19_tw; + } else { + char c0 = text.charAt(0); + char c1 = text.charAt(1); + char c2 = text.charAt(2); + char c3 = text.charAt(3); + char c5 = text.charAt(5); + if (c2 == '/' && c5 == '/') { // mm/dd/yyyy or mm/dd/yyyy + int v0 = (c0 - '0') * 10 + (c1 - '0'); + int v1 = (c3 - '0') * 10 + (c4 - '0'); + if (v0 > 12) { + formatter = formatter_dt19_eur; + } else if (v1 > 12) { + formatter = formatter_dt19_us; + } else { + String country = Locale.getDefault().getCountry(); + + if (country.equals("US")) { + formatter = formatter_dt19_us; + } else if (country.equals("BR") // + || country.equals("AU")) { + formatter = formatter_dt19_eur; + } + } + } else if (c2 == '.' && c5 == '.') { // dd.mm.yyyy + formatter = formatter_dt19_de; + } else if (c2 == '-' && c5 == '-') { // dd-mm-yyyy + formatter = formatter_dt19_in; + } + } + } + } + + if (text.length() >= 17) { + char c4 = text.charAt(4); + if (c4 == '年') { + if (text.charAt(text.length() - 1) == '秒') { + formatter = formatter_dt19_cn_1; + } else { + formatter = formatter_dt19_cn; + } + } else if (c4 == '년') { + formatter = formatter_dt19_kr; + } + } + } + + return formatter == null ? // + ZonedDateTime.parse(text) // + : ZonedDateTime.parse(text, formatter); + } + public int getFastMatchToken() { return JSONToken.LITERAL_STRING; } diff --git a/src/test/java/com/alibaba/json/bvt/jdk8/ZonedDateTimeTest2.java b/src/test/java/com/alibaba/json/bvt/jdk8/ZonedDateTimeTest2.java new file mode 100644 index 0000000000..c5f45626cd --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/jdk8/ZonedDateTimeTest2.java @@ -0,0 +1,30 @@ +package com.alibaba.json.bvt.jdk8; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.annotation.JSONField; +import junit.framework.TestCase; +import org.junit.Assert; + +import java.time.ZonedDateTime; +import java.time.temporal.TemporalField; + +public class ZonedDateTimeTest2 extends TestCase { + + public void test_for_issue() throws Exception { + VO vo = new VO(); + vo.date = ZonedDateTime.now(); + + String text = JSON.toJSONString(vo); + System.out.println(text); + + VO vo1 = JSON.parseObject(text, VO.class); + + Assert.assertEquals(vo.date.getSecond(), vo1.date.getSecond()); + } + + public static class VO { + @JSONField(format="yyyy-MM-dd HH:mm:ss") + public ZonedDateTime date; + + } +}