Skip to content

Commit

Permalink
improved java.sql.Time parse support
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed Jul 28, 2023
1 parent e738baf commit 29848f5
Show file tree
Hide file tree
Showing 12 changed files with 286 additions and 57 deletions.
4 changes: 4 additions & 0 deletions core/src/main/java/com/alibaba/fastjson2/JSONReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -1527,6 +1527,8 @@ public LocalTime readLocalTime() {
return readLocalTime5();
case 8:
return readLocalTime8();
case 9:
return readLocalTime9();
case 10:
return readLocalTime10();
case 11:
Expand Down Expand Up @@ -1782,6 +1784,8 @@ public final long readMillisFromString() {

protected abstract LocalTime readLocalTime8();

protected abstract LocalTime readLocalTime9();

protected abstract LocalTime readLocalTime10();

protected abstract LocalTime readLocalTime11();
Expand Down
12 changes: 12 additions & 0 deletions core/src/main/java/com/alibaba/fastjson2/JSONReaderJSONB.java
Original file line number Diff line number Diff line change
Expand Up @@ -5174,6 +5174,18 @@ protected LocalTime readLocalTime8() {
return time;
}

@Override
protected LocalTime readLocalTime9() {
LocalTime time;
if (bytes[offset] != BC_STR_ASCII_FIX_MIN + 8
|| (time = DateUtils.parseLocalTime8(bytes, offset + 1)) == null
) {
throw new JSONException("date only support string input");
}
offset += 10;
return time;
}

@Override
protected LocalTime readLocalTime12() {
LocalTime time;
Expand Down
20 changes: 20 additions & 0 deletions core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java
Original file line number Diff line number Diff line change
Expand Up @@ -5532,6 +5532,26 @@ protected final LocalTime readLocalTime8() {
return time;
}

@Override
protected final LocalTime readLocalTime9() {
if (ch != '"' && ch != '\'') {
throw new JSONException("localTime only support string input");
}

LocalTime time = DateUtils.parseLocalTime8(chars, offset);
if (time == null) {
return null;
}

offset += 10;
next();
if (comma = (ch == ',')) {
next();
}

return time;
}

@Override
public final LocalDate readLocalDate8() {
if (ch != '"' && ch != '\'') {
Expand Down
22 changes: 21 additions & 1 deletion core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java
Original file line number Diff line number Diff line change
Expand Up @@ -7281,7 +7281,7 @@ protected final LocalTime readLocalTime5() {

@Override
protected final LocalTime readLocalTime8() {
if (!isString()) {
if (ch != '"' && ch != '\'') {
throw new JSONException("localTime only support string input");
}

Expand All @@ -7299,6 +7299,26 @@ protected final LocalTime readLocalTime8() {
return time;
}

@Override
protected final LocalTime readLocalTime9() {
if (ch != '"' && ch != '\'') {
throw new JSONException("localTime only support string input");
}

LocalTime time = DateUtils.parseLocalTime8(bytes, offset);
if (time == null) {
return null;
}

offset += 10;
next();
if (comma = (ch == ',')) {
next();
}

return time;
}

@Override
protected final LocalTime readLocalTime10() {
if (!isString()) {
Expand Down
10 changes: 9 additions & 1 deletion core/src/main/java/com/alibaba/fastjson2/TypeReference.java
Original file line number Diff line number Diff line change
Expand Up @@ -329,11 +329,19 @@ public static Type arrayType(Class<?> elementType) {

public static Type mapType(
Class<? extends Map> mapClass,
Class<?> keyClass, Class<?> valueClass
Class<?> keyClass,
Class<?> valueClass
) {
return new ParameterizedTypeImpl(mapClass, keyClass, valueClass);
}

public static Type mapType(
Class<?> keyClass,
Type valueType
) {
return new ParameterizedTypeImpl(Map.class, keyClass, valueType);
}

public static Type parametricType(Class<?> parametrized, Class<?>... parameterClasses) {
return new ParameterizedTypeImpl(parametrized, parameterClasses);
}
Expand Down
76 changes: 28 additions & 48 deletions core/src/main/java/com/alibaba/fastjson2/util/DateUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class DateUtils {
public static final ZoneRules SHANGHAI_ZONE_RULES = SHANGHAI_ZONE_ID.getRules();
public static final String OFFSET_8_ZONE_ID_NAME = "+08:00";
public static final ZoneId OFFSET_8_ZONE_ID = ZoneId.of(OFFSET_8_ZONE_ID_NAME);
public static final LocalDate LOCAL_DATE_19700101 = LocalDate.of(1970, 1, 1);

static DateTimeFormatter DATE_TIME_FORMATTER_34;
static DateTimeFormatter DATE_TIME_FORMATTER_COOKIE;
Expand Down Expand Up @@ -240,6 +241,10 @@ public static LocalDateTime parseLocalDateTime(char[] str, int off, int len) {
String input = new String(str, off, len);
throw new DateTimeParseException("illegal input " + input, input, 0);
case 8: {
if (str[2] == ':' && str[5] == ':') {
LocalTime localTime = parseLocalTime8(str, off);
return LocalDateTime.of(LOCAL_DATE_19700101, localTime);
}
LocalDate localDate = parseLocalDate8(str, off);
if (localDate == null) {
return null;
Expand Down Expand Up @@ -375,55 +380,16 @@ public static LocalTime parseLocalTime8(byte[] bytes, int off) {
return null;
}

byte c0 = bytes[off];
byte c1 = bytes[off + 1];
byte c2 = bytes[off + 2];
byte c3 = bytes[off + 3];
byte c4 = bytes[off + 4];
byte c5 = bytes[off + 5];
byte c6 = bytes[off + 6];
byte c7 = bytes[off + 7];

byte h0, h1, i0, i1, s0, s1;
if (c2 == ':' && c5 == ':') {
h0 = c0;
h1 = c1;
i0 = c3;
i1 = c4;
s0 = c6;
s1 = c7;
} else {
return null;
}
char c0 = (char) bytes[off];
char c1 = (char) bytes[off + 1];
char c2 = (char) bytes[off + 2];
char c3 = (char) bytes[off + 3];
char c4 = (char) bytes[off + 4];
char c5 = (char) bytes[off + 5];
char c6 = (char) bytes[off + 6];
char c7 = (char) bytes[off + 7];

int hour;
if (h0 >= '0' && h0 <= '9'
&& h1 >= '0' && h1 <= '9'
) {
hour = (h0 - '0') * 10 + (h1 - '0');
} else {
return null;
}

int minute;
if (i0 >= '0' && i0 <= '9'
&& i1 >= '0' && i1 <= '9'
) {
minute = (i0 - '0') * 10 + (i1 - '0');
} else {
return null;
}

int second;
if (s0 >= '0' && s0 <= '9'
&& s1 >= '0' && s1 <= '9'
) {
second = (s0 - '0') * 10 + (s1 - '0');
} else {
return null;
}

return LocalTime.of(hour, minute, second);
return parseLocalTime(c0, c1, c2, c3, c4, c5, c6, c7);
}

public static LocalTime parseLocalTime8(char[] bytes, int off) {
Expand All @@ -440,6 +406,19 @@ public static LocalTime parseLocalTime8(char[] bytes, int off) {
char c6 = bytes[off + 6];
char c7 = bytes[off + 7];

return parseLocalTime(c0, c1, c2, c3, c4, c5, c6, c7);
}

public static LocalTime parseLocalTime(
char c0,
char c1,
char c2,
char c3,
char c4,
char c5,
char c6,
char c7
) {
char h0, h1, i0, i1, s0, s1;
if (c2 == ':' && c5 == ':') {
h0 = c0;
Expand Down Expand Up @@ -1432,6 +1411,7 @@ public static long parseMillis(char[] chars, int off, int len, ZoneId zoneId) {
} else {
char last = chars[len - 1];
if (last == 'Z') {
len--;
zoneId = UTC;
}
LocalDateTime ldt = DateUtils.parseLocalDateTime(chars, off, len);
Expand Down
30 changes: 23 additions & 7 deletions core/src/main/java/com/alibaba/fastjson2/util/JdbcSupport.java
Original file line number Diff line number Diff line change
Expand Up @@ -258,14 +258,30 @@ public Object readObject(JSONReader jsonReader, Type fieldType, Object fieldName
} else {
String str = jsonReader.readString();
if ("0000-00-00".equals(str) || "0000-00-00 00:00:00".equals(str)) {
return function.apply(0);
}

if (str.isEmpty() || "null".equals(str)) {
return null;
millis = 0;
} else {
if (str.length() == 9 && str.charAt(8) == 'Z') {
LocalTime localTime = DateUtils.parseLocalTime(
str.charAt(0),
str.charAt(1),
str.charAt(2),
str.charAt(3),
str.charAt(4),
str.charAt(5),
str.charAt(6),
str.charAt(7)
);
millis = LocalDateTime.of(DateUtils.LOCAL_DATE_19700101, localTime)
.atZone(DateUtils.DEFAULT_ZONE_ID)
.toInstant()
.toEpochMilli();
} else {
if (str.isEmpty() || "null".equals(str)) {
return null;
}
return functionValueOf.apply(str);
}
}

return functionValueOf.apply(str);
}

return function.apply(millis);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ default void write(JSONWriter jsonWriter, Object object) {
write(jsonWriter, object, null, null, 0);
}

default String toJSONString(T object, JSONWriter.Feature... features) {
JSONWriter jsonWriter = JSONWriter.of(features);
write(jsonWriter, object, null, null, 0);
return jsonWriter.toString();
}

void write(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features);

default void writeWithFilter(JSONWriter jsonWriter, Object object) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,12 @@ public void setTime(LocalTime time) {
this.time = time;
}
}

@Test
public void test5() throws Exception {
LocalTime time = JSON.parseObject("\"12:12:43Z\"", LocalTime.class);
String str = JSON.toJSONString(time);
LocalTime time1 = JSON.parseObject(str, LocalTime.class);
assertEquals(time, time1);
}
}
18 changes: 18 additions & 0 deletions core/src/test/java/com/alibaba/fastjson2/date/SqlTimeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import com.alibaba.fastjson2.annotation.JSONField;
import org.junit.jupiter.api.Test;

import java.sql.Time;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class SqlTimeTest {
Expand Down Expand Up @@ -83,4 +85,20 @@ public static class Student4 {
@JSONField(format = "unixtime")
public java.sql.Time birthday;
}

@Test
public void test5() throws Exception {
Time time = JSON.parseObject("\"12:12:43Z\"", Time.class);
String str = JSON.toJSONString(time);
Time time1 = JSON.parseObject(str, Time.class);
assertEquals(time, time1);
}

@Test
public void test6() throws Exception {
Time time = JSON.parseObject("\"12:12:43\"", Time.class);
String str = JSON.toJSONString(time);
Time time1 = JSON.parseObject(str, Time.class);
assertEquals(time, time1);
}
}
13 changes: 13 additions & 0 deletions extension/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,19 @@
<artifactId>commons-io</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-core</artifactId>
<version>1.17.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-json</artifactId>
<version>1.17.0</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Loading

0 comments on commit 29848f5

Please sign in to comment.