From 191c8c2d586e5db8817c15ca7e2ac464ee6e7273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E9=93=81?= Date: Sat, 10 Aug 2024 20:55:33 +0800 Subject: [PATCH] LocalDateTime & LocalDate parse support more cases --- .../alibaba/fastjson2/JSONReaderUTF16.java | 23 ++++++++ .../com/alibaba/fastjson2/JSONReaderUTF8.java | 23 ++++++++ .../com/alibaba/fastjson2/util/DateUtils.java | 20 +++++++ .../fastjson2/issues_2800/Issue2859.java | 54 +++++++++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 core/src/test/java/com/alibaba/fastjson2/issues_2800/Issue2859.java diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java index 6487bb0645..e5c7bcd5b7 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java @@ -4946,6 +4946,29 @@ public final LocalDate readLocalDate() { } } } + + int nextQuoteOffset = -1; + for (int i = offset, end = Math.min(i + 17, this.end); i < end; ++i) { + if (chars[i] == quote) { + nextQuoteOffset = i; + } + } + if (nextQuoteOffset != -1 + && nextQuoteOffset - offset > 10 + && chars[nextQuoteOffset - 6] == '-' + && chars[nextQuoteOffset - 3] == '-' + ) { + int year = TypeUtils.parseInt(chars, offset, nextQuoteOffset - offset - 6); + int month = TypeUtils.parseInt(chars, nextQuoteOffset - 5, 2); + int dayOfMonth = TypeUtils.parseInt(chars, nextQuoteOffset - 2, 2); + LocalDate localDate = LocalDate.of(year, month, dayOfMonth); + this.offset = nextQuoteOffset + 1; + next(); + if (comma = (this.ch == ',')) { + next(); + } + return localDate; + } } } return super.readLocalDate(); diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java index b467be0cc9..f779bd9f0b 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java @@ -6048,6 +6048,29 @@ public final LocalDate readLocalDate() { } } } + + int nextQuoteOffset = -1; + for (int i = offset, end = Math.min(i + 17, this.end); i < end; ++i) { + if (bytes[i] == quote) { + nextQuoteOffset = i; + } + } + if (nextQuoteOffset != -1 + && nextQuoteOffset - offset > 10 + && bytes[nextQuoteOffset - 6] == '-' + && bytes[nextQuoteOffset - 3] == '-' + ) { + int year = TypeUtils.parseInt(bytes, offset, nextQuoteOffset - offset - 6); + int month = TypeUtils.parseInt(bytes, nextQuoteOffset - 5, 2); + int dayOfMonth = TypeUtils.parseInt(bytes, nextQuoteOffset - 2, 2); + LocalDate localDate = LocalDate.of(year, month, dayOfMonth); + this.offset = nextQuoteOffset + 1; + next(); + if (comma = (this.ch == ',')) { + next(); + } + return localDate; + } } } return super.readLocalDate(); diff --git a/core/src/main/java/com/alibaba/fastjson2/util/DateUtils.java b/core/src/main/java/com/alibaba/fastjson2/util/DateUtils.java index 7697b7a432..9ad1ad9b65 100644 --- a/core/src/main/java/com/alibaba/fastjson2/util/DateUtils.java +++ b/core/src/main/java/com/alibaba/fastjson2/util/DateUtils.java @@ -5900,6 +5900,16 @@ public static LocalDateTime parseLocalDateTimeX(char[] str, int offset, int len) S6 = c26; S7 = c27; S8 = c28; + } else if (str[offset + len - 15] == '-' && str[offset + len - 12] == '-' + && (str[offset + len - 9] == ' ' || str[offset + len - 9] == 'T') + && str[offset + len - 6] == ':' && str[offset + len - 3] == ':') { + int year = TypeUtils.parseInt(str, offset, len - 15); + int month = TypeUtils.parseInt(str, offset + len - 14, 2); + int dayOfMonth = TypeUtils.parseInt(str, offset + len - 11, 2); + int hour = TypeUtils.parseInt(str, offset + len - 8, 2); + int minute = TypeUtils.parseInt(str, offset + len - 5, 2); + int second = TypeUtils.parseInt(str, offset + len - 2, 2); + return LocalDateTime.of(year, month, dayOfMonth, hour, minute, second); } else { return null; } @@ -6034,6 +6044,16 @@ public static LocalDateTime parseLocalDateTimeX(byte[] str, int offset, int len) S6 = c26; S7 = c27; S8 = c28; + } else if (str[offset + len - 15] == '-' && str[offset + len - 12] == '-' + && (str[offset + len - 9] == ' ' || str[offset + len - 9] == 'T') + && str[offset + len - 6] == ':' && str[offset + len - 3] == ':') { + int year = TypeUtils.parseInt(str, offset, len - 15); + int month = TypeUtils.parseInt(str, offset + len - 14, 2); + int dayOfMonth = TypeUtils.parseInt(str, offset + len - 11, 2); + int hour = TypeUtils.parseInt(str, offset + len - 8, 2); + int minute = TypeUtils.parseInt(str, offset + len - 5, 2); + int second = TypeUtils.parseInt(str, offset + len - 2, 2); + return LocalDateTime.of(year, month, dayOfMonth, hour, minute, second); } else { return null; } diff --git a/core/src/test/java/com/alibaba/fastjson2/issues_2800/Issue2859.java b/core/src/test/java/com/alibaba/fastjson2/issues_2800/Issue2859.java new file mode 100644 index 0000000000..d6fcdec996 --- /dev/null +++ b/core/src/test/java/com/alibaba/fastjson2/issues_2800/Issue2859.java @@ -0,0 +1,54 @@ +package com.alibaba.fastjson2.issues_2800; + +import com.alibaba.fastjson2.JSON; +import org.junit.jupiter.api.Test; + +import java.nio.charset.StandardCharsets; +import java.time.LocalDate; +import java.time.LocalDateTime; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class Issue2859 { + @Test + public void test() { + String str = "{\"time\":\"-999999999-11-12 13:14:15\"}"; + { + Bean bean = JSON.parseObject(str, Bean.class); + assertEquals(str, JSON.toJSONString(bean)); + } + { + Bean bean = JSON.parseObject(str.getBytes(StandardCharsets.UTF_8), Bean.class); + assertEquals(str, JSON.toJSONString(bean)); + } + { + Bean bean = JSON.parseObject(str.toCharArray(), Bean.class); + assertEquals(str, JSON.toJSONString(bean)); + } + } + + static class Bean { + public LocalDateTime time; + } + + @Test + public void test1() { + String str = "{\"date\":\"-999999999-11-12\"}"; + { + Bean1 bean = JSON.parseObject(str, Bean1.class); + assertEquals(str, JSON.toJSONString(bean)); + } + { + Bean1 bean = JSON.parseObject(str.getBytes(StandardCharsets.UTF_8), Bean1.class); + assertEquals(str, JSON.toJSONString(bean)); + } + { + Bean1 bean = JSON.parseObject(str.toCharArray(), Bean1.class); + assertEquals(str, JSON.toJSONString(bean)); + } + } + + static class Bean1 { + public LocalDate date; + } +}