optimize readOffsetDateTime

This commit is contained in:
wenshao 2025-02-23 11:00:58 +08:00
parent 5ec9959bb6
commit 0f5ddf1761
5 changed files with 118 additions and 65 deletions

View File

@ -13,7 +13,7 @@ public class ClientsParseUTF8BytesTest {
}
long millis = System.currentTimeMillis() - start;
System.out.println("fastjson2 millis : " + millis);
// zulu17.40.19 : 2417 2236 2139 1985 2174 2065
// zulu17.40.19 : 2417 2236 2139 1985 2174 2065 1974
// oracle-jdk-17.0.6 :
// oracle-jdk-17.0.6_vec :
// oracle-jdk-17.0.6_reflect : 3566 3513 3476

View File

@ -4542,10 +4542,10 @@ final class JSONReaderUTF16
public final OffsetDateTime readOffsetDateTime() {
final char[] chars = this.chars;
final int offset = this.offset;
if (this.ch == '"' || this.ch == '\'') {
int offset = this.offset, end = this.end;
char quote = this.ch;
if (quote == '"' || quote == '\'') {
if (!context.formatComplex) {
char quote = this.ch;
char c10;
int off21 = offset + 19;
if (off21 < chars.length
@ -4567,35 +4567,49 @@ final class JSONReaderUTF16
return zdt == null ? null : zdt.toOffsetDateTime();
}
LocalDate localDate;
try {
localDate = year == 0 && month == 0 && dom == 0
? null
: LocalDate.of(year, month, dom);
} catch (DateTimeException ex) {
throw new JSONException(info("read date error"), ex);
int nanos = 0, nanoSize = 0;
offset += 19;
char ch = chars[offset++];
if (ch == '.') {
ch = chars[offset++];
}
int nanoSize = -1;
int len = 0;
for (int start = offset + 19, i = start, end = offset + 31; i < end && i < this.end && i < chars.length; ++i) {
if (chars[i] == quote && chars[i - 1] == 'Z') {
nanoSize = i - start - 2;
len = i - offset + 1;
while (ch >= '0' && ch <= '9') {
nanos = nanos * 10 + (ch - '0');
nanoSize++;
if (offset < end) {
ch = chars[offset++];
} else {
break;
}
}
if (nanoSize != -1 || len == 21) {
int nano = nanoSize <= 0 ? 0 : DateUtils.readNanos(chars, nanoSize, offset + 20);
LocalTime localTime = LocalTime.of(hour, minute, second, nano);
LocalDateTime ldt = LocalDateTime.of(localDate, localTime);
OffsetDateTime oft = OffsetDateTime.of(ldt, ZoneOffset.UTC);
this.offset += len;
next();
if (comma = (this.ch == ',')) {
next();
if (nanoSize != 0) {
nanos = DateUtils.nanos(nanos, nanoSize);
}
ZoneOffset zoneOffset = ZoneOffset.UTC;
if (ch == 'Z') {
ch = chars[offset++];
} else if (ch != quote) {
int quoteIndex = IOUtils.indexOfChar(chars, '"', offset, end);
if (quoteIndex != -1) {
zoneOffset = DateUtils.zoneOffset(chars, offset - 1, quoteIndex - offset + 1);
offset = quoteIndex + 1;
ch = quote;
}
return oft;
}
if (ch == quote) {
ch = offset >= end ? EOI : chars[offset++];
while (ch == '\0' || (ch <= ' ' && ((1L << ch) & SPACE) != 0)) {
ch = offset == end ? EOI : chars[offset++];
}
if (comma = (ch == ',')) {
ch = offset == end ? EOI : chars[offset++];
while (ch <= ' ' && ((1L << ch) & SPACE) != 0) {
ch = offset == end ? EOI : chars[offset++];
}
}
this.offset = offset;
this.ch = ch;
return OffsetDateTime.of(year, month, dom, hour, minute, second, nanos, zoneOffset);
}
}
}

View File

@ -5625,7 +5625,7 @@ class JSONReaderUTF8
public final OffsetDateTime readOffsetDateTime() {
final byte[] bytes = this.bytes;
final int offset = this.offset;
int offset = this.offset, end = this.end;
char quote = this.ch;
if (quote == '"' || quote == '\'') {
if (!this.context.formatComplex) {
@ -5640,42 +5640,60 @@ class JSONReaderUTF8
&& ((c10 = bytes[offset + 10]) == ' ' || c10 == 'T')
&& ((hms = hms(bytes, offset + 11))) != -1L
) {
int year = yy + ((int) ymd & 0xFF);
int month = (int) (ymd >> 24) & 0xFF;
int dom = (int) (ymd >> 48) & 0xFF;
int hour = (int) hms & 0xFF;
int minute = (int) (hms >> 24) & 0xFF;
int second = (int) (hms >> 48) & 0xFF;
LocalDate localDate;
try {
localDate = year == 0 && month == 0 && dom == 0
? null
: LocalDate.of(year, month, dom);
} catch (DateTimeException ex) {
throw new JSONException(info("read date error"), ex);
int nanos = 0, nanoSize = 0;
offset += 19;
int ch = bytes[offset++];
if (ch == '.') {
ch = bytes[offset++];
}
int nanoSize = -1;
int len = 0;
for (int start = offset + 19, i = start, end = offset + 31; i < end && i < this.end && i < bytes.length; ++i) {
if (bytes[i] == quote && bytes[i - 1] == 'Z') {
nanoSize = i - start - 2;
len = i - offset + 1;
while (ch >= '0' && ch <= '9') {
nanos = nanos * 10 + (ch - '0');
nanoSize++;
if (offset < end) {
ch = bytes[offset++];
} else {
break;
}
}
if (nanoSize != -1 || len == 21) {
int nano = nanoSize <= 0 ? 0 : DateUtils.readNanos(bytes, nanoSize, offset + 20);
LocalTime localTime = LocalTime.of(hour, minute, second, nano);
LocalDateTime ldt = LocalDateTime.of(localDate, localTime);
OffsetDateTime oft = OffsetDateTime.of(ldt, ZoneOffset.UTC);
this.offset += len;
next();
if (comma = (this.ch == ',')) {
next();
if (nanoSize != 0) {
nanos = DateUtils.nanos(nanos, nanoSize);
}
ZoneOffset zoneOffset = ZoneOffset.UTC;
if (ch == 'Z') {
ch = bytes[offset++];
} else if (ch != quote) {
int quoteIndex = IOUtils.indexOfChar(bytes, '"', offset, end);
if (quoteIndex != -1) {
zoneOffset = DateUtils.zoneOffset(bytes, offset - 1, quoteIndex - offset + 1);
offset = quoteIndex + 1;
ch = quote;
}
return oft;
}
if (ch == quote) {
ch = offset >= end ? EOI : bytes[offset++];
while (ch == '\0' || (ch <= ' ' && ((1L << ch) & SPACE) != 0)) {
ch = offset == end ? EOI : bytes[offset++];
}
if (comma = (ch == ',')) {
ch = offset == end ? EOI : (char) bytes[offset++];
while (ch <= ' ' && ((1L << ch) & SPACE) != 0) {
ch = offset == end ? EOI : bytes[offset++];
}
}
if (ch < 0) {
char_utf8(ch, offset);
}
this.offset = offset;
this.ch = (char) ch;
return OffsetDateTime.of(
yy + ((int) ymd & 0xFF),
(int) (ymd >> 24) & 0xFF,
(int) (ymd >> 48) & 0xFF,
(int) hms & 0xFF,
(int) (hms >> 24) & 0xFF,
(int) (hms >> 48) & 0xFF,
nanos,
zoneOffset);
}
}
}

View File

@ -9008,6 +9008,18 @@ public class DateUtils {
return v;
}
public static ZoneOffset zoneOffset(byte[] bytes, int start, int len) {
return ZoneOffset.of(new String(bytes, start, len));
}
public static ZoneOffset zoneOffset(char[] bytes, int start, int len) {
return ZoneOffset.of(new String(bytes, start, len));
}
public static int nanos(int value, int nanoSize) {
return value * POWERS[(9 - nanoSize) & 0xF];
}
private static final int[] POWERS = {
1,
10,

View File

@ -1499,7 +1499,7 @@ public class IOUtils {
i += 8;
address += 8;
}
return indexOfChar0(value, quote, i, max);
return indexOfChar(value, quote, i, max);
}
public static int indexOfDoubleQuote(byte[] value, int fromIndex, int max) {
@ -1521,7 +1521,7 @@ public class IOUtils {
i += 8;
address += 8;
}
return indexOfChar0(value, '"', i, max);
return indexOfChar(value, '"', i, max);
}
public static int indexOfLineSeparator(byte[] value, int fromIndex, int max) {
@ -1543,7 +1543,7 @@ public class IOUtils {
i += 8;
address += 8;
}
return indexOfChar0(value, '\n', i, max);
return indexOfChar(value, '\n', i, max);
}
public static int indexOfSlash(byte[] value, int fromIndex, int max) {
@ -1565,10 +1565,19 @@ public class IOUtils {
i += 8;
address += 8;
}
return indexOfChar0(value, '\\', i, max);
return indexOfChar(value, '\\', i, max);
}
private static int indexOfChar0(byte[] value, int ch, int fromIndex, int max) {
public static int indexOfChar(byte[] value, int ch, int fromIndex, int max) {
for (int i = fromIndex; i < max; i++) {
if (value[i] == ch) {
return i;
}
}
return -1;
}
public static int indexOfChar(char[] value, int ch, int fromIndex, int max) {
for (int i = fromIndex; i < max; i++) {
if (value[i] == ch) {
return i;