diff --git a/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/jjb/ClientsParseUTF8BytesTest.java b/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/jjb/ClientsParseUTF8BytesTest.java index 9ae0a7b170..cdcdd0b164 100644 --- a/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/jjb/ClientsParseUTF8BytesTest.java +++ b/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/jjb/ClientsParseUTF8BytesTest.java @@ -59,8 +59,8 @@ public static void jackson() throws Exception { } public static void main(String[] args) throws Exception { - wast(); -// fastjson2(); +// wast(); + fastjson2(); // dsljson(); // jackson(); } diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReader.java b/core/src/main/java/com/alibaba/fastjson2/JSONReader.java index da75aa9022..a490793f69 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONReader.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONReader.java @@ -4650,6 +4650,10 @@ final JSONException valueError() { return new JSONException(info("illegal value")); } + final JSONException error(String message) { + return new JSONException(info(message)); + } + final JSONException error(int offset, int ch) { throw new JSONValidException("error, offset " + offset + ", char " + (char) ch); } diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderASCII.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderASCII.java index 95be0ab627..ccc2d4c210 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderASCII.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderASCII.java @@ -1,6 +1,7 @@ package com.alibaba.fastjson2; import com.alibaba.fastjson2.util.Fnv; +import com.alibaba.fastjson2.util.IOUtils; import com.alibaba.fastjson2.util.JDKUtils; import com.alibaba.fastjson2.util.TypeUtils; @@ -1424,115 +1425,44 @@ public String readString() { int valueLength; boolean valueEscape = false; - _for: - { - int i = 0; - byte c0 = 0, c1 = 0, c2 = 0, c3; - - // vector optimize - boolean quoted = false; - int upperBound = offset + ((end - offset) & ~3); - while (offset < upperBound) { - c0 = bytes[offset]; - c1 = bytes[offset + 1]; - c2 = bytes[offset + 2]; - c3 = bytes[offset + 3]; - if (c0 == slash || c1 == slash || c2 == slash || c3 == slash) { - break; - } - if (c0 == quote || c1 == quote || c2 == quote || c3 == quote) { - quoted = true; - break; - } - offset += 4; - i += 4; - } + int index = IOUtils.indexOfChar(bytes, quote, offset, end); + if (index == -1) { + throw error("invalid escape character EOI"); + } + int slashIndex = IOUtils.indexOfChar(bytes, '\\', offset, index); + if (slashIndex == -1) { + valueLength = index - offset; + offset = index; + } else { + valueEscape = true; + valueLength = slashIndex - offset; + offset = slashIndex; - if (quoted) { - if (c0 == quote) { - // skip - } else if (c1 == quote) { - offset++; - i++; - } else if (c2 == quote) { - offset += 2; - i += 2; - } else { - offset += 3; - i += 3; + for (;;) { + if (offset >= end) { + throw error("invalid escape character EOI"); } - valueLength = i; - } else { - for (; ; ++i) { - if (offset >= end) { - throw new JSONException("invalid escape character EOI"); - } - byte c = bytes[offset]; - if (c == slash) { - valueEscape = true; - c = bytes[offset + 1]; - offset += (c == 'u' ? 6 : (c == 'x' ? 4 : 2)); - continue; - } + byte c = bytes[offset]; + if (c == slash) { + valueLength++; + c = bytes[offset + 1]; + offset += (c == 'u' ? 6 : (c == 'x' ? 4 : 2)); + continue; + } - if (c == quote) { - valueLength = i; - break _for; - } - offset++; + if (c == quote) { + break; } + offset++; + valueLength++; } } String str; if (valueEscape) { char[] buf = new char[valueLength]; - offset = start; - for (int i = 0; ; ++i) { - char c = (char) (bytes[offset] & 0xff); - if (c == '\\') { - c = (char) bytes[++offset]; - switch (c) { - case 'u': { - c = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]); - offset += 4; - break; - } - case 'x': { - c = char2(bytes[offset + 1], bytes[offset + 2]); - offset += 2; - break; - } - case '\\': - case '"': - break; - case 'b': - c = '\b'; - break; - case 't': - c = '\t'; - break; - case 'n': - c = '\n'; - break; - case 'f': - c = '\f'; - break; - case 'r': - c = '\r'; - break; - default: - c = char1(c); - break; - } - } else if (c == quote) { - break; - } - buf[i] = c; - offset++; - } - + offset = readEscaped(bytes, start, quote, buf); str = new String(buf); } else { if (this.str != null) { @@ -1573,4 +1503,51 @@ public String readString() { return readStringNotMatch(); } + + private int readEscaped(byte[] bytes, int offset, byte quote, char[] buf) { + for (int i = 0; ; ++i) { + char c = (char) (bytes[offset] & 0xff); + if (c == '\\') { + c = (char) bytes[++offset]; + switch (c) { + case 'u': { + c = char4(bytes[offset + 1], bytes[offset + 2], bytes[offset + 3], bytes[offset + 4]); + offset += 4; + break; + } + case 'x': { + c = char2(bytes[offset + 1], bytes[offset + 2]); + offset += 2; + break; + } + case '\\': + case '"': + break; + case 'b': + c = '\b'; + break; + case 't': + c = '\t'; + break; + case 'n': + c = '\n'; + break; + case 'f': + c = '\f'; + break; + case 'r': + c = '\r'; + break; + default: + c = char1(c); + break; + } + } else if (c == quote) { + break; + } + buf[i] = c; + offset++; + } + return offset; + } } diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java index 99019dad20..0edbe00d95 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java @@ -2,6 +2,7 @@ import com.alibaba.fastjson2.util.DateUtils; import com.alibaba.fastjson2.util.Fnv; +import com.alibaba.fastjson2.util.IOUtils; import com.alibaba.fastjson2.util.TypeUtils; import java.io.Closeable; @@ -5006,79 +5007,13 @@ public final OffsetDateTime readOffsetDateTime() { && chars[offset + 13] == ':' && chars[offset + 16] == ':' ) { - char y0 = chars[offset]; - char y1 = chars[offset + 1]; - char y2 = chars[offset + 2]; - char y3 = chars[offset + 3]; - char m0 = chars[offset + 5]; - char m1 = chars[offset + 6]; - char d0 = chars[offset + 8]; - char d1 = chars[offset + 9]; - char h0 = chars[offset + 11]; - char h1 = chars[offset + 12]; - char i0 = chars[offset + 14]; - char i1 = chars[offset + 15]; - char s0 = chars[offset + 17]; - char s1 = chars[offset + 18]; - - int year; - int month; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - ZonedDateTime zdt = readZonedDateTime(); - return zdt == null ? null : zdt.toOffsetDateTime(); - } - - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - ZonedDateTime zdt = readZonedDateTime(); - return zdt == null ? null : zdt.toOffsetDateTime(); - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - ZonedDateTime zdt = readZonedDateTime(); - return zdt == null ? null : zdt.toOffsetDateTime(); - } - - int hour; - if (h0 >= '0' && h0 <= '9' - && h1 >= '0' && h1 <= '9' - ) { - hour = (h0 - '0') * 10 + (h1 - '0'); - } else { - ZonedDateTime zdt = readZonedDateTime(); - return zdt == null ? null : zdt.toOffsetDateTime(); - } - - int minute; - if (i0 >= '0' && i0 <= '9' - && i1 >= '0' && i1 <= '9' - ) { - minute = (i0 - '0') * 10 + (i1 - '0'); - } else { - ZonedDateTime zdt = readZonedDateTime(); - return zdt == null ? null : zdt.toOffsetDateTime(); - } - - int second; - if (s0 >= '0' && s0 <= '9' - && s1 >= '0' && s1 <= '9' - ) { - second = (s0 - '0') * 10 + (s1 - '0'); - } else { + int year = IOUtils.digit4(chars, offset); + int month = IOUtils.digit2(chars, offset + 5); + int dom = IOUtils.digit2(chars, offset + 8); + int hour = IOUtils.digit2(chars, offset + 11); + int minute = IOUtils.digit2(chars, offset + 14); + int second = IOUtils.digit2(chars, offset + 17); + if ((year | month | dom | minute | second) < 0) { ZonedDateTime zdt = readZonedDateTime(); return zdt == null ? null : zdt.toOffsetDateTime(); } @@ -5108,7 +5043,7 @@ public final OffsetDateTime readOffsetDateTime() { OffsetDateTime oft = OffsetDateTime.of(ldt, ZoneOffset.UTC); this.offset += len; next(); - if (comma = (ch == ',')) { + if (comma = (this.ch == ',')) { next(); } return oft; diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java index 8dc73cb644..50a294868f 100644 --- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java +++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java @@ -3699,6 +3699,7 @@ public final long readInt64Value() { return getInt64Value(); } + int end = this.end; if (quote != 0) { ch = offset == end ? EOI : bytes[offset++]; } @@ -6106,79 +6107,13 @@ public final OffsetDateTime readOffsetDateTime() { && bytes[offset + 13] == ':' && bytes[offset + 16] == ':' ) { - byte y0 = bytes[offset]; - byte y1 = bytes[offset + 1]; - byte y2 = bytes[offset + 2]; - byte y3 = bytes[offset + 3]; - byte m0 = bytes[offset + 5]; - byte m1 = bytes[offset + 6]; - byte d0 = bytes[offset + 8]; - byte d1 = bytes[offset + 9]; - byte h0 = bytes[offset + 11]; - byte h1 = bytes[offset + 12]; - byte i0 = bytes[offset + 14]; - byte i1 = bytes[offset + 15]; - byte s0 = bytes[offset + 17]; - byte s1 = bytes[offset + 18]; - - int year; - int month; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - ZonedDateTime zdt = readZonedDateTime(); - return zdt == null ? null : zdt.toOffsetDateTime(); - } - - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - ZonedDateTime zdt = readZonedDateTime(); - return zdt == null ? null : zdt.toOffsetDateTime(); - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - ZonedDateTime zdt = readZonedDateTime(); - return zdt == null ? null : zdt.toOffsetDateTime(); - } - - int hour; - if (h0 >= '0' && h0 <= '9' - && h1 >= '0' && h1 <= '9' - ) { - hour = (h0 - '0') * 10 + (h1 - '0'); - } else { - ZonedDateTime zdt = readZonedDateTime(); - return zdt == null ? null : zdt.toOffsetDateTime(); - } - - int minute; - if (i0 >= '0' && i0 <= '9' - && i1 >= '0' && i1 <= '9' - ) { - minute = (i0 - '0') * 10 + (i1 - '0'); - } else { - ZonedDateTime zdt = readZonedDateTime(); - return zdt == null ? null : zdt.toOffsetDateTime(); - } - - int second; - if (s0 >= '0' && s0 <= '9' - && s1 >= '0' && s1 <= '9' - ) { - second = (s0 - '0') * 10 + (s1 - '0'); - } else { + int year = IOUtils.digit4(bytes, offset); + int month = IOUtils.digit2(bytes, offset + 5); + int dom = IOUtils.digit2(bytes, offset + 8); + int hour = IOUtils.digit2(bytes, offset + 11); + int minute = IOUtils.digit2(bytes, offset + 14); + int second = IOUtils.digit2(bytes, offset + 17); + if ((year | month | dom | minute | second) < 0) { ZonedDateTime zdt = readZonedDateTime(); return zdt == null ? null : zdt.toOffsetDateTime(); } @@ -7022,30 +6957,16 @@ public final UUID readUUID() { && bytes[offset + 18] == '-' && bytes[offset + 23] == '-' ) { - for (int i = 0; i < 8; i++) { - hi = (hi << 4) + UUID_VALUES[bytes[offset + i] - '0']; - } - for (int i = 9; i < 13; i++) { - hi = (hi << 4) + UUID_VALUES[bytes[offset + i] - '0']; - } - for (int i = 14; i < 18; i++) { - hi = (hi << 4) + UUID_VALUES[bytes[offset + i] - '0']; - } - - for (int i = 19; i < 23; i++) { - lo = (lo << 4) + UUID_VALUES[bytes[offset + i] - '0']; - } - for (int i = 24; i < 36; i++) { - lo = (lo << 4) + UUID_VALUES[bytes[offset + i] - '0']; - } + hi = (IOUtils.hexDigit8(bytes, offset) << 32) + + (((long) IOUtils.hexDigit4(bytes, offset + 9)) << 16) + + IOUtils.hexDigit4(bytes, offset + 14); + lo = (((long) IOUtils.hexDigit4(bytes, offset + 19)) << 48) + | (((long) IOUtils.hexDigit4(bytes, offset + 24)) << 32) + | IOUtils.hexDigit8(bytes, offset + 28); offset += 37; } else if (offset + 32 < bytes.length && bytes[offset + 32] == quote) { - for (int i = 0; i < 16; i++) { - hi = (hi << 4) + UUID_VALUES[bytes[offset + i] - '0']; - } - for (int i = 16; i < 32; i++) { - lo = (lo << 4) + UUID_VALUES[bytes[offset + i] - '0']; - } + hi = (IOUtils.hexDigit8(bytes, offset) << 32) | IOUtils.hexDigit8(bytes, offset + 8); + lo = (IOUtils.hexDigit8(bytes, offset + 16) << 32) | IOUtils.hexDigit8(bytes, offset + 24); offset += 33; } else { String str = readString(); 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 edcdf2139e..06d06ad845 100644 --- a/core/src/main/java/com/alibaba/fastjson2/util/DateUtils.java +++ b/core/src/main/java/com/alibaba/fastjson2/util/DateUtils.java @@ -293,410 +293,169 @@ public static LocalDateTime parseLocalDateTime(char[] str, int off, int len) { } } - public static LocalTime parseLocalTime5(byte[] bytes, int off) { - if (off + 5 > bytes.length) { + public static LocalTime parseLocalTime5(byte[] str, int off) { + if (off + 5 > str.length) { 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 h0, h1, i0, i1; + int hour, minute; int second = 0; - if (c2 == ':') { - h0 = c0; - h1 = c1; - i0 = c3; - i1 = c4; - } else if (c1 == ':' && c3 == ':') { - h0 = '0'; - h1 = c0; - i0 = '0'; - i1 = c2; - second = c4 - '0'; - } else { - return null; - } - - int hour; - if (h0 >= '0' && h0 <= '9' - && h1 >= '0' && h1 <= '9' - ) { - hour = (h0 - '0') * 10 + (h1 - '0'); + if (str[off + 2] == ':') { + hour = digit2(str, off); + minute = digit2(str, off + 3); + } else if (str[off + 1] == ':' && str[off + 3] == ':') { + hour = digit1(str, off); + minute = digit1(str, off + 2); + second = digit1(str, off + 4); } else { return null; } - int minute; - if (i0 >= '0' && i0 <= '9' - && i1 >= '0' && i1 <= '9' - ) { - minute = (i0 - '0') * 10 + (i1 - '0'); - } else { - return null; - } - - return LocalTime.of(hour, minute, second); + return localTime(hour, minute, second); } - public static LocalTime parseLocalTime5(char[] chars, int off) { - if (off + 5 > chars.length) { - return null; - } - - char c0 = chars[off]; - char c1 = chars[off + 1]; - char c2 = chars[off + 2]; - char c3 = chars[off + 3]; - char c4 = chars[off + 4]; - - char h0, h1, i0, i1; - int second = 0; - if (c2 == ':') { - h0 = c0; - h1 = c1; - i0 = c3; - i1 = c4; - } else if (c1 == ':' && c3 == ':') { - h0 = '0'; - h1 = c0; - i0 = '0'; - i1 = c2; - second = c4 - '0'; - } else { - return null; - } - - int hour; - if (h0 >= '0' && h0 <= '9' - && h1 >= '0' && h1 <= '9' - ) { - hour = (h0 - '0') * 10 + (h1 - '0'); - } else { + public static LocalTime parseLocalTime5(char[] str, int off) { + if (off + 5 > str.length) { return null; } - int minute; - if (i0 >= '0' && i0 <= '9' - && i1 >= '0' && i1 <= '9' - ) { - minute = (i0 - '0') * 10 + (i1 - '0'); + int hour, minute, second = 0; + if (str[off + 2] == ':') { + hour = digit2(str, off); + minute = digit2(str, off + 3); + } else if (str[off + 1] == ':' && str[off + 3] == ':') { + hour = digit1(str, off); + minute = digit1(str, off + 2); + second = digit1(str, off + 4); } else { return null; } - return LocalTime.of(hour, minute, second); + return localTime(hour, minute, second); } - public static LocalTime parseLocalTime6(byte[] bytes, int off) { - if (off + 5 > bytes.length) { + public static LocalTime parseLocalTime6(byte[] str, int off) { + if (off + 5 > str.length) { 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 c1 = str[off + 1]; + byte c4 = str[off + 4]; - byte h0, h1, i0, i1, s0, s1; - if (c2 == ':' && c4 == ':') { - h0 = c0; - h1 = c1; - i0 = '0'; - i1 = c3; - s0 = '0'; - s1 = c5; + int hour, minute, second; + if (str[off + 2] == ':' && c4 == ':') { + hour = digit2(str, off); + minute = digit1(str, off + 3); + second = digit1(str, off + 5); } else if (c1 == ':' && c4 == ':') { - h0 = '0'; - h1 = c0; - i0 = c2; - i1 = c3; - s0 = '0'; - s1 = c5; - } else if (c1 == ':' && c3 == ':') { - h0 = '0'; - h1 = c0; - i0 = '0'; - i1 = c2; - s0 = c4; - s1 = c5; - } else { - return null; - } - - 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'); + hour = digit1(str, off); + minute = digit2(str, off + 2); + second = digit1(str, off + 5); + } else if (c1 == ':' && str[off + 3] == ':') { + hour = digit1(str, off); + minute = digit1(str, off + 2); + second = digit2(str, off + 4); } else { return null; } - return LocalTime.of(hour, minute, second); + return localTime(hour, minute, second); } - public static LocalTime parseLocalTime6(char[] chars, int off) { - if (off + 5 > chars.length) { + public static LocalTime parseLocalTime6(char[] str, int off) { + if (off + 5 > str.length) { return null; } - char c0 = chars[off]; - char c1 = chars[off + 1]; - char c2 = chars[off + 2]; - char c3 = chars[off + 3]; - char c4 = chars[off + 4]; - char c5 = chars[off + 5]; + char c1 = str[off + 1]; + char c4 = str[off + 4]; - char h0, h1, i0, i1, s0, s1; - if (c2 == ':' && c4 == ':') { - h0 = c0; - h1 = c1; - i0 = '0'; - i1 = c3; - s0 = '0'; - s1 = c5; + int hour, minute, second; + if (str[off + 2] == ':' && c4 == ':') { + hour = digit2(str, off); + minute = digit1(str, off + 3); + second = digit1(str, off + 5); } else if (c1 == ':' && c4 == ':') { - h0 = '0'; - h1 = c0; - i0 = c2; - i1 = c3; - s0 = '0'; - s1 = c5; - } else if (c1 == ':' && c3 == ':') { - h0 = '0'; - h1 = c0; - i0 = '0'; - i1 = c2; - s0 = c4; - s1 = c5; - } else { - return null; - } - - 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'); + hour = digit1(str, off); + minute = digit2(str, off + 2); + second = digit1(str, off + 5); + } else if (c1 == ':' && str[off + 3] == ':') { + hour = digit1(str, off); + minute = digit1(str, off + 2); + second = digit2(str, off + 4); } else { return null; } - return LocalTime.of(hour, minute, second); + return localTime(hour, minute, second); } - public static LocalTime parseLocalTime7(byte[] bytes, int off) { - if (off + 5 > bytes.length) { + public static LocalTime parseLocalTime7(byte[] str, int off) { + if (off + 5 > str.length) { 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 c2 = str[off + 2]; + byte c4 = str[off + 4]; - byte h0, h1, i0, i1, s0, s1; - if (c1 == ':' && c4 == ':') { - h0 = '0'; - h1 = c0; - i0 = c2; - i1 = c3; - s0 = c5; - s1 = c6; + int hour, minute, second; + if (str[off + 1] == ':' && c4 == ':') { + hour = digit1(str, off); + minute = digit2(str, off + 2); + second = digit2(str, off + 5); } else if (c2 == ':' && c4 == ':') { - h0 = c0; - h1 = c1; - i0 = '0'; - i1 = c3; - s0 = c5; - s1 = c6; - } else if (c2 == ':' && c5 == ':') { - h0 = c0; - h1 = c1; - i0 = c3; - i1 = c4; - s0 = '0'; - s1 = c6; - } else { - return null; - } - - 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'); + hour = digit2(str, off); + minute = digit1(str, off + 3); + second = digit2(str, off + 5); + } else if (c2 == ':' && str[off + 5] == ':') { + hour = digit2(str, off); + minute = digit2(str, off + 3); + second = digit1(str, off + 6); } else { return null; } - return LocalTime.of(hour, minute, second); + return localTime(hour, minute, second); } - public static LocalTime parseLocalTime7(char[] chars, int off) { - if (off + 5 > chars.length) { + public static LocalTime parseLocalTime7(char[] str, int off) { + if (off + 5 > str.length) { return null; } - char c0 = chars[off]; - char c1 = chars[off + 1]; - char c2 = chars[off + 2]; - char c3 = chars[off + 3]; - char c4 = chars[off + 4]; - char c5 = chars[off + 5]; - char c6 = chars[off + 6]; + char c2 = str[off + 2]; + char c4 = str[off + 4]; - char h0, h1, i0, i1, s0, s1; - if (c1 == ':' && c4 == ':') { - h0 = '0'; - h1 = c0; - i0 = c2; - i1 = c3; - s0 = c5; - s1 = c6; + int hour, minute, second; + if (str[off + 1] == ':' && c4 == ':') { + hour = digit1(str, off); + minute = digit2(str, off + 2); + second = digit2(str, off + 5); } else if (c2 == ':' && c4 == ':') { - h0 = c0; - h1 = c1; - i0 = '0'; - i1 = c3; - s0 = c5; - s1 = c6; - } else if (c2 == ':' && c5 == ':') { - h0 = c0; - h1 = c1; - i0 = c3; - i1 = c4; - s0 = '0'; - s1 = c6; - } else { - return null; - } - - 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'); + hour = digit2(str, off); + minute = digit1(str, off + 3); + second = digit2(str, off + 5); + } else if (c2 == ':' && str[off + 5] == ':') { + hour = digit2(str, off); + minute = digit2(str, off + 3); + second = digit1(str, off + 6); } else { return null; } - return LocalTime.of(hour, minute, second); + return localTime(hour, minute, second); } public static LocalTime parseLocalTime8(byte[] bytes, int off) { - if (off + 8 > bytes.length) { - 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]; - - return parseLocalTime(c0, c1, c2, c3, c4, c5, c6, c7); + return off + 8 > bytes.length || bytes[off + 2] != ':' || bytes[off + 5] != ':' + ? null + : localTime(digit2(bytes, off), digit2(bytes, off + 3), digit2(bytes, off + 6)); } public static LocalTime parseLocalTime8(char[] bytes, int off) { - if (off + 8 > bytes.length) { - return null; - } - - char c0 = bytes[off]; - char c1 = bytes[off + 1]; - char c2 = bytes[off + 2]; - char c3 = bytes[off + 3]; - char c4 = bytes[off + 4]; - char c5 = bytes[off + 5]; - char c6 = bytes[off + 6]; - char c7 = bytes[off + 7]; - - return parseLocalTime(c0, c1, c2, c3, c4, c5, c6, c7); + return off + 8 > bytes.length || bytes[off + 2] != ':' || bytes[off + 5] != ':' + ? null + : localTime(digit2(bytes, off), digit2(bytes, off + 3), digit2(bytes, off + 6)); } public static LocalTime parseLocalTime( @@ -751,3889 +510,1383 @@ public static LocalTime parseLocalTime( return LocalTime.of(hour, minute, second); } - public static LocalTime parseLocalTime10(byte[] bytes, int off) { - if (off + 10 > bytes.length) { + public static LocalTime parseLocalTime10(byte[] str, int off) { + if (off + 10 > str.length || str[off + 2] != ':' || str[off + 5] != ':' || str[off + 8] != '.') { return null; + } else { + int hour = digit2(str, off); + int minute = digit2(str, off + 3); + int second = digit2(str, off + 6); + int millis = digit1(str, off + 9); + if (millis > 0) { + millis *= 100000000; + } + return ((hour | minute | second | minute) < 0) + ? null + : LocalTime.of(hour, minute, second, millis); } + } - 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 c8 = bytes[off + 8]; - byte c9 = bytes[off + 9]; - - byte h0, h1, i0, i1, s0, s1, m0; - if (c2 == ':' && c5 == ':' && c8 == '.') { - h0 = c0; - h1 = c1; - i0 = c3; - i1 = c4; - s0 = c6; - s1 = c7; - m0 = c9; - } else { + public static LocalTime parseLocalTime10(char[] str, int off) { + if (off + 10 > str.length || str[off + 2] != ':' || str[off + 5] != ':' || str[off + 8] != '.') { return null; + } else { + int hour = digit2(str, off); + int minute = digit2(str, off + 3); + int second = digit2(str, off + 6); + int millis = digit1(str, off + 9); + if (millis > 0) { + millis *= 100000000; + } + return ((hour | minute | second | minute) < 0) + ? null + : LocalTime.of(hour, minute, second, millis); } + } - int hour; - if (h0 >= '0' && h0 <= '9' - && h1 >= '0' && h1 <= '9' - ) { - hour = (h0 - '0') * 10 + (h1 - '0'); - } else { + public static LocalTime parseLocalTime11(byte[] str, int off) { + if (off + 11 > str.length || str[off + 2] != ':' || str[off + 5] != ':' || str[off + 8] != '.') { return null; + } else { + int hour = digit2(str, off); + int minute = digit2(str, off + 3); + int second = digit2(str, off + 6); + int millis = digit2(str, off + 9); + if (millis > 0) { + millis *= 10000000; + } + return ((hour | minute | second | minute) < 0) + ? null + : LocalTime.of(hour, minute, second, millis); } + } - int minute; - if (i0 >= '0' && i0 <= '9' - && i1 >= '0' && i1 <= '9' - ) { - minute = (i0 - '0') * 10 + (i1 - '0'); - } else { + public static LocalTime parseLocalTime11(char[] str, int off) { + if (off + 11 > str.length || str[off + 2] != ':' || str[off + 5] != ':' || str[off + 8] != '.') { return null; + } else { + int hour = digit2(str, off); + int minute = digit2(str, off + 3); + int second = digit2(str, off + 6); + int millis = digit2(str, off + 9); + if (millis > 0) { + millis *= 10000000; + } + return ((hour | minute | second | minute) < 0) + ? null + : LocalTime.of(hour, minute, second, millis); } + } - int second; - if (s0 >= '0' && s0 <= '9' - && s1 >= '0' && s1 <= '9' - ) { - second = (s0 - '0') * 10 + (s1 - '0'); - } else { + public static LocalTime parseLocalTime12(byte[] str, int off) { + if (off + 12 > str.length || str[off + 2] != ':' || str[off + 5] != ':' || str[off + 8] != '.') { return null; - } - - int millis; - if (m0 >= '0' && m0 <= '9') { - millis = (m0 - '0') * 100; - millis *= 1000_000; } else { - return null; + int hour = digit2(str, off); + int minute = digit2(str, off + 3); + int second = digit2(str, off + 6); + int millis = digit3(str, off + 9); + if (millis > 0) { + millis *= 1000000; + } + return ((hour | minute | second | minute) < 0) + ? null + : LocalTime.of(hour, minute, second, millis); } - - return LocalTime.of(hour, minute, second, millis); } - public static LocalTime parseLocalTime10(char[] bytes, int off) { - if (off + 10 > bytes.length) { - return null; - } - - char c0 = bytes[off]; - char c1 = bytes[off + 1]; - char c2 = bytes[off + 2]; - char c3 = bytes[off + 3]; - char c4 = bytes[off + 4]; - char c5 = bytes[off + 5]; - char c6 = bytes[off + 6]; - char c7 = bytes[off + 7]; - char c8 = bytes[off + 8]; - char c9 = bytes[off + 9]; - - char h0, h1, i0, i1, s0, s1, m0; - if (c2 == ':' && c5 == ':' && c8 == '.') { - h0 = c0; - h1 = c1; - i0 = c3; - i1 = c4; - s0 = c6; - s1 = c7; - m0 = c9; - } else { - return null; - } - - int hour; - if (h0 >= '0' && h0 <= '9' - && h1 >= '0' && h1 <= '9' - ) { - hour = (h0 - '0') * 10 + (h1 - '0'); - } else { + public static LocalTime parseLocalTime12(char[] str, int off) { + if (off + 12 > str.length || str[off + 2] != ':' || str[off + 5] != ':' || str[off + 8] != '.') { return null; - } - - int minute; - if (i0 >= '0' && i0 <= '9' - && i1 >= '0' && i1 <= '9' - ) { - minute = (i0 - '0') * 10 + (i1 - '0'); } else { - return null; + int hour = digit2(str, off); + int minute = digit2(str, off + 3); + int second = digit2(str, off + 6); + int millis = digit3(str, off + 9); + if (millis > 0) { + millis *= 1000000; + } + return ((hour | minute | second | minute) < 0) + ? null + : LocalTime.of(hour, minute, second, millis); } + } - int second; - if (s0 >= '0' && s0 <= '9' - && s1 >= '0' && s1 <= '9' - ) { - second = (s0 - '0') * 10 + (s1 - '0'); - } else { + public static LocalTime parseLocalTime18(byte[] str, int off) { + if (off + 18 > str.length || str[off + 2] != ':' || str[off + 5] != ':' || str[off + 8] != '.') { return null; } + int hour = digit2(str, off); + int minute = digit2(str, off + 3); + int second = digit2(str, off + 6); + int nanos = readNanos(str, 9, off + 9); + return (hour | minute | second | nanos) < 0 + ? null + : LocalTime.of(hour, minute, second, nanos); + } - int millis; - if (m0 >= '0' && m0 <= '9') { - millis = (m0 - '0') * 100; - millis *= 1000_000; - } else { + public static LocalTime parseLocalTime18(char[] str, int off) { + if (off + 18 > str.length || str[off + 2] != ':' || str[off + 5] != ':' || str[off + 8] != '.') { return null; } - - return LocalTime.of(hour, minute, second, millis); + int hour = digit2(str, off); + int minute = digit2(str, off + 3); + int second = digit2(str, off + 6); + int nanos = readNanos(str, 9, off + 9); + return (hour | minute | second | nanos) < 0 + ? null + : LocalTime.of(hour, minute, second, nanos); } - public static LocalTime parseLocalTime11(byte[] bytes, int off) { - if (off + 11 > bytes.length) { - return null; - } + private static LocalTime localTime(int hour, int minute, int second) { + return (hour | minute | second) < 0 + ? null + : LocalTime.of(hour, minute, second); + } - 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 c8 = bytes[off + 8]; - byte c9 = bytes[off + 9]; - byte c10 = bytes[off + 10]; - - byte h0, h1, i0, i1, s0, s1, m0, m1; - if (c2 == ':' && c5 == ':' && c8 == '.') { - h0 = c0; - h1 = c1; - i0 = c3; - i1 = c4; - s0 = c6; - s1 = c7; - m0 = c9; - m1 = c10; - } else { + public static LocalDateTime parseLocalDateTime(byte[] str, int off, int len) { + if (str == null || len == 0) { return null; } - int hour; - if (h0 >= '0' && h0 <= '9' - && h1 >= '0' && h1 <= '9' - ) { - hour = (h0 - '0') * 10 + (h1 - '0'); - } else { - return null; + switch (len) { + case 4: + if (str[off] == 'n' && str[off + 1] == 'u' && str[off + 2] == 'l' && str[off + 3] == 'l') { + return null; + } + String input = new String(str, off, len); + throw new DateTimeParseException("illegal input " + input, input, 0); + case 8: { + LocalDate localDate = parseLocalDate8(str, off); + if (localDate == null) { + return null; + } + return LocalDateTime.of(localDate, LocalTime.MIN); + } + case 9: { + LocalDate localDate = parseLocalDate9(str, off); + if (localDate == null) { + return null; + } + return LocalDateTime.of(localDate, LocalTime.MIN); + } + case 10: { + LocalDate localDate = parseLocalDate10(str, off); + if (localDate == null) { + return null; + } + return LocalDateTime.of(localDate, LocalTime.MIN); + } + case 11: { + return LocalDateTime.of( + parseLocalDate11(str, off), + LocalTime.MIN + ); + } + case 12: + return parseLocalDateTime12(str, off); + case 14: + return parseLocalDateTime14(str, off); + case 16: + return parseLocalDateTime16(str, off); + case 17: + return parseLocalDateTime17(str, off); + case 18: + return parseLocalDateTime18(str, off); + case 19: + return parseLocalDateTime19(str, off); + case 20: + return parseLocalDateTime20(str, off); + default: + return parseLocalDateTimeX(str, off, len); } + } - int minute; - if (i0 >= '0' && i0 <= '9' - && i1 >= '0' && i1 <= '9' - ) { - minute = (i0 - '0') * 10 + (i1 - '0'); - } else { + public static LocalDate parseLocalDate(String str) { + if (str == null) { return null; } - int second; - if (s0 >= '0' && s0 <= '9' - && s1 >= '0' && s1 <= '9' - ) { - second = (s0 - '0') * 10 + (s1 - '0'); + LocalDate localDate; + if (STRING_CODER != null && STRING_VALUE != null && STRING_CODER.applyAsInt(str) == 0) { + byte[] bytes = JDKUtils.STRING_VALUE.apply(str); + localDate = parseLocalDate(bytes, 0, bytes.length); } else { - return null; + char[] chars = JDKUtils.getCharArray(str); + localDate = parseLocalDate(chars, 0, chars.length); } - int millis; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - millis = (m0 - '0') * 100 + (m1 - '0') * 10; - millis *= 1000_000; - } else { - return null; + if (localDate == null) { + switch (str) { + case "": + case "null": + case "00000000": + case "0000年00月00日": + case "0000-0-00": + case "0000-00-00": + return null; + default: + throw new DateTimeParseException(str, str, 0); + } } - return LocalTime.of(hour, minute, second, millis); + return localDate; } - public static LocalTime parseLocalTime11(char[] bytes, int off) { - if (off + 11 > bytes.length) { + public static LocalDate parseLocalDate(byte[] str, int off, int len) { + if (str == null || len == 0) { return null; } - char c0 = bytes[off]; - char c1 = bytes[off + 1]; - char c2 = bytes[off + 2]; - char c3 = bytes[off + 3]; - char c4 = bytes[off + 4]; - char c5 = bytes[off + 5]; - char c6 = bytes[off + 6]; - char c7 = bytes[off + 7]; - char c8 = bytes[off + 8]; - char c9 = bytes[off + 9]; - char c10 = bytes[off + 10]; - - char h0, h1, i0, i1, s0, s1, m0, m1; - if (c2 == ':' && c5 == ':' && c8 == '.') { - h0 = c0; - h1 = c1; - i0 = c3; - i1 = c4; - s0 = c6; - s1 = c7; - m0 = c9; - m1 = c10; - } else { - return null; + if (off + len > str.length) { + String input = new String(str, off, len); + throw new DateTimeParseException("illegal input " + input, input, 0); } - int hour; - if (h0 >= '0' && h0 <= '9' - && h1 >= '0' && h1 <= '9' - ) { - hour = (h0 - '0') * 10 + (h1 - '0'); - } else { - return null; + switch (len) { + case 8: + return parseLocalDate8(str, off); + case 9: + return parseLocalDate9(str, off); + case 10: + return parseLocalDate10(str, off); + case 11: + return parseLocalDate11(str, off); + default: + if (len == 4 && str[off] == 'n' && str[off + 1] == 'u' && str[off + 2] == 'l' && str[off + 3] == 'l') { + return null; + } + String input = new String(str, off, len); + throw new DateTimeParseException("illegal input " + input, input, 0); } + } - int minute; - if (i0 >= '0' && i0 <= '9' - && i1 >= '0' && i1 <= '9' - ) { - minute = (i0 - '0') * 10 + (i1 - '0'); - } else { + public static LocalDate parseLocalDate(char[] str, int off, int len) { + if (str == null || len == 0) { return null; } - int second; - if (s0 >= '0' && s0 <= '9' - && s1 >= '0' && s1 <= '9' - ) { - second = (s0 - '0') * 10 + (s1 - '0'); - } else { - return null; + if (off + len > str.length) { + String input = new String(str, off, len); + throw new DateTimeParseException("illegal input " + input, input, 0); } - int millis; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9') { - millis = (m0 - '0') * 100 + (m1 - '0') * 10; - millis *= 1000_000; - } else { - return null; + switch (len) { + case 8: + return parseLocalDate8(str, off); + case 9: + return parseLocalDate9(str, off); + case 10: + return parseLocalDate10(str, off); + case 11: + return parseLocalDate11(str, off); + default: + if (len == 4 && str[off] == 'n' && str[off + 1] == 'u' && str[off + 2] == 'l' && str[off + 3] == 'l') { + return null; + } + String input = new String(str, off, len); + throw new DateTimeParseException("illegal input " + input, input, 0); } + } + + public static long parseMillis(byte[] bytes, int off, int len) { + return parseMillis(bytes, off, len, StandardCharsets.UTF_8, DEFAULT_ZONE_ID); + } - return LocalTime.of(hour, minute, second, millis); + public static long parseMillis(byte[] bytes, int off, int len, Charset charset) { + return parseMillis(bytes, off, len, charset, DEFAULT_ZONE_ID); } - public static LocalTime parseLocalTime12(byte[] bytes, int off) { - if (off + 12 > bytes.length) { - return null; + public static long parseMillis(byte[] chars, int off, int len, Charset charset, ZoneId zoneId) { + if (chars == null || len == 0) { + return 0; } - 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 c8 = bytes[off + 8]; - byte c9 = bytes[off + 9]; - byte c10 = bytes[off + 10]; - byte c11 = bytes[off + 11]; - - byte h0, h1, i0, i1, s0, s1, m0, m1, m2; - if (c2 == ':' && c5 == ':' && c8 == '.') { - h0 = c0; - h1 = c1; - i0 = c3; - i1 = c4; - s0 = c6; - s1 = c7; - m0 = c9; - m1 = c10; - m2 = c11; - } else { - return null; + if (len == 4 + && chars[off] == 'n' + && chars[off + 1] == 'u' + && chars[off + 2] == 'l' + && chars[off + 3] == 'l' + ) { + return 0; } - 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; - } - - int millis; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - && m2 >= '0' && m2 <= '9' - ) { - millis = (m0 - '0') * 100 + (m1 - '0') * 10 + (m2 - '0'); - millis *= 1000_000; - } else { - return null; - } - - return LocalTime.of(hour, minute, second, millis); - } - - public static LocalTime parseLocalTime12(char[] bytes, int off) { - if (off + 12 > bytes.length) { - return null; - } - - char c0 = bytes[off]; - char c1 = bytes[off + 1]; - char c2 = bytes[off + 2]; - char c3 = bytes[off + 3]; - char c4 = bytes[off + 4]; - char c5 = bytes[off + 5]; - char c6 = bytes[off + 6]; - char c7 = bytes[off + 7]; - char c8 = bytes[off + 8]; - char c9 = bytes[off + 9]; - char c10 = bytes[off + 10]; - char c11 = bytes[off + 11]; - - char h0, h1, i0, i1, s0, s1, m0, m1, m2; - if (c2 == ':' && c5 == ':' && c8 == '.') { - h0 = c0; - h1 = c1; - i0 = c3; - i1 = c4; - s0 = c6; - s1 = c7; - m0 = c9; - m1 = c10; - m2 = c11; - } else { - return null; - } - - 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; - } - - int millis; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - && m2 >= '0' && m2 <= '9' - ) { - millis = (m0 - '0') * 100 + (m1 - '0') * 10 + (m2 - '0'); - millis *= 1000_000; - } else { - return null; - } - - return LocalTime.of(hour, minute, second, millis); - } - - public static LocalTime parseLocalTime18(byte[] bytes, int off) { - if (off + 18 > bytes.length) { - 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 c8 = bytes[off + 8]; - byte c9 = bytes[off + 9]; - byte c10 = bytes[off + 10]; - byte c11 = bytes[off + 11]; - byte c12 = bytes[off + 12]; - byte c13 = bytes[off + 13]; - byte c14 = bytes[off + 14]; - byte c15 = bytes[off + 15]; - byte c16 = bytes[off + 16]; - byte c17 = bytes[off + 17]; - - byte h0, h1, i0, i1, s0, s1, m0, m1, m2, m3, m4, m5, m6, m7, m8; - if (c2 == ':' && c5 == ':' && c8 == '.') { - h0 = c0; - h1 = c1; - i0 = c3; - i1 = c4; - s0 = c6; - s1 = c7; - m0 = c9; - m1 = c10; - m2 = c11; - m3 = c12; - m4 = c13; - m5 = c14; - m6 = c15; - m7 = c16; - m8 = c17; - } else { - return null; - } - - 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; - } - - int millis; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - && m2 >= '0' && m2 <= '9' - && m3 >= '0' && m3 <= '9' - && m4 >= '0' && m4 <= '9' - && m5 >= '0' && m5 <= '9' - && m6 >= '0' && m6 <= '9' - && m7 >= '0' && m7 <= '9' - && m8 >= '0' && m8 <= '9' - ) { - millis = (m0 - '0') * 1000_000_00 - + (m1 - '0') * 1000_000_0 - + (m2 - '0') * 1000_000 - + (m3 - '0') * 1000_00 - + (m4 - '0') * 1000_0 - + (m5 - '0') * 1000 - + (m6 - '0') * 100 - + (m7 - '0') * 10 - + (m8 - '0'); - } else { - return null; - } - - return LocalTime.of(hour, minute, second, millis); - } - - public static LocalTime parseLocalTime18(char[] bytes, int off) { - if (off + 18 > bytes.length) { - return null; - } - - char c0 = bytes[off]; - char c1 = bytes[off + 1]; - char c2 = bytes[off + 2]; - char c3 = bytes[off + 3]; - char c4 = bytes[off + 4]; - char c5 = bytes[off + 5]; - char c6 = bytes[off + 6]; - char c7 = bytes[off + 7]; - char c8 = bytes[off + 8]; - char c9 = bytes[off + 9]; - char c10 = bytes[off + 10]; - char c11 = bytes[off + 11]; - char c12 = bytes[off + 12]; - char c13 = bytes[off + 13]; - char c14 = bytes[off + 14]; - char c15 = bytes[off + 15]; - char c16 = bytes[off + 16]; - char c17 = bytes[off + 17]; - - char h0, h1, i0, i1, s0, s1, m0, m1, m2, m3, m4, m5, m6, m7, m8; - if (c2 == ':' && c5 == ':' && c8 == '.') { - h0 = c0; - h1 = c1; - i0 = c3; - i1 = c4; - s0 = c6; - s1 = c7; - m0 = c9; - m1 = c10; - m2 = c11; - m3 = c12; - m4 = c13; - m5 = c14; - m6 = c15; - m7 = c16; - m8 = c17; - } else { - return null; - } - - 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; - } - - int millis; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - && m2 >= '0' && m2 <= '9' - && m3 >= '0' && m3 <= '9' - && m4 >= '0' && m4 <= '9' - && m5 >= '0' && m5 <= '9' - && m6 >= '0' && m6 <= '9' - && m7 >= '0' && m7 <= '9' - && m8 >= '0' && m8 <= '9' - ) { - millis = (m0 - '0') * 1000_000_00 - + (m1 - '0') * 1000_000_0 - + (m2 - '0') * 1000_000 - + (m3 - '0') * 1000_00 - + (m4 - '0') * 1000_0 - + (m5 - '0') * 1000 - + (m6 - '0') * 100 - + (m7 - '0') * 10 - + (m8 - '0'); - } else { - return null; - } - - return LocalTime.of(hour, minute, second, millis); - } - - public static LocalDateTime parseLocalDateTime(byte[] str, int off, int len) { - if (str == null || len == 0) { - return null; - } - - switch (len) { - case 4: - if (str[off] == 'n' && str[off + 1] == 'u' && str[off + 2] == 'l' && str[off + 3] == 'l') { - return null; - } - String input = new String(str, off, len); - throw new DateTimeParseException("illegal input " + input, input, 0); - case 8: { - LocalDate localDate = parseLocalDate8(str, off); - if (localDate == null) { - return null; - } - return LocalDateTime.of(localDate, LocalTime.MIN); - } - case 9: { - LocalDate localDate = parseLocalDate9(str, off); - if (localDate == null) { - return null; - } - return LocalDateTime.of(localDate, LocalTime.MIN); - } - case 10: { - LocalDate localDate = parseLocalDate10(str, off); - if (localDate == null) { - return null; - } - return LocalDateTime.of(localDate, LocalTime.MIN); - } - case 11: { - return LocalDateTime.of( - parseLocalDate11(str, off), - LocalTime.MIN - ); - } - case 12: - return parseLocalDateTime12(str, off); - case 14: - return parseLocalDateTime14(str, off); - case 16: - return parseLocalDateTime16(str, off); - case 17: - return parseLocalDateTime17(str, off); - case 18: - return parseLocalDateTime18(str, off); - case 19: - return parseLocalDateTime19(str, off); - case 20: - return parseLocalDateTime20(str, off); - default: - return parseLocalDateTimeX(str, off, len); - } - } - - public static LocalDate parseLocalDate(String str) { - if (str == null) { - return null; - } - - LocalDate localDate; - if (STRING_CODER != null && STRING_VALUE != null && STRING_CODER.applyAsInt(str) == 0) { - byte[] bytes = JDKUtils.STRING_VALUE.apply(str); - localDate = parseLocalDate(bytes, 0, bytes.length); - } else { - char[] chars = JDKUtils.getCharArray(str); - localDate = parseLocalDate(chars, 0, chars.length); - } - - if (localDate == null) { - switch (str) { - case "": - case "null": - case "00000000": - case "0000年00月00日": - case "0000-0-00": - case "0000-00-00": - return null; - default: - throw new DateTimeParseException(str, str, 0); - } - } - - return localDate; - } - - public static LocalDate parseLocalDate(byte[] str, int off, int len) { - if (str == null || len == 0) { - return null; - } - - if (off + len > str.length) { - String input = new String(str, off, len); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - switch (len) { - case 8: - return parseLocalDate8(str, off); - case 9: - return parseLocalDate9(str, off); - case 10: - return parseLocalDate10(str, off); - case 11: - return parseLocalDate11(str, off); - default: - if (len == 4 && str[off] == 'n' && str[off + 1] == 'u' && str[off + 2] == 'l' && str[off + 3] == 'l') { - return null; - } - String input = new String(str, off, len); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - } - - public static LocalDate parseLocalDate(char[] str, int off, int len) { - if (str == null || len == 0) { - return null; - } - - if (off + len > str.length) { - String input = new String(str, off, len); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - switch (len) { - case 8: - return parseLocalDate8(str, off); - case 9: - return parseLocalDate9(str, off); - case 10: - return parseLocalDate10(str, off); - case 11: - return parseLocalDate11(str, off); - default: - if (len == 4 && str[off] == 'n' && str[off + 1] == 'u' && str[off + 2] == 'l' && str[off + 3] == 'l') { - return null; - } - String input = new String(str, off, len); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - } - - public static long parseMillis(byte[] bytes, int off, int len) { - return parseMillis(bytes, off, len, StandardCharsets.UTF_8, DEFAULT_ZONE_ID); - } - - public static long parseMillis(byte[] bytes, int off, int len, Charset charset) { - return parseMillis(bytes, off, len, charset, DEFAULT_ZONE_ID); - } - - public static long parseMillis(byte[] chars, int off, int len, Charset charset, ZoneId zoneId) { - if (chars == null || len == 0) { - return 0; - } - - if (len == 4 - && chars[off] == 'n' - && chars[off + 1] == 'u' - && chars[off + 2] == 'l' - && chars[off + 3] == 'l' - ) { - return 0; - } - - char c10; - long millis; - char c0 = (char) chars[off]; - if (c0 == '"' && chars[len - 1] == '"') { - try (JSONReader jsonReader = JSONReader.of(chars, off, len, charset)) { - Date date = (Date) ObjectReaderImplDate.INSTANCE.readObject( - jsonReader, - null, - null, - 0 - ); - millis = date.getTime(); - } - } else if (len == 19) { - millis = DateUtils.parseMillis19(chars, off, zoneId); - } else if (len > 19 - // ISO Date with offset example '2011-12-03+01:00' - || (len == 16 && ((c10 = (char) chars[off + 10]) == '+' || c10 == '-')) - ) { - ZonedDateTime zdt = parseZonedDateTime(chars, off, len, zoneId); - if (zdt == null) { - String input = new String(chars, off, len - off); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - millis = zdt.toInstant().toEpochMilli(); - } else if ((c0 == '-' || c0 >= '0' && c0 <= '9') && IOUtils.isNumber(chars, off, len)) { - millis = TypeUtils.parseLong(chars, off, len); - if (len == 8 && millis >= 19700101 && millis <= 21000101) { - int year = (int) millis / 10000; - int month = ((int) millis % 10000) / 100; - int dom = (int) millis % 100; - - if (month >= 1 && month <= 12) { - int max = 31; - switch (month) { - case 2: - boolean leapYear = (year & 3) == 0 && ((year % 100) != 0 || (year % 400) == 0); - max = leapYear ? 29 : 28; - break; - case 4: - case 6: - case 9: - case 11: - max = 30; - break; - } - if (dom <= max) { - LocalDateTime ldt = LocalDateTime.of(year, month, dom, 0, 0, 0); - ZonedDateTime zdt = ZonedDateTime.ofLocal(ldt, zoneId, null); - long seconds = zdt.toEpochSecond(); - millis = seconds * 1000L; - } - } - } - } else { - char last = (char) chars[len - 1]; - if (last == 'Z') { - zoneId = UTC; - } - LocalDateTime ldt = DateUtils.parseLocalDateTime(chars, off, len); - if (ldt == null - // && "0000-00-00".equals(str) - && chars[off] == '0' - && chars[off + 1] == '0' - && chars[off + 2] == '0' - && chars[off + 3] == '0' - && chars[off + 4] == '-' - && chars[off + 5] == '0' - && chars[off + 6] == '0' - && chars[off + 7] == '-' - && chars[off + 8] == '0' - && chars[off + 9] == '0' - ) { - ldt = LocalDateTime.of(1970, 1, 1, 0, 0, 0); - } - ZonedDateTime zdt = ZonedDateTime.ofLocal(ldt, zoneId, null); - long seconds = zdt.toEpochSecond(); - int nanos = ldt.getNano(); - if (seconds < 0 && nanos > 0) { - millis = (seconds + 1) * 1000 + nanos / 1000_000 - 1000; - } else { - millis = seconds * 1000L + nanos / 1000_000; - } - } - return millis; - } - - public static long parseMillis(char[] bytes, int off, int len) { - return parseMillis(bytes, off, len, DEFAULT_ZONE_ID); - } - - public static long parseMillis(char[] chars, int off, int len, ZoneId zoneId) { - if (chars == null || len == 0) { - return 0; - } - - if (len == 4 - && chars[off] == 'n' - && chars[off + 1] == 'u' - && chars[off + 2] == 'l' - && chars[off + 3] == 'l' - ) { - return 0; - } - - char c10; - long millis; - char c0 = chars[off]; - if (c0 == '"' && chars[len - 1] == '"') { - try (JSONReader jsonReader = JSONReader.of(chars, off, len)) { - Date date = (Date) ObjectReaderImplDate.INSTANCE.readObject( - jsonReader, - null, - null, - 0 - ); - millis = date.getTime(); - } - } else if (len == 19) { - millis = DateUtils.parseMillis19(chars, off, zoneId); - } else if (len > 19 - // ISO Date with offset example '2011-12-03+01:00' - || (len == 16 && ((c10 = chars[off + 10]) == '+' || c10 == '-')) - ) { - ZonedDateTime zdt = parseZonedDateTime(chars, off, len, zoneId); - if (zdt == null) { - String input = new String(chars, off, len - off); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - millis = zdt.toInstant().toEpochMilli(); - } else if ((c0 == '-' || c0 >= '0' && c0 <= '9') && IOUtils.isNumber(chars, off, len)) { - millis = TypeUtils.parseLong(chars, off, len); - if (len == 8 && millis >= 19700101 && millis <= 21000101) { - int year = (int) millis / 10000; - int month = ((int) millis % 10000) / 100; - int dom = (int) millis % 100; - - if (month >= 1 && month <= 12) { - int max = 31; - switch (month) { - case 2: - boolean leapYear = (year & 3) == 0 && ((year % 100) != 0 || (year % 400) == 0); - max = leapYear ? 29 : 28; - break; - case 4: - case 6: - case 9: - case 11: - max = 30; - break; - } - if (dom <= max) { - LocalDateTime ldt = LocalDateTime.of(year, month, dom, 0, 0, 0); - ZonedDateTime zdt = ZonedDateTime.ofLocal(ldt, zoneId, null); - long seconds = zdt.toEpochSecond(); - millis = seconds * 1000L; - } - } - } - } else { - char last = chars[len - 1]; - if (last == 'Z') { - len--; - zoneId = UTC; - } - LocalDateTime ldt = DateUtils.parseLocalDateTime(chars, off, len); - if (ldt == null - // && "0000-00-00".equals(str) - && chars[off] == '0' - && chars[off + 1] == '0' - && chars[off + 2] == '0' - && chars[off + 3] == '0' - && chars[off + 4] == '-' - && chars[off + 5] == '0' - && chars[off + 6] == '0' - && chars[off + 7] == '-' - && chars[off + 8] == '0' - && chars[off + 9] == '0' - ) { - ldt = LocalDateTime.of(1970, 1, 1, 0, 0, 0); - } - - if (ldt == null) { - String input = new String(chars, off, len - off); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - ZonedDateTime zdt = ZonedDateTime.ofLocal(ldt, zoneId, null); - long seconds = zdt.toEpochSecond(); - int nanos = ldt.getNano(); - if (seconds < 0 && nanos > 0) { - millis = (seconds + 1) * 1000 + nanos / 1000_000 - 1000; - } else { - millis = seconds * 1000L + nanos / 1000_000; - } - } - return millis; - } - - /** - * yyyy-m-d - * yyyyMMdd - * d-MMM-yy - */ - public static LocalDate parseLocalDate8(byte[] str, int off) { - if (off + 8 > str.length) { - return null; - } - - char c0 = (char) str[off]; - char c1 = (char) str[off + 1]; - char c2 = (char) str[off + 2]; - char c3 = (char) str[off + 3]; - char c4 = (char) str[off + 4]; - char c5 = (char) str[off + 5]; - char c6 = (char) str[off + 6]; - char c7 = (char) str[off + 7]; - - char y0, y1, y2, y3, m0, m1, d0, d1; - if (c4 == '-' && c6 == '-') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = '0'; - m1 = c5; - - d0 = '0'; - d1 = c7; - } else if (c1 == '/' && c3 == '/') { - m0 = '0'; - m1 = c0; - - d0 = '0'; - d1 = c2; - - y0 = c4; - y1 = c5; - y2 = c6; - y3 = c7; - } else if (c1 == '-' && c5 == '-') { - // d-MMM-yy - d0 = '0'; - d1 = c0; - - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - y0 = '2'; - y1 = '0'; - y2 = c6; - y3 = c7; - } else { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c4; - m1 = c5; - - d0 = c6; - d1 = c7; - } - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - return null; - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - return null; - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - return null; - } - - if (year == 0 && month == 0 && dom == 0) { - return null; - } - - return LocalDate.of(year, month, dom); - } - - /** - * yyyy-m-d - * yyyyMMdd - * d-MMM-yy - */ - public static LocalDate parseLocalDate8(char[] str, int off) { - if (off + 8 > str.length) { - return null; - } - - char c0 = str[off]; - char c1 = str[off + 1]; - char c2 = str[off + 2]; - char c3 = str[off + 3]; - char c4 = str[off + 4]; - char c5 = str[off + 5]; - char c6 = str[off + 6]; - char c7 = str[off + 7]; - - char y0, y1, y2, y3, m0, m1, d0, d1; - if (c4 == '-' && c6 == '-') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = '0'; - m1 = c5; - - d0 = '0'; - d1 = c7; - } else if (c1 == '/' && c3 == '/') { - m0 = '0'; - m1 = c0; - - d0 = '0'; - d1 = c2; - - y0 = c4; - y1 = c5; - y2 = c6; - y3 = c7; - } else if (c1 == '-' && c5 == '-') { - // d-MMM-yy - d0 = '0'; - d1 = c0; - - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - y0 = '2'; - y1 = '0'; - y2 = c6; - y3 = c7; - } else { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c4; - m1 = c5; - - d0 = c6; - d1 = c7; - } - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - return null; - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - return null; - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - return null; - } - - if (year == 0 && month == 0 && dom == 0) { - return null; - } - - return LocalDate.of(year, month, dom); - } - - /** - * yyyy-MM-d - * yyyy-M-dd - * dd-MMM-yy - */ - public static LocalDate parseLocalDate9(byte[] str, int off) { - if (off + 9 > str.length) { - return null; - } - - char c0 = (char) str[off]; - char c1 = (char) str[off + 1]; - char c2 = (char) str[off + 2]; - char c3 = (char) str[off + 3]; - char c4 = (char) str[off + 4]; - char c5 = (char) str[off + 5]; - char c6 = (char) str[off + 6]; - char c7 = (char) str[off + 7]; - char c8 = (char) str[off + 8]; - - char y0, y1, y2, y3, m0, m1, d0, d1; - if (c4 == '-' && c7 == '-') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = '0'; - d1 = c8; - } else if (c4 == '-' && c6 == '-') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = '0'; - m1 = c5; - - d0 = c7; - d1 = c8; - } else if (c4 == '/' && c7 == '/') { // tw : yyyy/mm/d - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = '0'; - d1 = c8; - } else if (c4 == '/' && c6 == '/') { // tw : yyyy/m/dd - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = '0'; - m1 = c5; - - d0 = c7; - d1 = c8; - } else if (c1 == '.' && c4 == '.') { - d0 = '0'; - d1 = c0; - - m0 = c2; - m1 = c3; - - y0 = c5; - y1 = c6; - y2 = c7; - y3 = c8; - } else if (c2 == '.' && c4 == '.') { - d0 = c0; - d1 = c1; - - m0 = '0'; - m1 = c3; - - y0 = c5; - y1 = c6; - y2 = c7; - y3 = c8; - } else if (c1 == '-' && c4 == '-') { - d0 = '0'; - d1 = c0; - - m0 = c2; - m1 = c3; - - y0 = c5; - y1 = c6; - y2 = c7; - y3 = c8; - } else if (c2 == '-' && c4 == '-') { - d0 = c0; - d1 = c1; - - m0 = '0'; - m1 = c3; - - y0 = c5; - y1 = c6; - y2 = c7; - y3 = c8; - } else if (c2 == '-' && c6 == '-') { - // dd-MMM-yy - d0 = c0; - d1 = c1; - - int month = DateUtils.month(c3, c4, c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - y0 = '2'; - y1 = '0'; - y2 = c7; - y3 = c8; - } else if (c1 == '/' && c4 == '/') { - // M/dd/dddd - m0 = '0'; - m1 = c0; - - d0 = c2; - d1 = c3; - - y0 = c5; - y1 = c6; - y2 = c7; - y3 = c8; - } else if (c2 == '/' && c4 == '/') { - // MM/d/dddd - m0 = c0; - m1 = c1; - - d0 = '0'; - d1 = c3; - - y0 = c5; - y1 = c6; - y2 = c7; - y3 = c8; - } else { - return null; - } - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - return null; - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - return null; - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - return null; - } - - if (year == 0 && month == 0 && dom == 0) { - return null; - } - - return LocalDate.of(year, month, dom); - } - - /** - * yyyy-MM-d - * yyyy-M-dd - * dd-MMM-yy - */ - public static LocalDate parseLocalDate9(char[] str, int off) { - if (off + 9 > str.length) { - return null; - } - - char c0 = str[off]; - char c1 = str[off + 1]; - char c2 = str[off + 2]; - char c3 = str[off + 3]; - char c4 = str[off + 4]; - char c5 = str[off + 5]; - char c6 = str[off + 6]; - char c7 = str[off + 7]; - char c8 = str[off + 8]; - - char y0, y1, y2, y3, m0, m1, d0, d1; - if (c4 == '-' && c7 == '-') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = '0'; - d1 = c8; - } else if (c4 == '-' && c6 == '-') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = '0'; - m1 = c5; - - d0 = c7; - d1 = c8; - } else if (c4 == '/' && c7 == '/') { // tw : yyyy/mm/d - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = '0'; - d1 = c8; - } else if (c4 == '/' && c6 == '/') { // tw : yyyy/m/dd - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = '0'; - m1 = c5; - - d0 = c7; - d1 = c8; - } else if (c1 == '.' && c4 == '.') { - d0 = '0'; - d1 = c0; - - m0 = c2; - m1 = c3; - - y0 = c5; - y1 = c6; - y2 = c7; - y3 = c8; - } else if (c2 == '.' && c4 == '.') { - d0 = c0; - d1 = c1; - - m0 = '0'; - m1 = c3; - - y0 = c5; - y1 = c6; - y2 = c7; - y3 = c8; - } else if (c1 == '-' && c4 == '-') { - d0 = '0'; - d1 = c0; - - m0 = c2; - m1 = c3; - - y0 = c5; - y1 = c6; - y2 = c7; - y3 = c8; - } else if (c2 == '-' && c4 == '-') { - d0 = c0; - d1 = c1; - - m0 = '0'; - m1 = c3; - - y0 = c5; - y1 = c6; - y2 = c7; - y3 = c8; - } else if (c4 == '年' && c6 == '月' && c8 == '日') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = '0'; - m1 = c5; - - d0 = '0'; - d1 = c7; - } else if (c4 == '년' && c6 == '월' && c8 == '일') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = '0'; - m1 = c5; - - d0 = '0'; - d1 = c7; - } else if (c2 == '-' && c6 == '-') { - // dd-MMM-yy - d0 = c0; - d1 = c1; - - int month = DateUtils.month(c3, c4, c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - y0 = '2'; - y1 = '0'; - y2 = c7; - y3 = c8; - } else if (c1 == '/' && c4 == '/') { - // M/dd/dddd - m0 = '0'; - m1 = c0; - - d0 = c2; - d1 = c3; - - y0 = c5; - y1 = c6; - y2 = c7; - y3 = c8; - } else if (c2 == '/' && c4 == '/') { - // MM/d/dddd - m0 = c0; - m1 = c1; - - d0 = '0'; - d1 = c3; - - y0 = c5; - y1 = c6; - y2 = c7; - y3 = c8; - } else { - return null; - } - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - return null; - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - return null; - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - return null; - } - - if (year == 0 && month == 0 && dom == 0) { - return null; - } - - return LocalDate.of(year, month, dom); - } - - /** - * yyyy-MM-dd - * yyyy/MM/dd - * MM/dd/yyyy - * dd.MM.yyyy - * yyyy年M月dd日 - * yyyy年MM月d日 - * yyyy MMM d - */ - public static LocalDate parseLocalDate10(byte[] str, int off) { - if (off + 10 > str.length) { - return null; - } - - char c0 = (char) str[off]; - char c1 = (char) str[off + 1]; - char c2 = (char) str[off + 2]; - char c3 = (char) str[off + 3]; - char c4 = (char) str[off + 4]; - char c5 = (char) str[off + 5]; - char c6 = (char) str[off + 6]; - char c7 = (char) str[off + 7]; - char c8 = (char) str[off + 8]; - char c9 = (char) str[off + 9]; - - char y0, y1, y2, y3, m0, m1, d0, d1; - if (c4 == '-' && c7 == '-') { - // yyyy-MM-dd - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - } else if (c4 == '/' && c7 == '/') { - // tw : yyyy/mm/dd - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - } else if (c2 == '.' && c5 == '.') { - // dd.MM.yyyy - d0 = c0; - d1 = c1; - - m0 = c3; - m1 = c4; - - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - } else if (c2 == '-' && c5 == '-') { - // dd-MM-yyyy - d0 = c0; - d1 = c1; - - m0 = c3; - m1 = c4; - - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - } else if (c2 == '/' && c5 == '/') { - // MM/dd/yyyy - m0 = c0; - m1 = c1; - - d0 = c3; - d1 = c4; - - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - } else if (c1 == ' ' && c5 == ' ') { - // yyyy MMM d - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - d0 = '0'; - d1 = c0; - } else { - return null; - } - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - return null; - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - return null; - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - return null; - } - - if (year == 0 && month == 0 && dom == 0) { - return null; - } - - return LocalDate.of(year, month, dom); - } - - /** - * yyyy-MM-dd - * yyyy/MM/dd - * MM/dd/yyyy - * dd.MM.yyyy - * yyyy年M月dd日 - * yyyy年MM月d日 - * yyyy MMM d - */ - public static LocalDate parseLocalDate10(char[] str, int off) { - if (off + 10 > str.length) { - return null; - } - - char c0 = str[off]; - char c1 = str[off + 1]; - char c2 = str[off + 2]; - char c3 = str[off + 3]; - char c4 = str[off + 4]; - char c5 = str[off + 5]; - char c6 = str[off + 6]; - char c7 = str[off + 7]; - char c8 = str[off + 8]; - char c9 = str[off + 9]; - - char y0, y1, y2, y3, m0, m1, d0, d1; - if (c4 == '-' && c7 == '-') { - // yyyy-MM-dd - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - } else if (c4 == '/' && c7 == '/') { - // tw : yyyy/mm/dd - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - } else if (c2 == '.' && c5 == '.') { - // dd.MM.yyyy - d0 = c0; - d1 = c1; - - m0 = c3; - m1 = c4; - - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - } else if (c2 == '-' && c5 == '-') { - // dd-MM-yyyy - d0 = c0; - d1 = c1; - - m0 = c3; - m1 = c4; - - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - } else if (c2 == '/' && c5 == '/') { - // MM/dd/yyyy - m0 = c0; - m1 = c1; - - d0 = c3; - d1 = c4; - - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - } else if (c4 == '年' && c6 == '月' && c9 == '日') { - // yyyy年M月dd日 - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = '0'; - m1 = c5; - - d0 = c7; - d1 = c8; - } else if (c4 == '년' && c6 == '월' && c9 == '일') { - // yyyy년M월dd일 - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = '0'; - m1 = c5; - - d0 = c7; - d1 = c8; - } else if (c4 == '年' && c7 == '月' && c9 == '日') { - // // yyyy年MM月d日 - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = '0'; - d1 = c8; - } else if (c4 == '년' && c7 == '월' && c9 == '일') { - // yyyy년MM월d일 - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = '0'; - d1 = c8; - } else if (c1 == ' ' && c5 == ' ') { - // yyyy MMM d - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - d0 = '0'; - d1 = c0; - } else { - return null; - } - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - return null; - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - return null; - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - return null; - } - - if (year == 0 && month == 0 && dom == 0) { - return null; - } - - return LocalDate.of(year, month, dom); - } - - /** - * yyyy年MM月dd日 - * yyyy년MM월dd일 - */ - public static LocalDate parseLocalDate11(char[] str, int off) { - if (off + 11 > str.length) { - return null; - } - - char c0 = str[off]; - char c1 = str[off + 1]; - char c2 = str[off + 2]; - char c3 = str[off + 3]; - char c4 = str[off + 4]; - char c5 = str[off + 5]; - char c6 = str[off + 6]; - char c7 = str[off + 7]; - char c8 = str[off + 8]; - char c9 = str[off + 9]; - char c10 = str[off + 10]; - - char y0, y1, y2, y3, m0, m1, d0, d1; - if (c4 == '年' && c7 == '月' && c10 == '日') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - } else if (c4 == '-' && c7 == '-' && c10 == 'Z') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - } else if (c4 == '년' && c7 == '월' && c10 == '일') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - } else if (c2 == ' ' && c6 == ' ') { - y0 = c7; - y1 = c8; - y2 = c9; - y3 = c10; - - int month = DateUtils.month(c3, c4, c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - d0 = c0; - d1 = c1; - } else { - return null; - } - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - return null; - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - return null; - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - return null; - } - - if (year == 0 && month == 0 && dom == 0) { - return null; - } - - return LocalDate.of(year, month, dom); - } - - /** - * - */ - public static LocalDate parseLocalDate11(byte[] str, int off) { - if (off + 11 > str.length) { - return null; - } - - char c0 = (char) str[off]; - char c1 = (char) str[off + 1]; - char c2 = (char) str[off + 2]; - char c3 = (char) str[off + 3]; - char c4 = (char) str[off + 4]; - char c5 = (char) str[off + 5]; - char c6 = (char) str[off + 6]; - char c7 = (char) str[off + 7]; - char c8 = (char) str[off + 8]; - char c9 = (char) str[off + 9]; - char c10 = (char) str[off + 10]; - - char y0, y1, y2, y3, m0, m1, d0, d1; - if (c4 == '-' && c7 == '-' && c10 == 'Z') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - } else if (c2 == ' ' && c6 == ' ') { - y0 = c7; - y1 = c8; - y2 = c9; - y3 = c10; - - int month = DateUtils.month(c3, c4, c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - d0 = c0; - d1 = c1; - } else { - return null; - } - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - return null; - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - return null; - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - return null; - } - - if (year == 0 && month == 0 && dom == 0) { - return null; - } - - return LocalDate.of(year, month, dom); - } - - public static LocalDateTime parseLocalDateTime12(char[] str, int off) { - if (off + 12 > str.length) { - String input = new String(str, off, str.length - off); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - char y0 = str[off]; - char y1 = str[off + 1]; - char y2 = str[off + 2]; - char y3 = str[off + 3]; - char m0 = str[off + 4]; - char m1 = str[off + 5]; - char d0 = str[off + 6]; - char d1 = str[off + 7]; - char h0 = str[off + 8]; - char h1 = str[off + 9]; - char i0 = str[off + 10]; - char i1 = str[off + 11]; - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - String input = new String(str, off, off + 12); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - String input = new String(str, off, off + 12); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - String input = new String(str, off, off + 12); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - int hour; - if (h0 >= '0' && h0 <= '9' - && h1 >= '0' && h1 <= '9' - ) { - hour = (h0 - '0') * 10 + (h1 - '0'); - } else { - String input = new String(str, off, off + 12); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - int minute; - if (i0 >= '0' && i0 <= '9' - && i1 >= '0' && i1 <= '9' - ) { - minute = (i0 - '0') * 10 + (i1 - '0'); - } else { - String input = new String(str, off, off + 12); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - if (year == 0 && month == 0 && dom == 0 && hour == 0 && minute == 0) { - return null; - } - - return LocalDateTime.of(year, month, dom, hour, minute, 0); - } - - /** - * parseLocalDateTime use format 'yyyyMMddHHmm' - */ - public static LocalDateTime parseLocalDateTime12(byte[] str, int off) { - if (off + 12 > str.length) { - String input = new String(str, off, str.length - off); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - char y0 = (char) str[off]; - char y1 = (char) str[off + 1]; - char y2 = (char) str[off + 2]; - char y3 = (char) str[off + 3]; - char m0 = (char) str[off + 4]; - char m1 = (char) str[off + 5]; - char d0 = (char) str[off + 6]; - char d1 = (char) str[off + 7]; - char h0 = (char) str[off + 8]; - char h1 = (char) str[off + 9]; - char i0 = (char) str[off + 10]; - char i1 = (char) str[off + 11]; - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - String input = new String(str, off, off + 12); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - String input = new String(str, off, off + 12); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - String input = new String(str, off, off + 12); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - int hour; - if (h0 >= '0' && h0 <= '9' - && h1 >= '0' && h1 <= '9' - ) { - hour = (h0 - '0') * 10 + (h1 - '0'); - } else { - String input = new String(str, off, off + 12); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - int minute; - if (i0 >= '0' && i0 <= '9' - && i1 >= '0' && i1 <= '9' - ) { - minute = (i0 - '0') * 10 + (i1 - '0'); - } else { - String input = new String(str, off, off + 12); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - if (year == 0 && month == 0 && dom == 0 && hour == 0 && minute == 0) { - return null; - } - - return LocalDateTime.of(year, month, dom, hour, minute, 0); - } - - /** - * yyyyMMddHHmmss - */ - public static LocalDateTime parseLocalDateTime14(char[] str, int off) { - if (off + 14 > str.length) { - return null; - } - - char y0 = str[off]; - char y1 = str[off + 1]; - char y2 = str[off + 2]; - char y3 = str[off + 3]; - char m0 = str[off + 4]; - char m1 = str[off + 5]; - char d0 = str[off + 6]; - char d1 = str[off + 7]; - char h0 = str[off + 8]; - char h1 = str[off + 9]; - char i0 = str[off + 10]; - char i1 = str[off + 11]; - char s0 = str[off + 12]; - char s1 = str[off + 13]; - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - return null; - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - return null; - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - return null; - } - - 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 LocalDateTime.of(year, month, dom, hour, minute, second); - } - - /** - * yyyyMMddHHmmss - */ - public static LocalDateTime parseLocalDateTime14(byte[] str, int off) { - if (off + 14 > str.length) { - return null; - } - - char y0 = (char) str[off]; - char y1 = (char) str[off + 1]; - char y2 = (char) str[off + 2]; - char y3 = (char) str[off + 3]; - char m0 = (char) str[off + 4]; - char m1 = (char) str[off + 5]; - char d0 = (char) str[off + 6]; - char d1 = (char) str[off + 7]; - char h0 = (char) str[off + 8]; - char h1 = (char) str[off + 9]; - char i0 = (char) str[off + 10]; - char i1 = (char) str[off + 11]; - char s0 = (char) str[off + 12]; - char s1 = (char) str[off + 13]; - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - return null; - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - return null; - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - return null; - } - - 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 LocalDateTime.of(year, month, dom, hour, minute, second); - } - - /** - * yyyy-MM-ddTHH:mm - * yyyy-MM-dd HH:mm - * yyyyMMddTHHmmssZ - * yyyy-MM-ddTH:m:s - * yyyy-MM-dd H:m:s - */ - public static LocalDateTime parseLocalDateTime16(char[] str, int off) { - if (off + 16 > str.length) { - return null; - } - - char c0 = str[off]; - char c1 = str[off + 1]; - char c2 = str[off + 2]; - char c3 = str[off + 3]; - char c4 = str[off + 4]; - char c5 = str[off + 5]; - char c6 = str[off + 6]; - char c7 = str[off + 7]; - char c8 = str[off + 8]; - char c9 = str[off + 9]; - char c10 = str[off + 10]; - char c11 = str[off + 11]; - char c12 = str[off + 12]; - char c13 = str[off + 13]; - char c14 = str[off + 14]; - char c15 = str[off + 15]; - - char y0, y1, y2, y3, m0, m1, d0, d1, h0, h1, i0, i1, s0 = '0', s1 = '0'; - if (c4 == '-' && c7 == '-' && (c10 == 'T' || c10 == ' ') && c13 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - - h0 = c11; - h1 = c12; - - i0 = c14; - i1 = c15; - } else if (c8 == 'T' && c15 == 'Z') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - m0 = c4; - m1 = c5; - d0 = c6; - d1 = c7; - h0 = c9; - h1 = c10; - i0 = c11; - i1 = c12; - s0 = c13; - s1 = c14; - } else if (c4 == '-' && c7 == '-' && (c10 == 'T' || c10 == ' ') && c12 == ':' && c14 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - - h0 = '0'; - h1 = c11; - - i0 = '0'; - i1 = c13; - - s1 = c15; - } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':') { - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - d0 = '0'; - d1 = c0; - - h0 = c11; - h1 = c12; - - i0 = c14; - i1 = c15; - } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c12 == ':' && c14 == ':') { - // d MMM yyyy H:m:ss - // 6 DEC 2020 2:3:14 - d0 = '0'; - d1 = c0; - - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - - h0 = '0'; - h1 = c11; - - i0 = '0'; - i1 = c13; - - s1 = c15; - } else { - return null; - } - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - return null; - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - return null; - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - return null; - } - - 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 LocalDateTime.of(year, month, dom, hour, minute, second); - } - - /** - * yyyy-MM-ddTHH:mm - * yyyy-MM-dd HH:mm - * yyyyMMddTHHmmssZ - * yyyy-MM-ddTH:m:s - * yyyy-MM-dd H:m:s - */ - public static LocalDateTime parseLocalDateTime16(byte[] str, int off) { - if (off + 16 > str.length) { - return null; - } - - byte c0 = str[off]; - byte c1 = str[off + 1]; - byte c2 = str[off + 2]; - byte c3 = str[off + 3]; - byte c4 = str[off + 4]; - byte c5 = str[off + 5]; - byte c6 = str[off + 6]; - byte c7 = str[off + 7]; - byte c8 = str[off + 8]; - byte c9 = str[off + 9]; - byte c10 = str[off + 10]; - byte c11 = str[off + 11]; - byte c12 = str[off + 12]; - byte c13 = str[off + 13]; - byte c14 = str[off + 14]; - byte c15 = str[off + 15]; - - char y0, y1, y2, y3, m0, m1, d0, d1, h0, h1, i0, i1, s0 = '0', s1 = '0'; - if (c4 == '-' && c7 == '-' && (c10 == 'T' || c10 == ' ') && c13 == ':') { - y0 = (char) c0; - y1 = (char) c1; - y2 = (char) c2; - y3 = (char) c3; - - m0 = (char) c5; - m1 = (char) c6; - - d0 = (char) c8; - d1 = (char) c9; - - h0 = (char) c11; - h1 = (char) c12; - - i0 = (char) c14; - i1 = (char) c15; - } else if (c8 == 'T' && c15 == 'Z') { - y0 = (char) c0; - y1 = (char) c1; - y2 = (char) c2; - y3 = (char) c3; - m0 = (char) c4; - m1 = (char) c5; - d0 = (char) c6; - d1 = (char) c7; - h0 = (char) c9; - h1 = (char) c10; - i0 = (char) c11; - i1 = (char) c12; - s0 = (char) c13; - s1 = (char) c14; - } else if (c4 == -27 && c5 == -71 && c6 == -76 // 年 - && c8 == -26 && c9 == -100 && c10 == -120 // 月 - && c13 == -26 && c14 == -105 && c15 == -91 // 日 - ) { - y0 = (char) c0; - y1 = (char) c1; - y2 = (char) c2; - y3 = (char) c3; - - m0 = '0'; - m1 = (char) c7; - - d0 = (char) c11; - d1 = (char) c12; - - h0 = '0'; - h1 = '0'; - - i0 = '0'; - i1 = '0'; - } else if (c4 == -27 && c5 == -71 && c6 == -76 // 年 - && c9 == -26 && c10 == -100 && c11 == -120 // 月 - && c13 == -26 && c14 == -105 && c15 == -91 // 日 - ) { - y0 = (char) c0; - y1 = (char) c1; - y2 = (char) c2; - y3 = (char) c3; - - m0 = (char) c7; - m1 = (char) c8; - - d0 = '0'; - d1 = (char) c12; - - h0 = '0'; - h1 = '0'; - - i0 = '0'; - i1 = '0'; - } else if (c4 == '-' && c7 == '-' && (c10 == 'T' || c10 == ' ') && c12 == ':' && c14 == ':') { - y0 = (char) c0; - y1 = (char) c1; - y2 = (char) c2; - y3 = (char) c3; - - m0 = (char) c5; - m1 = (char) c6; - - d0 = (char) c8; - d1 = (char) c9; - - h0 = '0'; - h1 = (char) c11; - - i0 = '0'; - i1 = (char) c13; - - s1 = (char) c15; - } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':') { - y0 = (char) c6; - y1 = (char) c7; - y2 = (char) c8; - y3 = (char) c9; - - int month = DateUtils.month((char) c2, (char) c3, (char) c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - d0 = '0'; - d1 = (char) c0; - - h0 = (char) c11; - h1 = (char) c12; - - i0 = (char) c14; - i1 = (char) c15; - } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c12 == ':' && c14 == ':') { - // d MMM yyyy H:m:ss - // 6 DEC 2020 2:3:14 - d0 = '0'; - d1 = (char) c0; - - int month = DateUtils.month((char) c2, (char) c3, (char) c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - y0 = (char) c6; - y1 = (char) c7; - y2 = (char) c8; - y3 = (char) c9; - - h0 = '0'; - h1 = (char) c11; - - i0 = '0'; - i1 = (char) c13; - - s1 = (char) c15; - } else { - return null; - } - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - return null; - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - return null; - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - return null; - } - - 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 LocalDateTime.of(year, month, dom, hour, minute, second); - } - - /** - * yyyy-MM-ddTHH:mmZ - * yyyy-MM-dd HH:mmZ - * yyyy-M-dTHH:mm:ss - * yyyy-M-d HH:mm:ss - */ - public static LocalDateTime parseLocalDateTime17(char[] str, int off) { - if (off + 17 > str.length) { - String input = new String(str, off, str.length - off); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - char c0 = str[off]; - char c1 = str[off + 1]; - char c2 = str[off + 2]; - char c3 = str[off + 3]; - char c4 = str[off + 4]; - char c5 = str[off + 5]; - char c6 = str[off + 6]; - char c7 = str[off + 7]; - char c8 = str[off + 8]; - char c9 = str[off + 9]; - char c10 = str[off + 10]; - char c11 = str[off + 11]; - char c12 = str[off + 12]; - char c13 = str[off + 13]; - char c14 = str[off + 14]; - char c15 = str[off + 15]; - char c16 = str[off + 16]; - - char y0, y1, y2, y3, m0, m1, d0, d1, h0, h1, i0, i1, s0, s1; - int nanoOfSecond = 0; - if (c4 == '-' && c7 == '-' && (c10 == 'T' || c10 == ' ') && c13 == ':' && c16 == 'Z') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - - h0 = c11; - h1 = c12; - - i0 = c14; - i1 = c15; - - s0 = '0'; - s1 = '0'; - } else if (c4 == '-' && c6 == '-' && (c8 == ' ' || c8 == 'T') && c11 == ':' && c14 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = '0'; - m1 = c5; - - d0 = '0'; - d1 = c7; - - h0 = c9; - h1 = c10; - - i0 = c12; - i1 = c13; - - s0 = c15; - s1 = c16; - } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c14 == ':') { - y0 = c7; - y1 = c8; - y2 = c9; - y3 = c10; - - int month = DateUtils.month(c3, c4, c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - d0 = c0; - d1 = c1; - - h0 = c12; - h1 = c13; - - i0 = c15; - i1 = c16; - - s0 = '0'; - s1 = '0'; - } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c12 == ':' && c14 == ':') { - // d MMM yyyy H:m:ss - // 6 DEC 2020 1:3:14 - d0 = '0'; - d1 = c0; - - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - - h0 = '0'; - h1 = c11; - - i0 = '0'; - i1 = c13; - - s0 = c15; - s1 = c16; - } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c12 == ':' && c15 == ':') { - // d MMM yyyy H:mm:s - // 6 DEC 2020 1:13:4 - d0 = '0'; - d1 = c0; - - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - - h0 = '0'; - h1 = c11; - - i0 = c13; - i1 = c14; - - s0 = '0'; - s1 = c16; - } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':' && c15 == ':') { - // d MMM yyyy HH:m:s - // 6 DEC 2020 11:3:4 - d0 = '0'; - d1 = c0; - - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - - h0 = c11; - h1 = c12; - - i0 = '0'; - i1 = c14; - - s0 = '0'; - s1 = c16; - } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c13 == ':' && c15 == ':') { - // dd MMM yyyy H:m:s - // 16 DEC 2020 1:3:4 - d0 = c0; - d1 = c1; - - int month = DateUtils.month(c3, c4, c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - return null; - } - - y0 = c7; - y1 = c8; - y2 = c9; - y3 = c10; - - h0 = '0'; - h1 = c12; - - i0 = '0'; - i1 = c14; - - s0 = '0'; - s1 = c16; - } else { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c4; - m1 = c5; - - d0 = c6; - d1 = c7; - - h0 = c8; - h1 = c9; - - i0 = c10; - i1 = c11; - - s0 = c12; - s1 = c13; - - if (c14 >= '0' && c14 <= '9' - && c15 >= '0' && c15 <= '9' - && c16 >= '0' && c16 <= '9' - ) { - nanoOfSecond = ((c14 - '0') * 100 + (c15 - '0') * 10 + (c16 - '0')) * 1_000_000; - } else { - return null; - } - } - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - return null; - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - return null; - } - - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - return null; - } - - 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 LocalDateTime.of(year, month, dom, hour, minute, second, nanoOfSecond); - } - - /** - * yyyy-MM-ddTHH:mmZ - * yyyy-MM-dd HH:mmZ - * yyyy-M-dTHH:mm:ss - * yyyy-M-d HH:mm:ss - */ - public static LocalDateTime parseLocalDateTime17(byte[] str, int off) { - if (off + 17 > str.length) { - String input = new String(str, off, str.length - off); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - byte c0 = str[off]; - byte c1 = str[off + 1]; - byte c2 = str[off + 2]; - byte c3 = str[off + 3]; - byte c4 = str[off + 4]; - byte c5 = str[off + 5]; - byte c6 = str[off + 6]; - byte c7 = str[off + 7]; - byte c8 = str[off + 8]; - byte c9 = str[off + 9]; - byte c10 = str[off + 10]; - byte c11 = str[off + 11]; - byte c12 = str[off + 12]; - byte c13 = str[off + 13]; - byte c14 = str[off + 14]; - byte c15 = str[off + 15]; - byte c16 = str[off + 16]; - - char y0, y1, y2, y3, m0, m1, d0, d1, h0, h1, i0, i1, s0, s1; - int nanoOfSecond = 0; - if (c4 == '-' && c7 == '-' && (c10 == 'T' || c10 == ' ') && c13 == ':' && c16 == 'Z') { - y0 = (char) c0; - y1 = (char) c1; - y2 = (char) c2; - y3 = (char) c3; - - m0 = (char) c5; - m1 = (char) c6; - - d0 = (char) c8; - d1 = (char) c9; - - h0 = (char) c11; - h1 = (char) c12; - - i0 = (char) c14; - i1 = (char) c15; - - s0 = '0'; - s1 = '0'; - } else if (c4 == '-' && c6 == '-' && (c8 == ' ' || c8 == 'T') && c11 == ':' && c14 == ':') { - y0 = (char) c0; - y1 = (char) c1; - y2 = (char) c2; - y3 = (char) c3; - - m0 = '0'; - m1 = (char) c5; - - d0 = '0'; - d1 = (char) c7; - - h0 = (char) c9; - h1 = (char) c10; - - i0 = (char) c12; - i1 = (char) c13; - - s0 = (char) c15; - s1 = (char) c16; - } else if (c4 == -27 && c5 == -71 && c6 == -76 // 年 - && c9 == -26 && c10 == -100 && c11 == -120 // 月 - && c14 == -26 && c15 == -105 && c16 == -91 // 日 + char c10; + long millis; + char c0 = (char) chars[off]; + if (c0 == '"' && chars[len - 1] == '"') { + try (JSONReader jsonReader = JSONReader.of(chars, off, len, charset)) { + Date date = (Date) ObjectReaderImplDate.INSTANCE.readObject( + jsonReader, + null, + null, + 0 + ); + millis = date.getTime(); + } + } else if (len == 19) { + millis = DateUtils.parseMillis19(chars, off, zoneId); + } else if (len > 19 + // ISO Date with offset example '2011-12-03+01:00' + || (len == 16 && ((c10 = (char) chars[off + 10]) == '+' || c10 == '-')) ) { - y0 = (char) c0; - y1 = (char) c1; - y2 = (char) c2; - y3 = (char) c3; - - m0 = (char) c7; - m1 = (char) c8; - - d0 = (char) c12; - d1 = (char) c13; - - h0 = '0'; - h1 = '0'; - - i0 = '0'; - i1 = '0'; - - s0 = '0'; - s1 = '0'; - } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c14 == ':') { - y0 = (char) c7; - y1 = (char) c8; - y2 = (char) c9; - y3 = (char) c10; - - int month = DateUtils.month((char) c3, (char) c4, (char) c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - String input = new String(str, off, 17); + ZonedDateTime zdt = parseZonedDateTime(chars, off, len, zoneId); + if (zdt == null) { + String input = new String(chars, off, len - off); throw new DateTimeParseException("illegal input " + input, input, 0); } + millis = zdt.toInstant().toEpochMilli(); + } else if ((c0 == '-' || c0 >= '0' && c0 <= '9') && IOUtils.isNumber(chars, off, len)) { + millis = TypeUtils.parseLong(chars, off, len); + if (len == 8 && millis >= 19700101 && millis <= 21000101) { + int year = (int) millis / 10000; + int month = ((int) millis % 10000) / 100; + int dom = (int) millis % 100; - d0 = (char) c0; - d1 = (char) c1; - - h0 = (char) c12; - h1 = (char) c13; - - i0 = (char) c15; - i1 = (char) c16; - - s0 = '0'; - s1 = '0'; - } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c12 == ':' && c14 == ':') { - // d MMM yyyy H:m:ss - // 6 DEC 2020 1:3:14 - d0 = '0'; - d1 = (char) c0; - - int month = DateUtils.month((char) c2, (char) c3, (char) c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); + if (month >= 1 && month <= 12) { + int max = 31; + switch (month) { + case 2: + boolean leapYear = (year & 3) == 0 && ((year % 100) != 0 || (year % 400) == 0); + max = leapYear ? 29 : 28; + break; + case 4: + case 6: + case 9: + case 11: + max = 30; + break; + } + if (dom <= max) { + LocalDateTime ldt = LocalDateTime.of(year, month, dom, 0, 0, 0); + ZonedDateTime zdt = ZonedDateTime.ofLocal(ldt, zoneId, null); + long seconds = zdt.toEpochSecond(); + millis = seconds * 1000L; + } + } + } + } else { + char last = (char) chars[len - 1]; + if (last == 'Z') { + zoneId = UTC; + } + LocalDateTime ldt = DateUtils.parseLocalDateTime(chars, off, len); + if (ldt == null + // && "0000-00-00".equals(str) + && chars[off] == '0' + && chars[off + 1] == '0' + && chars[off + 2] == '0' + && chars[off + 3] == '0' + && chars[off + 4] == '-' + && chars[off + 5] == '0' + && chars[off + 6] == '0' + && chars[off + 7] == '-' + && chars[off + 8] == '0' + && chars[off + 9] == '0' + ) { + ldt = LocalDateTime.of(1970, 1, 1, 0, 0, 0); + } + ZonedDateTime zdt = ZonedDateTime.ofLocal(ldt, zoneId, null); + long seconds = zdt.toEpochSecond(); + int nanos = ldt.getNano(); + if (seconds < 0 && nanos > 0) { + millis = (seconds + 1) * 1000 + nanos / 1000_000 - 1000; } else { - String input = new String(str, off, 17); - throw new DateTimeParseException("illegal input " + input, input, 0); + millis = seconds * 1000L + nanos / 1000_000; } + } + return millis; + } - y0 = (char) c6; - y1 = (char) c7; - y2 = (char) c8; - y3 = (char) c9; - - h0 = '0'; - h1 = (char) c11; + public static long parseMillis(char[] bytes, int off, int len) { + return parseMillis(bytes, off, len, DEFAULT_ZONE_ID); + } - i0 = '0'; - i1 = (char) c13; + public static long parseMillis(char[] chars, int off, int len, ZoneId zoneId) { + if (chars == null || len == 0) { + return 0; + } - s0 = (char) c15; - s1 = (char) c16; - } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c12 == ':' && c15 == ':') { - // d MMM yyyy H:mm:s - // 6 DEC 2020 1:13:4 - d0 = '0'; - d1 = (char) c0; + if (len == 4 + && chars[off] == 'n' + && chars[off + 1] == 'u' + && chars[off + 2] == 'l' + && chars[off + 3] == 'l' + ) { + return 0; + } - int month = DateUtils.month((char) c2, (char) c3, (char) c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - String input = new String(str, off, 17); + char c10; + long millis; + char c0 = chars[off]; + if (c0 == '"' && chars[len - 1] == '"') { + try (JSONReader jsonReader = JSONReader.of(chars, off, len)) { + Date date = (Date) ObjectReaderImplDate.INSTANCE.readObject( + jsonReader, + null, + null, + 0 + ); + millis = date.getTime(); + } + } else if (len == 19) { + millis = DateUtils.parseMillis19(chars, off, zoneId); + } else if (len > 19 + // ISO Date with offset example '2011-12-03+01:00' + || (len == 16 && ((c10 = chars[off + 10]) == '+' || c10 == '-')) + ) { + ZonedDateTime zdt = parseZonedDateTime(chars, off, len, zoneId); + if (zdt == null) { + String input = new String(chars, off, len - off); throw new DateTimeParseException("illegal input " + input, input, 0); } + millis = zdt.toInstant().toEpochMilli(); + } else if ((c0 == '-' || c0 >= '0' && c0 <= '9') && IOUtils.isNumber(chars, off, len)) { + millis = TypeUtils.parseLong(chars, off, len); + if (len == 8 && millis >= 19700101 && millis <= 21000101) { + int year = (int) millis / 10000; + int month = ((int) millis % 10000) / 100; + int dom = (int) millis % 100; - y0 = (char) c6; - y1 = (char) c7; - y2 = (char) c8; - y3 = (char) c9; - - h0 = '0'; - h1 = (char) c11; - - i0 = (char) c13; - i1 = (char) c14; - - s0 = '0'; - s1 = (char) c16; - } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':' && c15 == ':') { - // d MMM yyyy HH:m:s - // 6 DEC 2020 11:3:4 - d0 = '0'; - d1 = (char) c0; + if (month >= 1 && month <= 12) { + int max = 31; + switch (month) { + case 2: + boolean leapYear = (year & 3) == 0 && ((year % 100) != 0 || (year % 400) == 0); + max = leapYear ? 29 : 28; + break; + case 4: + case 6: + case 9: + case 11: + max = 30; + break; + } + if (dom <= max) { + LocalDateTime ldt = LocalDateTime.of(year, month, dom, 0, 0, 0); + ZonedDateTime zdt = ZonedDateTime.ofLocal(ldt, zoneId, null); + long seconds = zdt.toEpochSecond(); + millis = seconds * 1000L; + } + } + } + } else { + char last = chars[len - 1]; + if (last == 'Z') { + len--; + zoneId = UTC; + } + LocalDateTime ldt = DateUtils.parseLocalDateTime(chars, off, len); + if (ldt == null + // && "0000-00-00".equals(str) + && chars[off] == '0' + && chars[off + 1] == '0' + && chars[off + 2] == '0' + && chars[off + 3] == '0' + && chars[off + 4] == '-' + && chars[off + 5] == '0' + && chars[off + 6] == '0' + && chars[off + 7] == '-' + && chars[off + 8] == '0' + && chars[off + 9] == '0' + ) { + ldt = LocalDateTime.of(1970, 1, 1, 0, 0, 0); + } - int month = DateUtils.month((char) c2, (char) c3, (char) c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - String input = new String(str, off, 17); + if (ldt == null) { + String input = new String(chars, off, len - off); throw new DateTimeParseException("illegal input " + input, input, 0); } - y0 = (char) c6; - y1 = (char) c7; - y2 = (char) c8; - y3 = (char) c9; - - h0 = (char) c11; - h1 = (char) c12; - - i0 = '0'; - i1 = (char) c14; - - s0 = '0'; - s1 = (char) c16; - } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c13 == ':' && c15 == ':') { - // dd MMM yyyy H:m:s - // 16 DEC 2020 1:3:4 - d0 = (char) c0; - d1 = (char) c1; - - int month = DateUtils.month((char) c3, (char) c4, (char) c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); + ZonedDateTime zdt = ZonedDateTime.ofLocal(ldt, zoneId, null); + long seconds = zdt.toEpochSecond(); + int nanos = ldt.getNano(); + if (seconds < 0 && nanos > 0) { + millis = (seconds + 1) * 1000 + nanos / 1000_000 - 1000; } else { - String input = new String(str, off, 17); - throw new DateTimeParseException("illegal input " + input, input, 0); + millis = seconds * 1000L + nanos / 1000_000; } + } + return millis; + } - y0 = (char) c7; - y1 = (char) c8; - y2 = (char) c9; - y3 = (char) c10; - - h0 = '0'; - h1 = (char) c12; + /** + * yyyy-m-d + * yyyyMMdd + * d-MMM-yy + */ + public static LocalDate parseLocalDate8(byte[] str, int off) { + if (off + 8 > str.length) { + return null; + } - i0 = '0'; - i1 = (char) c14; + char c1 = (char) str[off + 1]; + char c3 = (char) str[off + 3]; + char c4 = (char) str[off + 4]; - s0 = '0'; - s1 = (char) c16; + int year, month, dom; + if (c4 == '-' && str[off + 6] == '-') { + year = digit4(str, off); + month = digit1(str, off + 5); + dom = digit1(str, off + 7); + } else if (c1 == '/' && c3 == '/') { + month = digit1(str, off); + dom = digit1(str, off + 2); + year = digit4(str, off + 4); + } else if (c1 == '-' && str[off + 5] == '-') { + // d-MMM-yy + dom = digit1(str, off); + month = DateUtils.month((char) str[off + 2], c3, c4); + year = digit2(str, off + 6); + if (year != -1) { + year += 2000; + } } else { - y0 = (char) c0; - y1 = (char) c1; - y2 = (char) c2; - y3 = (char) c3; - - m0 = (char) c4; - m1 = (char) c5; + year = digit4(str, off); + month = digit2(str, off + 4); + dom = digit2(str, off + 6); + } - d0 = (char) c6; - d1 = (char) c7; + if ((year | month | dom) <= 0) { + return null; + } - h0 = (char) c8; - h1 = (char) c9; + return LocalDate.of(year, month, dom); + } - i0 = (char) c10; - i1 = (char) c11; + /** + * yyyy-m-d + * yyyyMMdd + * d-MMM-yy + */ + public static LocalDate parseLocalDate8(char[] str, int off) { + if (off + 8 > str.length) { + return null; + } - s0 = (char) c12; - s1 = (char) c13; + char c1 = str[off + 1]; + char c3 = str[off + 3]; + char c4 = str[off + 4]; - if (c14 >= '0' && c14 <= '9' - && c15 >= '0' && c15 <= '9' - && c16 >= '0' && c16 <= '9' - ) { - nanoOfSecond = ((c14 - '0') * 100 + (c15 - '0') * 10 + (c16 - '0')) * 1_000_000; - } else { - return null; + int year, month, dom; + if (c4 == '-' && str[off + 6] == '-') { + year = digit4(str, off); + month = digit1(str, off + 5); + dom = digit1(str, off + 7); + } else if (c1 == '/' && c3 == '/') { + month = digit1(str, off); + dom = digit1(str, off + 2); + year = digit4(str, off + 4); + } else if (c1 == '-' && str[off + 5] == '-') { + // d-MMM-yy + dom = digit1(str, off); + month = DateUtils.month((char) str[off + 2], c3, c4); + year = digit2(str, off + 6); + if (year != -1) { + year += 2000; } - } - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); } else { - String input = new String(str, off, 17); - throw new DateTimeParseException("illegal input " + input, input, 0); + year = digit4(str, off); + month = digit2(str, off + 4); + dom = digit2(str, off + 6); } - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); - } else { - String input = new String(str, off, 17); - throw new DateTimeParseException("illegal input " + input, input, 0); + if ((year | month | dom) <= 0) { + return null; } - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - String input = new String(str, off, 17); - throw new DateTimeParseException("illegal input " + input, input, 0); - } + return LocalDate.of(year, month, dom); + } - int hour; - if (h0 >= '0' && h0 <= '9' - && h1 >= '0' && h1 <= '9' - ) { - hour = (h0 - '0') * 10 + (h1 - '0'); - } else { - String input = new String(str, off, 17); - throw new DateTimeParseException("illegal input " + input, input, 0); + /** + * yyyy-MM-d + * yyyy-M-dd + * dd-MMM-yy + */ + public static LocalDate parseLocalDate9(byte[] str, int off) { + if (off + 9 > str.length) { + return null; } - int minute; - if (i0 >= '0' && i0 <= '9' - && i1 >= '0' && i1 <= '9' + char c1 = (char) str[off + 1]; + char c2 = (char) str[off + 2]; + char c4 = (char) str[off + 4]; + char c6 = (char) str[off + 6]; + char c7 = (char) str[off + 7]; + + int year, month, dom; + if ((c4 == '-' && c7 == '-') + || (c4 == '/' && c7 == '/') // tw : yyyy/mm/d ) { - minute = (i0 - '0') * 10 + (i1 - '0'); + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit1(str, off + 8); + } else if ((c4 == '-' && c6 == '-') + || (c4 == '/' && c6 == '/') // tw : yyyy/m/dd + ) { + year = digit4(str, off); + month = digit1(str, off + 5); + dom = digit2(str, off + 7); + } else if (c1 == '.' && c4 == '.') { + dom = digit1(str, off); + month = digit2(str, off + 2); + year = digit4(str, off + 5); + } else if ((c2 == '.' && c4 == '.') + || (c2 == '-' && c4 == '-') + ) { + dom = digit2(str, off); + month = digit1(str, off + 3); + year = digit4(str, off + 5); + } else if (c1 == '-' && c4 == '-') { + dom = digit1(str, off); + month = digit2(str, off + 2); + year = digit4(str, off + 5); + } else if (c2 == '-' && c6 == '-') { + // dd-MMM-yy + dom = digit2(str, off); + month = DateUtils.month((char) str[off + 3], c4, (char) str[off + 5]); + year = digit2(str, off + 7); + if (year != -1) { + year += 2000; + } + } else if (c1 == '/' && c4 == '/') { + // M/dd/dddd + month = digit1(str, off); + dom = digit2(str, off + 2); + year = digit4(str, off + 5); + } else if (c2 == '/' && c4 == '/') { + // MM/d/dddd + month = digit2(str, off); + dom = digit1(str, off + 3); + year = digit4(str, off + 5); } else { - String input = new String(str, off, 17); - throw new DateTimeParseException("illegal input " + input, input, 0); + return null; } - int second; - if (s0 >= '0' && s0 <= '9' - && s1 >= '0' && s1 <= '9' - ) { - second = (s0 - '0') * 10 + (s1 - '0'); - } else { - String input = new String(str, off, 17); - throw new DateTimeParseException("illegal input " + input, input, 0); + if ((year | month | dom) <= 0) { + return null; } - return LocalDateTime.of(year, month, dom, hour, minute, second, nanoOfSecond); + return LocalDate.of(year, month, dom); } /** - * yyyy-M-ddTHH:mm:ss - * yyyy-M-dd HH:mm:ss - * yyyy-MM-dTHH:mm:ss - * yyyy-MM-d HH:mm:ss - * yyyy-MM-ddTH:mm:ss - * yyyy-MM-dd H:mm:ss - * yyyy-MM-ddTHH:m:ss - * yyyy-MM-dd HH:m:ss - * yyyy-MM-ddTHH:mm:s - * yyyy-MM-dd HH:mm:s + * yyyy-MM-d + * yyyy-M-dd + * dd-MMM-yy */ - public static LocalDateTime parseLocalDateTime18(char[] str, int off) { - if (off + 18 > str.length) { - String input = new String(str, off, str.length - off); - throw new DateTimeParseException("illegal input " + input, input, 0); + public static LocalDate parseLocalDate9(char[] str, int off) { + if (off + 9 > str.length) { + return null; } - char c0 = str[off]; char c1 = str[off + 1]; char c2 = str[off + 2]; - char c3 = str[off + 3]; char c4 = str[off + 4]; - char c5 = str[off + 5]; char c6 = str[off + 6]; char c7 = str[off + 7]; char c8 = str[off + 8]; - char c9 = str[off + 9]; - char c10 = str[off + 10]; - char c11 = str[off + 11]; - char c12 = str[off + 12]; - char c13 = str[off + 13]; - char c14 = str[off + 14]; - char c15 = str[off + 15]; - char c16 = str[off + 16]; - char c17 = str[off + 17]; - char y0, y1, y2, y3, m0, m1, d0, d1, h0, h1, i0, i1, s0, s1; - if (c4 == '-' && c6 == '-' && (c9 == ' ' || c9 == 'T') && c12 == ':' && c15 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = '0'; - m1 = c5; - - d0 = c7; - d1 = c8; - - h0 = c10; - h1 = c11; - - i0 = c13; - i1 = c14; - - s0 = c16; - s1 = c17; - } else if (c4 == '-' && c7 == '-' && (c9 == ' ' || c9 == 'T') && c12 == ':' && c15 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = '0'; - d1 = c8; - - h0 = c10; - h1 = c11; - - i0 = c13; - i1 = c14; - - s0 = c16; - s1 = c17; - } else if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c12 == ':' && c15 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - - h0 = '0'; - h1 = c11; - - i0 = c13; - i1 = c14; - - s0 = c16; - s1 = c17; - } else if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c15 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; + int year, month, dom; + if ((c4 == '-' && c7 == '-') + || (c4 == '/' && c7 == '/') // tw : yyyy/mm/d + ) { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit1(str, off + 8); + } else if ((c4 == '-' && c6 == '-') + || (c4 == '/' && c6 == '/') // tw : yyyy/m/dd + ) { + year = digit4(str, off); + month = digit1(str, off + 5); + dom = digit2(str, off + 7); + } else if ((c4 == '年' && c6 == '月' && c8 == '日') + || (c4 == '년' && c6 == '월' && c8 == '일') + ) { + year = digit4(str, off); + month = digit1(str, off + 5); + dom = digit1(str, off + 7); + } else if (c1 == '.' && c4 == '.') { + dom = digit1(str, off); + month = digit2(str, off + 2); + year = digit4(str, off + 5); + } else if ((c2 == '.' && c4 == '.') + || (c2 == '-' && c4 == '-') + ) { + dom = digit2(str, off); + month = digit1(str, off + 3); + year = digit4(str, off + 5); + } else if (c1 == '-' && c4 == '-') { + dom = digit1(str, off); + month = digit2(str, off + 2); + year = digit4(str, off + 5); + } else if (c2 == '-' && c6 == '-') { + // dd-MMM-yy + dom = digit2(str, off); + month = DateUtils.month(str[off + 3], c4, str[off + 5]); + year = digit2(str, off + 7); + if (year != -1) { + year += 2000; + } + } else if (c1 == '/' && c4 == '/') { + // M/dd/dddd + month = digit1(str, off); + dom = digit2(str, off + 2); + year = digit4(str, off + 5); + } else if (c2 == '/' && c4 == '/') { + // MM/d/dddd + month = digit2(str, off); + dom = digit1(str, off + 3); + year = digit4(str, off + 5); + } else { + return null; + } - h0 = c11; - h1 = c12; + if ((year | month | dom) <= 0) { + return null; + } - i0 = '0'; - i1 = c14; + return LocalDate.of(year, month, dom); + } - s0 = c16; - s1 = c17; - } else if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; + /** + * yyyy-MM-dd + * yyyy/MM/dd + * MM/dd/yyyy + * dd.MM.yyyy + * yyyy年M月dd日 + * yyyy年MM月d日 + * yyyy MMM d + */ + public static LocalDate parseLocalDate10(byte[] str, int off) { + if (off + 10 > str.length) { + return null; + } - m0 = c5; - m1 = c6; + char c2 = (char) str[off + 2]; + char c4 = (char) str[off + 4]; + char c5 = (char) str[off + 5]; + char c7 = (char) str[off + 7]; - d0 = c8; - d1 = c9; + int year, month, dom; + if ((c4 == '-' && c7 == '-') || (c4 == '/' && c7 == '/')) { + // yyyy-MM-dd + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + } else if ((c2 == '.' && c5 == '.') || (c2 == '-' && c5 == '-')) { + // dd.MM.yyyy + dom = digit2(str, off); + month = digit2(str, off + 3); + year = digit4(str, off + 6); + } else if (c2 == '/' && c5 == '/') { + // MM/dd/yyyy + month = digit2(str, off); + dom = digit2(str, off + 3); + year = digit4(str, off + 6); + } else if (str[off + 1] == ' ' && c5 == ' ') { + dom = digit1(str, off); + month = DateUtils.month(c2, (char) str[off + 3], c4); + year = digit4(str, off + 6); + } else { + return null; + } - h0 = c11; - h1 = c12; + return (year | month | dom) <= 0 + ? null + : LocalDate.of(year, month, dom); + } - i0 = c14; - i1 = c15; + /** + * yyyy-MM-dd + * yyyy/MM/dd + * MM/dd/yyyy + * dd.MM.yyyy + * yyyy年M月dd日 + * yyyy年MM月d日 + * yyyy MMM d + */ + public static LocalDate parseLocalDate10(char[] str, int off) { + if (off + 10 > str.length) { + return null; + } - s0 = '0'; - s1 = c17; - } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c12 == ':' && c15 == ':') { - // d MMM yyyy H:mm:ss - // 6 DEC 2020 2:13:14 - d0 = '0'; - d1 = c0; + char c1 = str[off + 1]; + char c2 = str[off + 2]; + char c4 = str[off + 4]; + char c5 = str[off + 5]; + char c6 = str[off + 6]; + char c7 = str[off + 7]; + char c9 = str[off + 9]; - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } + int year, month, dom; + char y0, y1, y2, y3, m0, m1, d0, d1; + if ((c4 == '-' && c7 == '-') || (c4 == '/' && c7 == '/')) { + // yyyy-MM-dd + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + } else if ((c2 == '.' && c5 == '.') || (c2 == '-' && c5 == '-')) { + // dd.MM.yyyy + dom = digit2(str, off); + month = digit2(str, off + 3); + year = digit4(str, off + 6); + } else if (c2 == '/' && c5 == '/') { + // MM/dd/yyyy + month = digit2(str, off); + dom = digit2(str, off + 3); + year = digit4(str, off + 6); + } else if ((c4 == '年' && c6 == '月' && c9 == '日') + || (c4 == '년' && c6 == '월' && c9 == '일') + ) { + // yyyy年M月dd日 + year = digit4(str, off); + month = digit1(str, off + 5); + dom = digit2(str, off + 7); + } else if ((c4 == '年' && c7 == '月' && c9 == '日') + || (c4 == '년' && c7 == '월' && c9 == '일') + ) { + // yyyy年M月dd日 + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit1(str, off + 8); + } else if (c1 == ' ' && c5 == ' ') { + // d MMM yyyy + dom = digit1(str, off); + month = DateUtils.month(c2, (char) str[off + 3], c4); + year = digit4(str, off + 6); + } else { + return null; + } - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; + return (year | month | dom) <= 0 + ? null + : LocalDate.of(year, month, dom); + } - h0 = '0'; - h1 = c11; + /** + * yyyy年MM月dd日 + * yyyy년MM월dd일 + */ + public static LocalDate parseLocalDate11(char[] str, int off) { + if (off + 11 > str.length) { + return null; + } - i0 = c13; - i1 = c14; + char c4 = str[off + 4]; + char c7 = str[off + 7]; + char c10 = str[off + 10]; - s0 = c16; - s1 = c17; - } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':' && c15 == ':') { - // d MMM yyyy HH:m:ss - // 6 DEC 2020 12:3:14 - d0 = '0'; - d1 = c0; + int year, month, dom; + if ((c4 == '年' && c7 == '月' && c10 == '日') + || (c4 == '-' && c7 == '-' && c10 == 'Z') + || (c4 == '년' && c7 == '월' && c10 == '일')) { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + } else if (str[off + 2] == ' ' && str[off + 6] == ' ') { + year = digit4(str, off + 7); + month = DateUtils.month(str[off + 3], c4, str[off + 5]); + dom = digit2(str, off); + } else { + return null; + } - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } + if ((year | month | dom) < 0 || (year == 0 && month == 0 && dom == 0)) { + return null; + } - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; + return LocalDate.of(year, month, dom); + } - h0 = c11; - h1 = c12; + /** + * + */ + public static LocalDate parseLocalDate11(byte[] str, int off) { + if (off + 11 > str.length) { + return null; + } - i0 = '0'; - i1 = c14; + int year, month, dom; + if (str[off + 4] == '-' && str[off + 7] == '-' && str[off + 10] == 'Z') { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + } else if (str[off + 2] == ' ' && str[off + 6] == ' ') { + year = digit4(str, off + 7); + month = DateUtils.month((char) str[off + 3], (char) str[off + 4], (char) str[off + 5]); + dom = digit2(str, off); + } else { + return null; + } - s0 = c16; - s1 = c17; - } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':' && c16 == ':') { - // d MMM yyyy HH:m:ss - // 6 DEC 2020 12:3:14 - d0 = '0'; - d1 = c0; + if ((year | month | dom) < 0 || (year == 0 && month == 0 && dom == 0)) { + return null; + } - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } + return LocalDate.of(year, month, dom); + } - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; + public static LocalDateTime parseLocalDateTime12(char[] str, int off) { + if (off + 12 > str.length) { + String input = new String(str, off, str.length - off); + throw new DateTimeParseException("illegal input " + input, input, 0); + } - h0 = c11; - h1 = c12; + int year = digit4(str, off); + int month = digit2(str, off + 4); + int dom = digit2(str, off + 6); + int hour = digit2(str, off + 8); + int minute = digit2(str, off + 10); - i0 = c14; - i1 = c15; + if ((year | month | dom | hour | minute) < 0) { + String input = new String(str, off, off + 12); + throw new DateTimeParseException("illegal input " + input, input, 0); + } - s0 = '0'; - s1 = c17; - } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c14 == ':' && c16 == ':') { - // dd MMM yyyy HH:m:s - // 16 DEC 2020 12:3:4 - d0 = c0; - d1 = c1; + if (year == 0 && month == 0 && dom == 0 && hour == 0 && minute == 0) { + return null; + } - int month = DateUtils.month(c3, c4, c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } + return LocalDateTime.of(year, month, dom, hour, minute, 0); + } - y0 = c7; - y1 = c8; - y2 = c9; - y3 = c10; + /** + * parseLocalDateTime use format 'yyyyMMddHHmm' + */ + public static LocalDateTime parseLocalDateTime12(byte[] str, int off) { + if (off + 12 > str.length) { + String input = new String(str, off, str.length - off); + throw new DateTimeParseException("illegal input " + input, input, 0); + } - h0 = c12; - h1 = c13; + int year = digit4(str, off); + int month = digit2(str, off + 4); + int dom = digit2(str, off + 6); + int hour = digit2(str, off + 8); + int minute = digit2(str, off + 10); - i0 = '0'; - i1 = c15; + if ((year | month | dom | hour | minute) < 0) { + String input = new String(str, off, off + 12); + throw new DateTimeParseException("illegal input " + input, input, 0); + } - s0 = '0'; - s1 = c17; - } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c13 == ':' && c16 == ':') { - // dd MMM yyyy H:mm:s - // 16 DEC 2020 1:13:4 - d0 = c0; - d1 = c1; + if (year == 0 && month == 0 && dom == 0 && hour == 0 && minute == 0) { + return null; + } - int month = DateUtils.month(c3, c4, c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } + return LocalDateTime.of(year, month, dom, hour, minute, 0); + } - y0 = c7; - y1 = c8; - y2 = c9; - y3 = c10; + /** + * yyyyMMddHHmmss + */ + public static LocalDateTime parseLocalDateTime14(char[] str, int off) { + if (off + 14 > str.length) { + return null; + } - h0 = '0'; - h1 = c12; + int year = digit4(str, off); + int month = digit2(str, off + 4); + int dom = digit2(str, off + 6); + int hour = digit2(str, off + 8); + int minute = digit2(str, off + 10); + int second = digit2(str, off + 12); - i0 = c14; - i1 = c15; + return (year | month | dom | hour | minute | second) < 0 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second); + } - s0 = '0'; - s1 = c17; - } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c13 == ':' && c15 == ':') { - // dd MMM yyyy H:mm:s - // 16 DEC 2020 1:13:4 - d0 = c0; - d1 = c1; + /** + * yyyyMMddHHmmss + */ + public static LocalDateTime parseLocalDateTime14(byte[] str, int off) { + if (off + 14 > str.length) { + return null; + } - int month = DateUtils.month(c3, c4, c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } + int year = digit4(str, off); + int month = digit2(str, off + 4); + int dom = digit2(str, off + 6); + int hour = digit2(str, off + 8); + int minute = digit2(str, off + 10); + int second = digit2(str, off + 12); - y0 = c7; - y1 = c8; - y2 = c9; - y3 = c10; + return (year | month | dom | hour | minute | second) < 0 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second); + } - h0 = '0'; - h1 = c12; + /** + * yyyy-MM-ddTHH:mm + * yyyy-MM-dd HH:mm + * yyyyMMddTHHmmssZ + * yyyy-MM-ddTH:m:s + * yyyy-MM-dd H:m:s + */ + public static LocalDateTime parseLocalDateTime16(char[] str, int off) { + if (off + 16 > str.length) { + return null; + } - i0 = '0'; - i1 = c14; + char c1 = str[off + 1]; + char c2 = str[off + 2]; + char c3 = str[off + 3]; + char c4 = str[off + 4]; + char c5 = str[off + 5]; + char c7 = str[off + 7]; + char c10 = str[off + 10]; + char c12 = str[off + 12]; + char c13 = str[off + 13]; + char c14 = str[off + 14]; - s0 = c16; - s1 = c17; + int year, month, dom, hour, minute, second = 0; + if (c4 == '-' && c7 == '-' && (c10 == 'T' || c10 == ' ') && c13 == ':') { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + } else if (str[off + 8] == 'T' && str[off + 15] == 'Z') { + year = digit4(str, off); + month = digit2(str, off + 4); + dom = digit2(str, off + 6); + hour = digit2(str, off + 9); + minute = digit2(str, off + 11); + second = digit2(str, off + 13); + } else if (c4 == '-' && c7 == '-' && (c10 == 'T' || c10 == ' ') && c12 == ':' && c14 == ':') { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + hour = digit1(str, off + 11); + minute = digit1(str, off + 13); + second = digit1(str, off + 15); + } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':') { + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c12 == ':' && c14 == ':') { + // d MMM yyyy H:m:ss + // 6 DEC 2020 2:3:14 + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit1(str, off + 11); + minute = digit1(str, off + 13); + second = digit1(str, off + 15); } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); + return null; } - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); + return (year | month | dom | hour | minute | second) < 0 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second); + } + + /** + * yyyy-MM-ddTHH:mm + * yyyy-MM-dd HH:mm + * yyyyMMddTHHmmssZ + * yyyy-MM-ddTH:m:s + * yyyy-MM-dd H:m:s + */ + public static LocalDateTime parseLocalDateTime16(byte[] str, int off) { + if (off + 16 > str.length) { + return null; } - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' + byte c1 = str[off + 1]; + byte c2 = str[off + 2]; + byte c3 = str[off + 3]; + byte c4 = str[off + 4]; + byte c5 = str[off + 5]; + byte c6 = str[off + 6]; + byte c7 = str[off + 7]; + byte c8 = str[off + 8]; + byte c9 = str[off + 9]; + byte c10 = str[off + 10]; + byte c11 = str[off + 11]; + byte c12 = str[off + 12]; + byte c13 = str[off + 13]; + byte c14 = str[off + 14]; + byte c15 = str[off + 15]; + + int year, month, dom, hour, minute, second = 0; + if (c4 == '-' && c7 == '-' && (c10 == 'T' || c10 == ' ') && c13 == ':') { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + } else if (str[off + 8] == 'T' && str[off + 15] == 'Z') { + year = digit4(str, off); + month = digit2(str, off + 4); + dom = digit2(str, off + 6); + hour = digit2(str, off + 9); + minute = digit2(str, off + 11); + second = digit2(str, off + 13); + } else if (c4 == '-' && c7 == '-' && (c10 == 'T' || c10 == ' ') && c12 == ':' && c14 == ':') { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + hour = digit1(str, off + 11); + minute = digit1(str, off + 13); + second = digit1(str, off + 15); + } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':') { + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c12 == ':' && c14 == ':') { + // d MMM yyyy H:m:ss + // 6 DEC 2020 2:3:14 + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit1(str, off + 11); + minute = digit1(str, off + 13); + second = digit1(str, off + 15); + } else if (c4 == -27 && c5 == -71 && c6 == -76 // 年 + && c8 == -26 && c9 == -100 && c10 == -120 // 月 + && c13 == -26 && c14 == -105 && c15 == -91 // 日 ) { - month = (m0 - '0') * 10 + (m1 - '0'); + year = digit4(str, off); + month = digit1(str, off + 7); + dom = digit2(str, off + 11); + hour = 0; + minute = 0; + } else if (c4 == -27 && c5 == -71 && c6 == -76 // 年 + && c9 == -26 && c10 == -100 && c11 == -120 // 月 + && c13 == -26 && c14 == -105 && c15 == -91 // 日 + ) { + year = digit4(str, off); + month = digit2(str, off + 7); + dom = digit1(str, off + 12); + hour = 0; + minute = 0; } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); + return null; } - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - String input = new String(str, off, 18); + return (year | month | dom | hour | minute | second) < 0 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second); + } + + /** + * yyyy-MM-ddTHH:mmZ + * yyyy-MM-dd HH:mmZ + * yyyy-M-dTHH:mm:ss + * yyyy-M-d HH:mm:ss + */ + public static LocalDateTime parseLocalDateTime17(char[] str, int off) { + if (off + 17 > str.length) { + String input = new String(str, off, str.length - off); throw new DateTimeParseException("illegal input " + input, input, 0); } - int hour; - if (h0 >= '0' && h0 <= '9' - && h1 >= '0' && h1 <= '9' - ) { - hour = (h0 - '0') * 10 + (h1 - '0'); + char c1 = str[off + 1]; + char c2 = str[off + 2]; + char c3 = str[off + 3]; + char c4 = str[off + 4]; + char c5 = str[off + 5]; + char c6 = str[off + 6]; + char c7 = str[off + 7]; + char c8 = str[off + 8]; + char c10 = str[off + 10]; + char c11 = str[off + 11]; + char c12 = str[off + 12]; + char c13 = str[off + 13]; + char c14 = str[off + 14]; + char c15 = str[off + 15]; + char c16 = str[off + 16]; + + int year, month, dom, hour, minute, second = 0, nanoOfSecond = 0; + if (c4 == '-' && c7 == '-' && (c10 == 'T' || c10 == ' ') && c13 == ':' && c16 == 'Z') { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + second = 0; + } else if (c4 == '-' && c6 == '-' && (c8 == ' ' || c8 == 'T') && c11 == ':' && c14 == ':') { + year = digit4(str, off); + month = digit1(str, off + 5); + dom = digit1(str, off + 7); + hour = digit2(str, off + 9); + minute = digit2(str, off + 12); + second = digit2(str, off + 15); + } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c14 == ':') { + dom = digit2(str, off); + month = DateUtils.month(c3, c4, c5); + year = digit4(str, off + 7); + hour = digit2(str, off + 12); + minute = digit2(str, off + 15); + second = 0; + } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c12 == ':' && c14 == ':') { + // d MMM yyyy H:m:ss + // 6 DEC 2020 1:3:14 + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit1(str, off + 11); + minute = digit1(str, off + 13); + second = digit2(str, off + 15); + } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c12 == ':' && c15 == ':') { + // d MMM yyyy H:mm:s + // 6 DEC 2020 1:13:4 + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit1(str, off + 11); + minute = digit2(str, off + 13); + second = digit1(str, off + 16); + } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':' && c15 == ':') { + // d MMM yyyy HH:m:s + // 6 DEC 2020 11:3:4 + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit2(str, off + 11); + minute = digit1(str, off + 14); + second = digit1(str, off + 16); + } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c13 == ':' && c15 == ':') { + // dd MMM yyyy H:m:s + // 16 DEC 2020 1:3:4 + dom = digit2(str, off); + month = DateUtils.month(c3, c4, c5); + year = digit4(str, off + 7); + hour = digit1(str, off + 12); + minute = digit1(str, off + 14); + second = digit1(str, off + 16); } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); + year = digit4(str, off); + month = digit2(str, off + 4); + dom = digit2(str, off + 6); + hour = digit2(str, off + 8); + minute = digit2(str, off + 10); + second = digit2(str, off + 12); + nanoOfSecond = readNanos(str, 3, off + 14); } - int minute; - if (i0 >= '0' && i0 <= '9' - && i1 >= '0' && i1 <= '9' - ) { - minute = (i0 - '0') * 10 + (i1 - '0'); - } else { - String input = new String(str, off, 18); + return (year | month | dom | hour | minute | second | nanoOfSecond) < 0 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second, nanoOfSecond); + } + + /** + * yyyy-MM-ddTHH:mmZ + * yyyy-MM-dd HH:mmZ + * yyyy-M-dTHH:mm:ss + * yyyy-M-d HH:mm:ss + */ + public static LocalDateTime parseLocalDateTime17(byte[] str, int off) { + if (off + 17 > str.length) { + String input = new String(str, off, str.length - off); throw new DateTimeParseException("illegal input " + input, input, 0); } - int second; - if (s0 >= '0' && s0 <= '9' - && s1 >= '0' && s1 <= '9' + byte c1 = str[off + 1]; + byte c2 = str[off + 2]; + byte c3 = str[off + 3]; + byte c4 = str[off + 4]; + byte c5 = str[off + 5]; + byte c6 = str[off + 6]; + byte c7 = str[off + 7]; + byte c8 = str[off + 8]; + byte c9 = str[off + 9]; + byte c10 = str[off + 10]; + byte c11 = str[off + 11]; + byte c12 = str[off + 12]; + byte c13 = str[off + 13]; + byte c14 = str[off + 14]; + byte c15 = str[off + 15]; + byte c16 = str[off + 16]; + + int year, month, dom, hour, minute, second = 0, nanoOfSecond = 0; + if (c4 == '-' && c7 == '-' && (c10 == 'T' || c10 == ' ') && c13 == ':' && c16 == 'Z') { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + second = 0; + } else if (c4 == '-' && c6 == '-' && (c8 == ' ' || c8 == 'T') && c11 == ':' && c14 == ':') { + year = digit4(str, off); + month = digit1(str, off + 5); + dom = digit1(str, off + 7); + hour = digit2(str, off + 9); + minute = digit2(str, off + 12); + second = digit2(str, off + 15); + } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c14 == ':') { + dom = digit2(str, off); + month = DateUtils.month(c3, c4, c5); + year = digit4(str, off + 7); + hour = digit2(str, off + 12); + minute = digit2(str, off + 15); + second = 0; + } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c12 == ':' && c14 == ':') { + // d MMM yyyy H:m:ss + // 6 DEC 2020 1:3:14 + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit1(str, off + 11); + minute = digit1(str, off + 13); + second = digit2(str, off + 15); + } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c12 == ':' && c15 == ':') { + // d MMM yyyy H:mm:s + // 6 DEC 2020 1:13:4 + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit1(str, off + 11); + minute = digit2(str, off + 13); + second = digit1(str, off + 16); + } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':' && c15 == ':') { + // d MMM yyyy HH:m:s + // 6 DEC 2020 11:3:4 + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit2(str, off + 11); + minute = digit1(str, off + 14); + second = digit1(str, off + 16); + } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c13 == ':' && c15 == ':') { + // dd MMM yyyy H:m:s + // 16 DEC 2020 1:3:4 + dom = digit2(str, off); + month = DateUtils.month(c3, c4, c5); + year = digit4(str, off + 7); + hour = digit1(str, off + 12); + minute = digit1(str, off + 14); + second = digit1(str, off + 16); + } else if (c4 == -27 && c5 == -71 && c6 == -76 // 年 + && c9 == -26 && c10 == -100 && c11 == -120 // 月 + && c14 == -26 && c15 == -105 && c16 == -91 // 日 ) { - second = (s0 - '0') * 10 + (s1 - '0'); + year = digit4(str, off); + month = digit2(str, off + 7); + dom = digit2(str, off + 12); + hour = 0; + minute = 0; } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); + year = digit4(str, off); + month = digit2(str, off + 4); + dom = digit2(str, off + 6); + hour = digit2(str, off + 8); + minute = digit2(str, off + 10); + second = digit2(str, off + 12); + nanoOfSecond = readNanos(str, 3, off + 14); } - return LocalDateTime.of(year, month, dom, hour, minute, second); + return (year | month | dom | hour | minute | second | nanoOfSecond) < 0 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second, nanoOfSecond); } /** @@ -4645,371 +1898,263 @@ public static LocalDateTime parseLocalDateTime18(char[] str, int off) { * yyyy-MM-dd H:mm:ss * yyyy-MM-ddTHH:m:ss * yyyy-MM-dd HH:m:ss - * yyyy-MM-ddTHH:mm:s - * yyyy-MM-dd HH:mm:s - */ - public static LocalDateTime parseLocalDateTime18(byte[] str, int off) { - if (off + 18 > str.length) { - String input = new String(str, off, str.length - off); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - char c0 = (char) str[off]; - char c1 = (char) str[off + 1]; - char c2 = (char) str[off + 2]; - char c3 = (char) str[off + 3]; - char c4 = (char) str[off + 4]; - char c5 = (char) str[off + 5]; - char c6 = (char) str[off + 6]; - char c7 = (char) str[off + 7]; - char c8 = (char) str[off + 8]; - char c9 = (char) str[off + 9]; - char c10 = (char) str[off + 10]; - char c11 = (char) str[off + 11]; - char c12 = (char) str[off + 12]; - char c13 = (char) str[off + 13]; - char c14 = (char) str[off + 14]; - char c15 = (char) str[off + 15]; - char c16 = (char) str[off + 16]; - char c17 = (char) str[off + 17]; - - char y0, y1, y2, y3, m0, m1, d0, d1, h0, h1, i0, i1, s0, s1; - if (c4 == '-' && c6 == '-' && (c9 == ' ' || c9 == 'T') && c12 == ':' && c15 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = '0'; - m1 = c5; - - d0 = c7; - d1 = c8; - - h0 = c10; - h1 = c11; - - i0 = c13; - i1 = c14; - - s0 = c16; - s1 = c17; - } else if (c4 == '-' && c7 == '-' && (c9 == ' ' || c9 == 'T') && c12 == ':' && c15 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = '0'; - d1 = c8; - - h0 = c10; - h1 = c11; - - i0 = c13; - i1 = c14; - - s0 = c16; - s1 = c17; - } else if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c12 == ':' && c15 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - - h0 = '0'; - h1 = c11; - - i0 = c13; - i1 = c14; - - s0 = c16; - s1 = c17; - } else if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c15 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - - h0 = c11; - h1 = c12; - - i0 = '0'; - i1 = c14; - - s0 = c16; - s1 = c17; - } else if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - - h0 = c11; - h1 = c12; + * yyyy-MM-ddTHH:mm:s + * yyyy-MM-dd HH:mm:s + */ + public static LocalDateTime parseLocalDateTime18(char[] str, int off) { + if (off + 18 > str.length) { + String input = new String(str, off, str.length - off); + throw new DateTimeParseException("illegal input " + input, input, 0); + } - i0 = c14; - i1 = c15; + char c1 = str[off + 1]; + char c2 = str[off + 2]; + char c3 = str[off + 3]; + char c4 = str[off + 4]; + char c5 = str[off + 5]; + char c6 = str[off + 6]; + char c7 = str[off + 7]; + char c9 = str[off + 9]; + char c10 = str[off + 10]; + char c11 = str[off + 11]; + char c12 = str[off + 12]; + char c13 = str[off + 13]; + char c14 = str[off + 14]; + char c15 = str[off + 15]; + char c16 = str[off + 16]; - s0 = '0'; - s1 = c17; + int year, month, dom, hour, minute, second; + if (c4 == '-' && c6 == '-' && (c9 == ' ' || c9 == 'T') && c12 == ':' && c15 == ':') { + year = digit4(str, off); + month = digit1(str, off + 5); + dom = digit2(str, off + 7); + hour = digit2(str, off + 10); + minute = digit2(str, off + 13); + second = digit2(str, off + 16); + } else if (c4 == '-' && c7 == '-' && (c9 == ' ' || c9 == 'T') && c12 == ':' && c15 == ':') { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit1(str, off + 8); + hour = digit2(str, off + 10); + minute = digit2(str, off + 13); + second = digit2(str, off + 16); + } else if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c12 == ':' && c15 == ':') { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + hour = digit1(str, off + 11); + minute = digit2(str, off + 13); + second = digit2(str, off + 16); + } else if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c15 == ':') { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + hour = digit2(str, off + 11); + minute = digit1(str, off + 14); + second = digit2(str, off + 16); + } else if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':') { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + second = digit1(str, off + 17); } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c12 == ':' && c15 == ':') { // d MMM yyyy H:mm:ss // 6 DEC 2020 2:13:14 - d0 = '0'; - d1 = c0; - - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - - h0 = '0'; - h1 = c11; - - i0 = c13; - i1 = c14; - - s0 = c16; - s1 = c17; + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit1(str, off + 11); + minute = digit2(str, off + 13); + second = digit2(str, off + 16); } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':' && c15 == ':') { // d MMM yyyy HH:m:ss // 6 DEC 2020 12:3:14 - d0 = '0'; - d1 = c0; - - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - - h0 = c11; - h1 = c12; - - i0 = '0'; - i1 = c14; - - s0 = c16; - s1 = c17; + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit2(str, off + 11); + minute = digit1(str, off + 14); + second = digit2(str, off + 16); } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':' && c16 == ':') { // d MMM yyyy HH:m:ss // 6 DEC 2020 12:3:14 - d0 = '0'; - d1 = c0; - - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - - h0 = c11; - h1 = c12; - - i0 = c14; - i1 = c15; - - s0 = '0'; - s1 = c17; + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + second = digit1(str, off + 17); } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c14 == ':' && c16 == ':') { // dd MMM yyyy HH:m:s // 16 DEC 2020 12:3:4 - d0 = c0; - d1 = c1; - - int month = DateUtils.month(c3, c4, c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - y0 = c7; - y1 = c8; - y2 = c9; - y3 = c10; - - h0 = c12; - h1 = c13; - - i0 = '0'; - i1 = c15; - - s0 = '0'; - s1 = c17; + dom = digit2(str, off); + month = DateUtils.month(c3, c4, c5); + year = digit4(str, off + 7); + hour = digit2(str, off + 12); + minute = digit1(str, off + 15); + second = digit1(str, off + 17); } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c13 == ':' && c16 == ':') { // dd MMM yyyy H:mm:s // 16 DEC 2020 1:13:4 - d0 = c0; - d1 = c1; - - int month = DateUtils.month(c3, c4, c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - y0 = c7; - y1 = c8; - y2 = c9; - y3 = c10; - - h0 = '0'; - h1 = c12; - - i0 = c14; - i1 = c15; - - s0 = '0'; - s1 = c17; + dom = digit2(str, off); + month = DateUtils.month(c3, c4, c5); + year = digit4(str, off + 7); + hour = digit1(str, off + 12); + minute = digit2(str, off + 14); + second = digit1(str, off + 17); } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c13 == ':' && c15 == ':') { // dd MMM yyyy H:mm:s // 16 DEC 2020 1:13:4 - d0 = c0; - d1 = c1; - - int month = DateUtils.month(c3, c4, c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - y0 = c7; - y1 = c8; - y2 = c9; - y3 = c10; - - h0 = '0'; - h1 = c12; - - i0 = '0'; - i1 = c14; - - s0 = c16; - s1 = c17; - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - int year; - if (y0 >= '0' && y0 <= '9' - && y1 >= '0' && y1 <= '9' - && y2 >= '0' && y2 <= '9' - && y3 >= '0' && y3 <= '9' - ) { - year = (y0 - '0') * 1000 + (y1 - '0') * 100 + (y2 - '0') * 10 + (y3 - '0'); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } - - int month; - if (m0 >= '0' && m0 <= '9' - && m1 >= '0' && m1 <= '9' - ) { - month = (m0 - '0') * 10 + (m1 - '0'); + dom = digit2(str, off); + month = DateUtils.month(c3, c4, c5); + year = digit4(str, off + 7); + hour = digit1(str, off + 12); + minute = digit1(str, off + 14); + second = digit2(str, off + 16); } else { String input = new String(str, off, 18); throw new DateTimeParseException("illegal input " + input, input, 0); } - int dom; - if (d0 >= '0' && d0 <= '9' - && d1 >= '0' && d1 <= '9' - ) { - dom = (d0 - '0') * 10 + (d1 - '0'); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } + return (year | month | dom | hour | minute | second) < 0 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second); + } - int hour; - if (h0 >= '0' && h0 <= '9' - && h1 >= '0' && h1 <= '9' - ) { - hour = (h0 - '0') * 10 + (h1 - '0'); - } else { - String input = new String(str, off, 18); + /** + * yyyy-M-ddTHH:mm:ss + * yyyy-M-dd HH:mm:ss + * yyyy-MM-dTHH:mm:ss + * yyyy-MM-d HH:mm:ss + * yyyy-MM-ddTH:mm:ss + * yyyy-MM-dd H:mm:ss + * yyyy-MM-ddTHH:m:ss + * yyyy-MM-dd HH:m:ss + * yyyy-MM-ddTHH:mm:s + * yyyy-MM-dd HH:mm:s + */ + public static LocalDateTime parseLocalDateTime18(byte[] str, int off) { + if (off + 18 > str.length) { + String input = new String(str, off, str.length - off); throw new DateTimeParseException("illegal input " + input, input, 0); } - int minute; - if (i0 >= '0' && i0 <= '9' - && i1 >= '0' && i1 <= '9' - ) { - minute = (i0 - '0') * 10 + (i1 - '0'); - } else { - String input = new String(str, off, 18); - throw new DateTimeParseException("illegal input " + input, input, 0); - } + byte c1 = str[off + 1]; + byte c2 = str[off + 2]; + byte c3 = str[off + 3]; + byte c4 = str[off + 4]; + byte c5 = str[off + 5]; + byte c6 = str[off + 6]; + byte c7 = str[off + 7]; + byte c9 = str[off + 9]; + byte c10 = str[off + 10]; + byte c11 = str[off + 11]; + byte c12 = str[off + 12]; + byte c13 = str[off + 13]; + byte c14 = str[off + 14]; + byte c15 = str[off + 15]; + byte c16 = str[off + 16]; - int second; - if (s0 >= '0' && s0 <= '9' - && s1 >= '0' && s1 <= '9' - ) { - second = (s0 - '0') * 10 + (s1 - '0'); + int year, month, dom, hour, minute, second; + if (c4 == '-' && c6 == '-' && (c9 == ' ' || c9 == 'T') && c12 == ':' && c15 == ':') { + year = digit4(str, off); + month = digit1(str, off + 5); + dom = digit2(str, off + 7); + hour = digit2(str, off + 10); + minute = digit2(str, off + 13); + second = digit2(str, off + 16); + } else if (c4 == '-' && c7 == '-' && (c9 == ' ' || c9 == 'T') && c12 == ':' && c15 == ':') { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit1(str, off + 8); + hour = digit2(str, off + 10); + minute = digit2(str, off + 13); + second = digit2(str, off + 16); + } else if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c12 == ':' && c15 == ':') { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + hour = digit1(str, off + 11); + minute = digit2(str, off + 13); + second = digit2(str, off + 16); + } else if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c15 == ':') { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + hour = digit2(str, off + 11); + minute = digit1(str, off + 14); + second = digit2(str, off + 16); + } else if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':') { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + second = digit1(str, off + 17); + } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c12 == ':' && c15 == ':') { + // d MMM yyyy H:mm:ss + // 6 DEC 2020 2:13:14 + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit1(str, off + 11); + minute = digit2(str, off + 13); + second = digit2(str, off + 16); + } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':' && c15 == ':') { + // d MMM yyyy HH:m:ss + // 6 DEC 2020 12:3:14 + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit2(str, off + 11); + minute = digit1(str, off + 14); + second = digit2(str, off + 16); + } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':' && c16 == ':') { + // d MMM yyyy HH:m:ss + // 6 DEC 2020 12:3:14 + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + second = digit1(str, off + 17); + } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c14 == ':' && c16 == ':') { + // dd MMM yyyy HH:m:s + // 16 DEC 2020 12:3:4 + dom = digit2(str, off); + month = DateUtils.month(c3, c4, c5); + year = digit4(str, off + 7); + hour = digit2(str, off + 12); + minute = digit1(str, off + 15); + second = digit1(str, off + 17); + } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c13 == ':' && c16 == ':') { + // dd MMM yyyy H:mm:s + // 16 DEC 2020 1:13:4 + dom = digit2(str, off); + month = DateUtils.month(c3, c4, c5); + year = digit4(str, off + 7); + hour = digit1(str, off + 12); + minute = digit2(str, off + 14); + second = digit1(str, off + 17); + } else if (c2 == ' ' && c6 == ' ' && c11 == ' ' && c13 == ':' && c15 == ':') { + // dd MMM yyyy H:mm:s + // 16 DEC 2020 1:13:4 + dom = digit2(str, off); + month = DateUtils.month(c3, c4, c5); + year = digit4(str, off + 7); + hour = digit1(str, off + 12); + minute = digit1(str, off + 14); + second = digit2(str, off + 16); } else { String input = new String(str, off, 18); throw new DateTimeParseException("illegal input " + input, input, 0); } - return LocalDateTime.of(year, month, dom, hour, minute, second); + return (year | month | dom | hour | minute | second) < 0 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second); } /** @@ -5023,118 +2168,48 @@ public static LocalDateTime parseLocalDateTime19(char[] str, int off) { return null; } - char c0 = str[off]; char c1 = str[off + 1]; char c2 = str[off + 2]; char c3 = str[off + 3]; char c4 = str[off + 4]; char c5 = str[off + 5]; - char c6 = str[off + 6]; char c7 = str[off + 7]; - char c8 = str[off + 8]; - char c9 = str[off + 9]; char c10 = str[off + 10]; - char c11 = str[off + 11]; - char c12 = str[off + 12]; char c13 = str[off + 13]; - char c14 = str[off + 14]; - char c15 = str[off + 15]; char c16 = str[off + 16]; - char c17 = str[off + 17]; - char c18 = str[off + 18]; - - char y0, y1, y2, y3, m0, m1, d0, d1, h0, h1, i0, i1, s0, s1; - if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - - h0 = c11; - h1 = c12; - - i0 = c14; - i1 = c15; - - s0 = c17; - s1 = c18; - } else if (c4 == '/' && c7 == '/' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - - h0 = c11; - h1 = c12; - - i0 = c14; - i1 = c15; - - s0 = c17; - s1 = c18; + int year, month, dom, hour, minute, second; + if (((c4 == '-' && c7 == '-') || (c4 == '/' && c7 == '/')) + && (c10 == ' ' || c10 == 'T') + && c13 == ':' && c16 == ':' + ) { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + second = digit2(str, off + 17); } else if (c2 == '/' && c5 == '/' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':') { - d0 = c0; - d1 = c1; - - m0 = c3; - m1 = c4; - - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - - h0 = c11; - h1 = c12; - - i0 = c14; - i1 = c15; - - s0 = c17; - s1 = c18; + dom = digit2(str, off); + month = digit2(str, off + 3); + year = digit4(str, off + 6); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + second = digit2(str, off + 17); } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':' && c16 == ':') { - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - m0 = '0'; - m1 = '0'; - } - - d0 = '0'; - d1 = c0; - - h0 = c11; - h1 = c12; - - i0 = c14; - i1 = c15; - - s0 = c17; - s1 = c18; + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + second = digit2(str, off + 17); } else { return null; } - return localDateTime(y0, y1, y2, y3, m0, m1, d0, d1, h0, h1, i0, i1, s0, s1); + return (year | month | dom | hour | minute | second) <= 0 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second); } public static LocalDateTime parseLocalDateTime19(String str, int off) { @@ -5159,618 +2234,311 @@ public static LocalDateTime parseLocalDateTime19(String str, int off) { /** * yyyy-MM-ddTHH:mm:ss - * yyyy-MM-dd HH:mm:ss - * yyyy/MM/ddTHH:mm:ss - * yyyy/MM/dd HH:mm:ss - */ - public static LocalDateTime parseLocalDateTime19(byte[] str, int off) { - if (off + 19 > str.length) { - return null; - } - - char c0 = (char) str[off]; - char c1 = (char) str[off + 1]; - char c2 = (char) str[off + 2]; - char c3 = (char) str[off + 3]; - char c4 = (char) str[off + 4]; - char c5 = (char) str[off + 5]; - char c6 = (char) str[off + 6]; - char c7 = (char) str[off + 7]; - char c8 = (char) str[off + 8]; - char c9 = (char) str[off + 9]; - char c10 = (char) str[off + 10]; - char c11 = (char) str[off + 11]; - char c12 = (char) str[off + 12]; - char c13 = (char) str[off + 13]; - char c14 = (char) str[off + 14]; - char c15 = (char) str[off + 15]; - char c16 = (char) str[off + 16]; - char c17 = (char) str[off + 17]; - char c18 = (char) str[off + 18]; - - char y0, y1, y2, y3, m0, m1, d0, d1, h0, h1, i0, i1, s0, s1; - if (c4 == '-' && c7 == '-' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - - h0 = c11; - h1 = c12; - - i0 = c14; - i1 = c15; - - s0 = c17; - s1 = c18; - } else if (c4 == '/' && c7 == '/' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':') { - y0 = c0; - y1 = c1; - y2 = c2; - y3 = c3; - - m0 = c5; - m1 = c6; - - d0 = c8; - d1 = c9; - - h0 = c11; - h1 = c12; - - i0 = c14; - i1 = c15; - - s0 = c17; - s1 = c18; - } else if (c2 == '/' && c5 == '/' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':') { - d0 = c0; - d1 = c1; - - m0 = c3; - m1 = c4; - - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - - h0 = c11; - h1 = c12; - - i0 = c14; - i1 = c15; - - s0 = c17; - s1 = c18; - } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':' && c16 == ':') { - y0 = c6; - y1 = c7; - y2 = c8; - y3 = c9; - - int month = DateUtils.month(c2, c3, c4); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - m0 = '0'; - m1 = '0'; - } - - d0 = '0'; - d1 = c0; - - h0 = c11; - h1 = c12; - - i0 = c14; - i1 = c15; - - s0 = c17; - s1 = c18; - } else { - return null; - } - - return localDateTime(y0, y1, y2, y3, m0, m1, d0, d1, h0, h1, i0, i1, s0, s1); - } - - public static LocalDateTime parseLocalDateTime20(char[] str, int off) { - if (off + 19 > str.length) { - return null; - } - - char c0 = str[off]; - char c1 = str[off + 1]; - char c2 = str[off + 2]; - char c3 = str[off + 3]; - char c4 = str[off + 4]; - char c5 = str[off + 5]; - char c6 = str[off + 6]; - char c7 = str[off + 7]; - char c8 = str[off + 8]; - char c9 = str[off + 9]; - char c10 = str[off + 10]; - char c11 = str[off + 11]; - char c12 = str[off + 12]; - char c13 = str[off + 13]; - char c14 = str[off + 14]; - char c15 = str[off + 15]; - char c16 = str[off + 16]; - char c17 = str[off + 17]; - char c18 = str[off + 18]; - char c19 = str[off + 19]; - - if (c2 != ' ' || c6 != ' ' || c11 != ' ' || c14 != ':' || c17 != ':') { + * yyyy-MM-dd HH:mm:ss + * yyyy/MM/ddTHH:mm:ss + * yyyy/MM/dd HH:mm:ss + */ + public static LocalDateTime parseLocalDateTime19(byte[] str, int off) { + if (off + 19 > str.length) { return null; } - char m0, m1; + byte c1 = str[off + 1]; + byte c2 = str[off + 2]; + byte c3 = str[off + 3]; + byte c4 = str[off + 4]; + byte c5 = str[off + 5]; + byte c7 = str[off + 7]; + byte c10 = str[off + 10]; + byte c13 = str[off + 13]; + byte c16 = str[off + 16]; - int month = DateUtils.month(c3, c4, c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); + int year, month, dom, hour, minute, second; + if (((c4 == '-' && c7 == '-') || (c4 == '/' && c7 == '/')) + && (c10 == ' ' || c10 == 'T') + && c13 == ':' && c16 == ':' + ) { + year = digit4(str, off); + month = digit2(str, off + 5); + dom = digit2(str, off + 8); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + second = digit2(str, off + 17); + } else if (c2 == '/' && c5 == '/' && (c10 == ' ' || c10 == 'T') && c13 == ':' && c16 == ':') { + dom = digit2(str, off); + month = digit2(str, off + 3); + year = digit4(str, off + 6); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + second = digit2(str, off + 17); + } else if (c1 == ' ' && c5 == ' ' && c10 == ' ' && c13 == ':' && c16 == ':') { + dom = digit1(str, off); + month = DateUtils.month(c2, c3, c4); + year = digit4(str, off + 6); + hour = digit2(str, off + 11); + minute = digit2(str, off + 14); + second = digit2(str, off + 17); } else { - m0 = '0'; - m1 = '0'; + return null; } - return localDateTime( - c7, c8, c9, c10, // yyyy - m0, m1, - c0, c1, // dd - c12, c13, // HH - c15, c16, // mm - c18, c19 // ss - ); + return (year | month | dom | hour | minute | second) <= 0 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second); } - public static LocalDateTime parseLocalDateTime20(byte[] str, int off) { - if (off + 19 > str.length) { + public static LocalDateTime parseLocalDateTime20(char[] str, int off) { + if (off + 19 > str.length + || str[off + 2] != ' ' + || str[off + 6] != ' ' + || str[off + 11] != ' ' + || str[off + 14] != ':' + || str[off + 17] != ':' + ) { return null; } - char c0 = (char) str[off]; - char c1 = (char) str[off + 1]; - char c2 = (char) str[off + 2]; - char c3 = (char) str[off + 3]; - char c4 = (char) str[off + 4]; - char c5 = (char) str[off + 5]; - char c6 = (char) str[off + 6]; - char c7 = (char) str[off + 7]; - char c8 = (char) str[off + 8]; - char c9 = (char) str[off + 9]; - char c10 = (char) str[off + 10]; - char c11 = (char) str[off + 11]; - char c12 = (char) str[off + 12]; - char c13 = (char) str[off + 13]; - char c14 = (char) str[off + 14]; - char c15 = (char) str[off + 15]; - char c16 = (char) str[off + 16]; - char c17 = (char) str[off + 17]; - char c18 = (char) str[off + 18]; - char c19 = (char) str[off + 19]; + int dom = digit2(str, off); + int month = DateUtils.month(str[off + 3], str[off + 4], str[off + 5]); + int year = digit4(str, off + 7); + int hour = digit2(str, off + 12); + int minute = digit2(str, off + 15); + int second = digit2(str, off + 18); + + return (year | month | dom | hour | minute | second) <= 0 || hour > 24 || minute > 59 || second > 60 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second); + } - if (c2 != ' ' || c6 != ' ' || c11 != ' ' || c14 != ':' || c17 != ':') { + public static LocalDateTime parseLocalDateTime20(byte[] str, int off) { + if (off + 19 > str.length + || str[off + 2] != ' ' + || str[off + 6] != ' ' + || str[off + 11] != ' ' + || str[off + 14] != ':' + || str[off + 17] != ':' + ) { return null; } - char m0, m1; - - int month = DateUtils.month(c3, c4, c5); - if (month > 0) { - m0 = (char) ('0' + month / 10); - m1 = (char) ('0' + (month % 10)); - } else { - m0 = '0'; - m1 = '0'; - } + int dom = digit2(str, off); + int month = DateUtils.month(str[off + 3], str[off + 4], str[off + 5]); + int year = digit4(str, off + 7); + int hour = digit2(str, off + 12); + int minute = digit2(str, off + 15); + int second = digit2(str, off + 18); - return localDateTime( - c7, c8, c9, c10, // yyyy - m0, m1, - c0, c1, // dd - c12, c13, // HH - c15, c16, // mm - c18, c19 // ss - ); + return (year | month | dom | hour | minute | second) <= 0 || hour > 24 || minute > 59 || second > 60 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second); } public static LocalDateTime parseLocalDateTime26(byte[] str, int off) { - if (off + 26 > str.length) { + byte c10; + if (off + 26 > str.length + || str[off + 4] != '-' + || str[off + 7] != '-' + || ((c10 = str[off + 10]) != ' ' && c10 != 'T') + || str[off + 13] != ':' + || str[off + 16] != ':' + || str[off + 19] != '.' + ) { return null; } - char c0 = (char) str[off]; - char c1 = (char) str[off + 1]; - char c2 = (char) str[off + 2]; - char c3 = (char) str[off + 3]; - char c4 = (char) str[off + 4]; - char c5 = (char) str[off + 5]; - char c6 = (char) str[off + 6]; - char c7 = (char) str[off + 7]; - char c8 = (char) str[off + 8]; - char c9 = (char) str[off + 9]; - char c10 = (char) str[off + 10]; - char c11 = (char) str[off + 11]; - char c12 = (char) str[off + 12]; - char c13 = (char) str[off + 13]; - char c14 = (char) str[off + 14]; - char c15 = (char) str[off + 15]; - char c16 = (char) str[off + 16]; - char c17 = (char) str[off + 17]; - char c18 = (char) str[off + 18]; - char c19 = (char) str[off + 19]; - char c20 = (char) str[off + 20]; - char c21 = (char) str[off + 21]; - char c22 = (char) str[off + 22]; - char c23 = (char) str[off + 23]; - char c24 = (char) str[off + 24]; - char c25 = (char) str[off + 25]; - - if (c4 != '-' || c7 != '-' || (c10 != ' ' && c10 != 'T') || c13 != ':' || c16 != ':' || c19 != '.') { - return null; - } + int year = digit4(str, off); + int month = digit2(str, off + 5); + int dom = digit2(str, off + 8); + int hour = digit2(str, off + 11); + int minute = digit2(str, off + 14); + int second = digit2(str, off + 17); + int nano = readNanos(str, 6, off + 20); - return localDateTime( - c0, c1, c2, c3, // yyyy - c5, c6, // MM - c8, c9, // dd - c11, c12, // HH - c14, c15, // mm - c17, c18, // ss - c20, c21, c22, c23, c24, c25, '0', '0', '0' - ); + return (year | month | dom | hour | minute | second | nano) <= 0 || hour > 24 || minute > 59 || second > 60 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second, nano); } public static LocalDateTime parseLocalDateTime26(char[] str, int off) { - if (off + 26 > str.length) { + char c10; + if (off + 26 > str.length + || str[off + 4] != '-' + || str[off + 7] != '-' + || ((c10 = str[off + 10]) != ' ' && c10 != 'T') + || str[off + 13] != ':' + || str[off + 16] != ':' + || str[off + 19] != '.' + ) { return null; } - char c0 = str[off]; - char c1 = str[off + 1]; - char c2 = str[off + 2]; - char c3 = str[off + 3]; - char c4 = str[off + 4]; - char c5 = str[off + 5]; - char c6 = str[off + 6]; - char c7 = str[off + 7]; - char c8 = str[off + 8]; - char c9 = str[off + 9]; - char c10 = str[off + 10]; - char c11 = str[off + 11]; - char c12 = str[off + 12]; - char c13 = str[off + 13]; - char c14 = str[off + 14]; - char c15 = str[off + 15]; - char c16 = str[off + 16]; - char c17 = str[off + 17]; - char c18 = str[off + 18]; - char c19 = str[off + 19]; - char c20 = str[off + 20]; - char c21 = str[off + 21]; - char c22 = str[off + 22]; - char c23 = str[off + 23]; - char c24 = str[off + 24]; - char c25 = str[off + 25]; - - if (c4 != '-' || c7 != '-' || (c10 != ' ' && c10 != 'T') || c13 != ':' || c16 != ':' || c19 != '.') { - return null; - } + int year = digit4(str, off); + int month = digit2(str, off + 5); + int dom = digit2(str, off + 8); + int hour = digit2(str, off + 11); + int minute = digit2(str, off + 14); + int second = digit2(str, off + 17); + int nano = readNanos(str, 6, off + 20); - return localDateTime( - c0, c1, c2, c3, // yyyy - c5, c6, // MM - c8, c9, // dd - c11, c12, // HH - c14, c15, // mm - c17, c18, // SS - c20, c21, c22, c23, c24, c25, - '0', '0', '0' - ); + return (year | month | dom | hour | minute | second | nano) <= 0 || hour > 24 || minute > 59 || second > 60 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second, nano); } public static LocalDateTime parseLocalDateTime27(byte[] str, int off) { - if (off + 27 > str.length) { + byte c10; + if (off + 27 > str.length + || str[off + 4] != '-' + || str[off + 7] != '-' + || ((c10 = str[off + 10]) != ' ' && c10 != 'T') + || str[off + 13] != ':' + || str[off + 16] != ':' + || str[off + 19] != '.' + ) { return null; } - char c0 = (char) str[off]; - char c1 = (char) str[off + 1]; - char c2 = (char) str[off + 2]; - char c3 = (char) str[off + 3]; - char c4 = (char) str[off + 4]; - char c5 = (char) str[off + 5]; - char c6 = (char) str[off + 6]; - char c7 = (char) str[off + 7]; - char c8 = (char) str[off + 8]; - char c9 = (char) str[off + 9]; - char c10 = (char) str[off + 10]; - char c11 = (char) str[off + 11]; - char c12 = (char) str[off + 12]; - char c13 = (char) str[off + 13]; - char c14 = (char) str[off + 14]; - char c15 = (char) str[off + 15]; - char c16 = (char) str[off + 16]; - char c17 = (char) str[off + 17]; - char c18 = (char) str[off + 18]; - char c19 = (char) str[off + 19]; - char c20 = (char) str[off + 20]; - char c21 = (char) str[off + 21]; - char c22 = (char) str[off + 22]; - char c23 = (char) str[off + 23]; - char c24 = (char) str[off + 24]; - char c25 = (char) str[off + 25]; - char c26 = (char) str[off + 26]; - - if (c4 != '-' || c7 != '-' || (c10 != ' ' && c10 != 'T') || c13 != ':' || c16 != ':' || c19 != '.') { - return null; - } + int year = digit4(str, off); + int month = digit2(str, off + 5); + int dom = digit2(str, off + 8); + int hour = digit2(str, off + 11); + int minute = digit2(str, off + 14); + int second = digit2(str, off + 17); + int nano = readNanos(str, 7, off + 20); - return localDateTime( - c0, c1, c2, c3, // yyyy - c5, c6, // MM - c8, c9, // dd - c11, c12, // HH - c14, c15, // mm - c17, c18, // ss - c20, c21, c22, c23, c24, c25, c26, '0', '0' - ); + return (year | month | dom | hour | minute | second | nano) <= 0 || hour > 24 || minute > 59 || second > 60 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second, nano); } public static LocalDateTime parseLocalDateTime27(char[] str, int off) { - if (off + 27 > str.length) { + char c10; + if (off + 27 > str.length + || str[off + 4] != '-' + || str[off + 7] != '-' + || ((c10 = str[off + 10]) != ' ' && c10 != 'T') + || str[off + 13] != ':' + || str[off + 16] != ':' + || str[off + 19] != '.' + ) { return null; } - char c0 = str[off]; - char c1 = str[off + 1]; - char c2 = str[off + 2]; - char c3 = str[off + 3]; - char c4 = str[off + 4]; - char c5 = str[off + 5]; - char c6 = str[off + 6]; - char c7 = str[off + 7]; - char c8 = str[off + 8]; - char c9 = str[off + 9]; - char c10 = str[off + 10]; - char c11 = str[off + 11]; - char c12 = str[off + 12]; - char c13 = str[off + 13]; - char c14 = str[off + 14]; - char c15 = str[off + 15]; - char c16 = str[off + 16]; - char c17 = str[off + 17]; - char c18 = str[off + 18]; - char c19 = str[off + 19]; - char c20 = str[off + 20]; - char c21 = str[off + 21]; - char c22 = str[off + 22]; - char c23 = str[off + 23]; - char c24 = str[off + 24]; - char c25 = str[off + 25]; - char c26 = str[off + 26]; - - if (c4 != '-' || c7 != '-' || (c10 != ' ' && c10 != 'T') || c13 != ':' || c16 != ':' || c19 != '.') { - return null; - } + int year = digit4(str, off); + int month = digit2(str, off + 5); + int dom = digit2(str, off + 8); + int hour = digit2(str, off + 11); + int minute = digit2(str, off + 14); + int second = digit2(str, off + 17); + int nano = readNanos(str, 7, off + 20); - return localDateTime( - c0, c1, c2, c3, // yyyy - c5, c6, // MM - c8, c9, // dd - c11, c12, // hh - c14, c15, // mm - c17, c18, // ss - c20, c21, c22, c23, c24, c25, c26, '0', '0' - ); + return (year | month | dom | hour | minute | second | nano) <= 0 || hour > 24 || minute > 59 || second > 60 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second, nano); } public static LocalDateTime parseLocalDateTime28(char[] str, int off) { - if (off + 28 > str.length) { + char c10; + if (off + 28 > str.length + || str[off + 4] != '-' + || str[off + 7] != '-' + || ((c10 = str[off + 10]) != ' ' && c10 != 'T') + || str[off + 13] != ':' + || str[off + 16] != ':' + || str[off + 19] != '.' + ) { return null; } - char c0 = str[off]; - char c1 = str[off + 1]; - char c2 = str[off + 2]; - char c3 = str[off + 3]; - char c4 = str[off + 4]; - char c5 = str[off + 5]; - char c6 = str[off + 6]; - char c7 = str[off + 7]; - char c8 = str[off + 8]; - char c9 = str[off + 9]; - char c10 = str[off + 10]; - char c11 = str[off + 11]; - char c12 = str[off + 12]; - char c13 = str[off + 13]; - char c14 = str[off + 14]; - char c15 = str[off + 15]; - char c16 = str[off + 16]; - char c17 = str[off + 17]; - char c18 = str[off + 18]; - char c19 = str[off + 19]; - char c20 = str[off + 20]; - char c21 = str[off + 21]; - char c22 = str[off + 22]; - char c23 = str[off + 23]; - char c24 = str[off + 24]; - char c25 = str[off + 25]; - char c26 = str[off + 26]; - char c27 = str[off + 27]; - - if (c4 != '-' || c7 != '-' || (c10 != ' ' && c10 != 'T') || c13 != ':' || c16 != ':' || c19 != '.') { - return null; - } + int year = digit4(str, off); + int month = digit2(str, off + 5); + int dom = digit2(str, off + 8); + int hour = digit2(str, off + 11); + int minute = digit2(str, off + 14); + int second = digit2(str, off + 17); + int nano = readNanos(str, 8, off + 20); - return localDateTime( - c0, c1, c2, c3, // yyyy - c5, c6, // MM - c8, c9, // dd - c11, c12, // HH - c14, c15, // mm - c17, c18, // ss - c20, c21, c22, c23, c24, c25, c26, c27, '0' - ); + return (year | month | dom | hour | minute | second | nano) <= 0 || hour > 24 || minute > 59 || second > 60 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second, nano); } public static LocalDateTime parseLocalDateTime28(byte[] str, int off) { - if (off + 28 > str.length) { + byte c10; + if (off + 28 > str.length + || str[off + 4] != '-' + || str[off + 7] != '-' + || ((c10 = str[off + 10]) != ' ' && c10 != 'T') + || str[off + 13] != ':' + || str[off + 16] != ':' + || str[off + 19] != '.' + ) { return null; } - char c0 = (char) str[off]; - char c1 = (char) str[off + 1]; - char c2 = (char) str[off + 2]; - char c3 = (char) str[off + 3]; - char c4 = (char) str[off + 4]; - char c5 = (char) str[off + 5]; - char c6 = (char) str[off + 6]; - char c7 = (char) str[off + 7]; - char c8 = (char) str[off + 8]; - char c9 = (char) str[off + 9]; - char c10 = (char) str[off + 10]; - char c11 = (char) str[off + 11]; - char c12 = (char) str[off + 12]; - char c13 = (char) str[off + 13]; - char c14 = (char) str[off + 14]; - char c15 = (char) str[off + 15]; - char c16 = (char) str[off + 16]; - char c17 = (char) str[off + 17]; - char c18 = (char) str[off + 18]; - char c19 = (char) str[off + 19]; - char c20 = (char) str[off + 20]; - char c21 = (char) str[off + 21]; - char c22 = (char) str[off + 22]; - char c23 = (char) str[off + 23]; - char c24 = (char) str[off + 24]; - char c25 = (char) str[off + 25]; - char c26 = (char) str[off + 26]; - char c27 = (char) str[off + 27]; - - if (c4 != '-' || c7 != '-' || (c10 != ' ' && c10 != 'T') || c13 != ':' || c16 != ':' || c19 != '.') { - return null; - } + int year = digit4(str, off); + int month = digit2(str, off + 5); + int dom = digit2(str, off + 8); + int hour = digit2(str, off + 11); + int minute = digit2(str, off + 14); + int second = digit2(str, off + 17); + int nano = readNanos(str, 8, off + 20); - return localDateTime( - c0, c1, c2, c3, // yyyy - c5, c6, // MM - c8, c9, // dd - c11, c12, // HH - c14, c15, // mm - c17, c18, // ss - c20, c21, c22, c23, c24, c25, c26, c27, '0' - ); + return (year | month | dom | hour | minute | second | nano) <= 0 || hour > 24 || minute > 59 || second > 60 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second, nano); } public static LocalDateTime parseLocalDateTime29(byte[] str, int off) { - if (off + 29 > str.length) { + byte c10; + if (off + 29 > str.length + || str[off + 4] != '-' + || str[off + 7] != '-' + || ((c10 = str[off + 10]) != ' ' && c10 != 'T') + || str[off + 13] != ':' + || str[off + 16] != ':' + || str[off + 19] != '.' + ) { return null; } - char c0 = (char) str[off]; - char c1 = (char) str[off + 1]; - char c2 = (char) str[off + 2]; - char c3 = (char) str[off + 3]; - char c4 = (char) str[off + 4]; - char c5 = (char) str[off + 5]; - char c6 = (char) str[off + 6]; - char c7 = (char) str[off + 7]; - char c8 = (char) str[off + 8]; - char c9 = (char) str[off + 9]; - char c10 = (char) str[off + 10]; - char c11 = (char) str[off + 11]; - char c12 = (char) str[off + 12]; - char c13 = (char) str[off + 13]; - char c14 = (char) str[off + 14]; - char c15 = (char) str[off + 15]; - char c16 = (char) str[off + 16]; - char c17 = (char) str[off + 17]; - char c18 = (char) str[off + 18]; - char c19 = (char) str[off + 19]; - char c20 = (char) str[off + 20]; - char c21 = (char) str[off + 21]; - char c22 = (char) str[off + 22]; - char c23 = (char) str[off + 23]; - char c24 = (char) str[off + 24]; - char c25 = (char) str[off + 25]; - char c26 = (char) str[off + 26]; - char c27 = (char) str[off + 27]; - char c28 = (char) str[off + 28]; - - if (c4 != '-' || c7 != '-' || (c10 != ' ' && c10 != 'T') || c13 != ':' || c16 != ':' || c19 != '.') { - return null; - } + int year = digit4(str, off); + int month = digit2(str, off + 5); + int dom = digit2(str, off + 8); + int hour = digit2(str, off + 11); + int minute = digit2(str, off + 14); + int second = digit2(str, off + 17); + int nano = readNanos(str, 9, off + 20); - return localDateTime( - c0, c1, c2, c3, // yyyy - c5, c6, // MM - c8, c9, // dd - c11, c12, // HH - c14, c15, // mm - c17, c18, // ss - c20, c21, c22, c23, c24, c25, c26, c27, c28 - ); + return (year | month | dom | hour | minute | second | nano) <= 0 || hour > 24 || minute > 59 || second > 60 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second, nano); } public static LocalDateTime parseLocalDateTime29(char[] str, int off) { - if (off + 29 > str.length) { + char c10; + if (off + 29 > str.length + || str[off + 4] != '-' + || str[off + 7] != '-' + || ((c10 = str[off + 10]) != ' ' && c10 != 'T') + || str[off + 13] != ':' + || str[off + 16] != ':' + || str[off + 19] != '.' + ) { return null; } - char c0 = str[off]; - char c1 = str[off + 1]; - char c2 = str[off + 2]; - char c3 = str[off + 3]; - char c4 = str[off + 4]; - char c5 = str[off + 5]; - char c6 = str[off + 6]; - char c7 = str[off + 7]; - char c8 = str[off + 8]; - char c9 = str[off + 9]; - char c10 = str[off + 10]; - char c11 = str[off + 11]; - char c12 = str[off + 12]; - char c13 = str[off + 13]; - char c14 = str[off + 14]; - char c15 = str[off + 15]; - char c16 = str[off + 16]; - char c17 = str[off + 17]; - char c18 = str[off + 18]; - char c19 = str[off + 19]; - char c20 = str[off + 20]; - char c21 = str[off + 21]; - char c22 = str[off + 22]; - char c23 = str[off + 23]; - char c24 = str[off + 24]; - char c25 = str[off + 25]; - char c26 = str[off + 26]; - char c27 = str[off + 27]; - char c28 = str[off + 28]; - - if (c4 != '-' || c7 != '-' || (c10 != ' ' && c10 != 'T') || c13 != ':' || c16 != ':' || c19 != '.') { - return null; - } + int year = digit4(str, off); + int month = digit2(str, off + 5); + int dom = digit2(str, off + 8); + int hour = digit2(str, off + 11); + int minute = digit2(str, off + 14); + int second = digit2(str, off + 17); + int nano = readNanos(str, 9, off + 20); - return localDateTime( - c0, c1, c2, c3, // yyyy - c5, c6, // MM - c8, c9, // dd - c11, c12, // HH - c14, c15, // mm - c17, c18, // ss - c20, c21, c22, c23, c24, c25, c26, c27, c28 // S0 - S9 - ); + return (year | month | dom | hour | minute | second | nano) <= 0 || hour > 24 || minute > 59 || second > 60 + ? null + : LocalDateTime.of(year, month, dom, hour, minute, second, nano); } public static LocalDateTime parseLocalDateTimeX(char[] str, int offset, int len) { @@ -11933,6 +8701,10 @@ public static String toString(long timeMillis, boolean timeZone, ZoneId zoneId) return new String(bytes, 0, bytes.length, StandardCharsets.ISO_8859_1); } + private static int month(byte c0, byte c1, byte c2) { + return month((char) c0, (char) c1, (char) c2); + } + public static int month(char c0, char c1, char c2) { switch (c0) { case 'J': @@ -11996,7 +8768,7 @@ public static int month(char c0, char c1, char c2) { break; } - return 0; + return -1; } public static int hourAfterNoon(char h0, char h1) { @@ -12386,119 +9158,48 @@ public static boolean isLocalTime(String str) { } public static int readNanos(final char[] chars, final int len, final int offset) { - switch (len) { - case 1: - return 100000000 * (chars[offset] - 48); - case 2: - return 100000000 * (chars[offset] - 48) - + 10000000 * (chars[offset + 1] - 48); - case 3: - return 100000000 * (chars[offset] - 48) - + 10000000 * (chars[offset + 1] - 48) - + 1000000 * (chars[offset + 2] - 48); - case 4: - return 100000000 * (chars[offset] - 48) - + 10000000 * (chars[offset + 1] - 48) - + 1000000 * (chars[offset + 2] - 48) - + 100000 * (chars[offset + 3] - 48); - case 5: - return 100000000 * (chars[offset] - 48) - + 10000000 * (chars[offset + 1] - 48) - + 1000000 * (chars[offset + 2] - 48) - + 100000 * (chars[offset + 3] - 48) - + 10000 * (chars[offset + 4] - 48); - case 6: - return 100000000 * (chars[offset] - 48) - + 10000000 * (chars[offset + 1] - 48) - + 1000000 * (chars[offset + 2] - 48) - + 100000 * (chars[offset + 3] - 48) - + 10000 * (chars[offset + 4] - 48) - + 1000 * (chars[offset + 5] - 48); - case 7: - return 100000000 * (chars[offset] - 48) - + 10000000 * (chars[offset + 1] - 48) - + 1000000 * (chars[offset + 2] - 48) - + 100000 * (chars[offset + 3] - 48) - + 10000 * (chars[offset + 4] - 48) - + 1000 * (chars[offset + 5] - 48) - + 100 * (chars[offset + 6] - 48); - case 8: - return 100000000 * (chars[offset] - 48) - + 10000000 * (chars[offset + 1] - 48) - + 1000000 * (chars[offset + 2] - 48) - + 100000 * (chars[offset + 3] - 48) - + 10000 * (chars[offset + 4] - 48) - + 1000 * (chars[offset + 5] - 48) - + 100 * (chars[offset + 6] - 48) - + 10 * (chars[offset + 7] - 48); - default: - return 100000000 * (chars[offset] - 48) - + 10000000 * (chars[offset + 1] - 48) - + 1000000 * (chars[offset + 2] - 48) - + 100000 * (chars[offset + 3] - 48) - + 10000 * (chars[offset + 4] - 48) - + 1000 * (chars[offset + 5] - 48) - + 100 * (chars[offset + 6] - 48) - + 10 * (chars[offset + 7] - 48) - + chars[offset + 8] - 48; + int v = 0; + for (int i = 0; i < len; i++) { + int d = chars[offset + i] - '0'; + if (d < 0 | d > 9) { + return -1; + } + v = v * 10 + d; } + v *= POWERS[(9 - len) & 0xF]; + return v; } public static int readNanos(final byte[] bytes, final int len, final int offset) { - switch (len) { - case 1: - return 100000000 * (bytes[offset] - 48); - case 2: - return 100000000 * (bytes[offset] - 48) + 10000000 * (bytes[offset + 1] - 48); - case 3: - return 100000000 * (bytes[offset] - 48) - + 10000000 * (bytes[offset + 1] - 48) - + 1000000 * (bytes[offset + 2] - 48); - case 4: - return 100000000 * (bytes[offset] - 48) - + 10000000 * (bytes[offset + 1] - 48) - + 1000000 * (bytes[offset + 2] - 48) - + 100000 * (bytes[offset + 3] - 48); - case 5: - return 100000000 * (bytes[offset] - 48) - + 10000000 * (bytes[offset + 1] - 48) - + 1000000 * (bytes[offset + 2] - 48) - + 100000 * (bytes[offset + 3] - 48) - + 10000 * (bytes[offset + 4] - 48); - case 6: - return 100000000 * (bytes[offset] - 48) - + 10000000 * (bytes[offset + 1] - 48) - + 1000000 * (bytes[offset + 2] - 48) - + 100000 * (bytes[offset + 3] - 48) - + 10000 * (bytes[offset + 4] - 48) - + 1000 * (bytes[offset + 5] - 48); - case 7: - return 100000000 * (bytes[offset] - 48) - + 10000000 * (bytes[offset + 1] - 48) - + 1000000 * (bytes[offset + 2] - 48) - + 100000 * (bytes[offset + 3] - 48) - + 10000 * (bytes[offset + 4] - 48) - + 1000 * (bytes[offset + 5] - 48) - + 100 * (bytes[offset + 6] - 48); - case 8: - return 100000000 * (bytes[offset] - 48) - + 10000000 * (bytes[offset + 1] - 48) - + 1000000 * (bytes[offset + 2] - 48) - + 100000 * (bytes[offset + 3] - 48) - + 10000 * (bytes[offset + 4] - 48) - + 1000 * (bytes[offset + 5] - 48) - + 100 * (bytes[offset + 6] - 48) - + 10 * (bytes[offset + 7] - 48); - default: - return 100000000 * (bytes[offset] - 48) - + 10000000 * (bytes[offset + 1] - 48) - + 1000000 * (bytes[offset + 2] - 48) - + 100000 * (bytes[offset + 3] - 48) - + 10000 * (bytes[offset + 4] - 48) - + 1000 * (bytes[offset + 5] - 48) - + 100 * (bytes[offset + 6] - 48) - + 10 * (bytes[offset + 7] - 48) - + bytes[offset + 8] - 48; - } - } + int v = 0; + long address = ARRAY_BYTE_BASE_OFFSET + offset; + for (int i = 0; i < len; i++) { + int d = UNSAFE.getByte(bytes, address + i) - '0'; + if (d < 0 | d > 9) { + return -1; + } + v = v * 10 + d; + } + v *= POWERS[(9 - len) & 0xF]; + return v; + } + + private static final int[] POWERS = { + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 0, + 0, + 0, + 0, + 0, + 0, + }; } diff --git a/core/src/main/java/com/alibaba/fastjson2/util/IOUtils.java b/core/src/main/java/com/alibaba/fastjson2/util/IOUtils.java index a886f5b4b3..95d1018bb9 100644 --- a/core/src/main/java/com/alibaba/fastjson2/util/IOUtils.java +++ b/core/src/main/java/com/alibaba/fastjson2/util/IOUtils.java @@ -1424,4 +1424,197 @@ public static void putLong(char[] buf, int pos, long v) { BIG_ENDIAN ? Long.reverseBytes(v) : v ); } + + public static int digit4(char[] chars, int off) { + long x = UNSAFE.getLong(chars, ARRAY_CHAR_BASE_OFFSET + ((long) off << 1)); + if (BIG_ENDIAN) { + x = Long.reverseBytes(x); + } + long d; + if ((x & 0xF000F000F000F0L) != 0x30003000300030L + || (((d = x & 0x0F000F000F000FL) + 0x06000600060006L) & 0xF000F000F000F0L) != 0 + ) { + return -1; + } + return (int) (((d & 0xF) << 10) + ((d & 0xF) << 3) - ((d & 0xF) << 5) // (d & 0xF) * 1000 + + ((d & 0xF0000) >> 10) + ((d & 0xF0000) >> 11) + ((d & 0xF0000) >> 14) // ((d & 0xF0000) >> 16) * 100 + + ((d & 0xF00000000L) >> 29) + ((d & 0xF00000000L) >> 31) // ((d & 0xF00000000L) >> 32) * 10 + + (d >> 48)); + } + + public static int digit4(byte[] bytes, int off) { + int x = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + off); + if (BIG_ENDIAN) { + x = Integer.reverseBytes(x); + } + /* + Here we are doing a 4-Byte Vector operation on the Int type. + + x & 0xF0 != 0xC0 + --------------- + 0 0b0011_0000 & 0b1111_0000 = 0b0011_0000 + 1 0b0011_0001 & 0b1111_0000 = 0b0011_0000 + 2 0b0011_0010 & 0b1111_0000 = 0b0011_0000 + 3 0b0011_0011 & 0b1111_0000 = 0b0011_0000 + 4 0b0011_0100 & 0b1111_0000 = 0b0011_0000 + 5 0b0011_0101 & 0b1111_0000 = 0b0011_0000 + 6 0b0011_0110 & 0b1111_0000 = 0b0011_0000 + 7 0b0011_0111 & 0b1111_0000 = 0b0011_0000 + 8 0b0011_1000 & 0b1111_0000 = 0b0011_0000 + 9 0b0011_1001 & 0b1111_0000 = 0b0011_0000 + + (((d = x & 0x0F) + 0x06) & 0xF0) != 0 + --------------- + 0 ((0b0011_0000) & 0b0000_1111 + 0b0110_0000) & 0b1111_0000 = 0b0110_0000 + 1 ((0b0011_0001) & 0b0000_1111 + 0b0110_0000) & 0b1111_0000 = 0b0110_0000 + 2 ((0b0011_0010) & 0b0000_1111 + 0b0110_0000) & 0b1111_0000 = 0b0110_0000 + 3 ((0b0011_0011) & 0b0000_1111 + 0b0110_0000) & 0b1111_0000 = 0b0110_0000 + 4 ((0b0011_0100) & 0b0000_1111 + 0b0110_0000) & 0b1111_0000 = 0b0110_0000 + 5 ((0b0011_0101) & 0b0000_1111 + 0b0110_0000) & 0b1111_0000 = 0b0110_0000 + 6 ((0b0011_0110) & 0b0000_1111 + 0b0110_0000) & 0b1111_0000 = 0b0110_0000 + 7 ((0b0011_0111) & 0b0000_1111 + 0b0110_0000) & 0b1111_0000 = 0b0110_0000 + 8 ((0b0011_1000) & 0b0000_1111 + 0b0110_0000) & 0b1111_0000 = 0b0110_0000 + 9 ((0b0011_1001) & 0b0000_1111 + 0b0110_0000) & 0b1111_0000 = 0b0110_0000 + */ + int d; + if ((x & 0xF0F0F0F0) != 0x30303030 + || (((d = x & 0x0F0F0F0F) + 0x06060606) & 0xF0F0F0F0) != 0 + ) { + return -1; + } + /* + 10 = (1 << 3 ) + (1 << 1) + 100 = (1 << 6 ) + (1 << 5) + (1 << 2) + 1000 = (1 << 10) + (1 << 3) - (1 << 5) + */ + return ((d & 0xF) << 10) + ((d & 0xF) << 3) - ((d & 0xF) << 5) // (d & 0xF) * 1000 + + ((d & 0xF00) >> 2) + ((d & 0xF00) >> 3) + ((d & 0xF00) >> 6) // ((d & 0xF00) >> 8) * 100 + + ((d & 0xF0000) >> 13) + ((d & 0xF0000) >> 15) // ((d & 0xF0000) >> 16) * 10 + + (d >> 24); + } + + public static int digit3(char[] chars, int off) { + long address = ARRAY_CHAR_BASE_OFFSET + ((long) off << 1); + int i = UNSAFE.getInt(chars, address); + short s = UNSAFE.getShort(chars, address + 4); + if (BIG_ENDIAN) { + i = Integer.reverseBytes(i); + s = Short.reverseBytes(s); + } + long x = (((long) s) << 32) | i; // reuse + long d; + if ((x & 0xF000F000F0L) != 0x3000300030L + || (((d = x & 0x0F000F000FL) + 0x0600060006L) & 0xF000F000F0L) != 0 + ) { + return -1; + } + return (int) (((d & 0xF) << 6) + ((d & 0xF) << 5) + ((d & 0xF) << 2) // (d & 0xF) * 100 + + ((d & 0xF0000L) >> 13) + ((d & 0xF0000L) >> 15) // ((d & 0xF0000) >> 16) * 10 + + (d >> 32)); + } + + public static int digit3(byte[] bytes, int off) { + int x = UNSAFE.getShort(bytes, ARRAY_BYTE_BASE_OFFSET + off); + if (BIG_ENDIAN) { + x = Short.reverseBytes((short) x); + } + x |= UNSAFE.getByte(bytes, ARRAY_BYTE_BASE_OFFSET + off + 2) << 16; + int d; + if ((x & 0xF0F0F0) != 0x303030 + || (((d = x & 0x0F0F0F) + 0x060606) & 0xF0F0F0) != 0 + ) { + return -1; + } + return ((d & 0xF) << 6) + ((d & 0xF) << 5) + ((d & 0xF) << 2) // (d & 0xff) * 100 + + ((d & 0xF00) >> 5) + ((d & 0xF00) >> 7) // ((d & 0xF00) >> 8) * 10 + + (d >> 16); + } + + public static int digit2(char[] chars, int off) { + int x = UNSAFE.getInt(chars, ARRAY_CHAR_BASE_OFFSET + ((long) off << 1)); + if (BIG_ENDIAN) { + x = Integer.reverseBytes(x); + } + int d; + if ((x & 0xF000F0) != 0x300030 + || (((d = x & 0x0F000F) + 0x060006) & 0xF000F0) != 0 + ) { + return -1; + } + return ((d & 0xF) << 3) + ((d & 0xF) << 1) // (d & 0xF) * 10 + + (d >> 16); + } + + public static int digit2(byte[] bytes, int off) { + short x = UNSAFE.getShort(bytes, ARRAY_BYTE_BASE_OFFSET + off); + if (BIG_ENDIAN) { + x = Short.reverseBytes(x); + } + int d; + if ((x & 0xF0F0) != 0x3030 + || (((d = x & 0x0F0F) + 0x0606) & 0xF0F0) != 0 + ) { + return -1; + } + return ((d & 0xF) << 3) + ((d & 0xF) << 1) // (d & 0xF) * 10 + + (d >> 8); + } + + public static int digit1(char[] chars, int off) { + int d = UNSAFE.getByte(chars, ARRAY_CHAR_BASE_OFFSET + ((long) off << 1)) - '0'; + return d >= 0 && d <= 9 ? d : -1; + } + + public static int digit1(byte[] bytes, int off) { + int d = UNSAFE.getByte(bytes, ARRAY_BYTE_BASE_OFFSET + off) - '0'; + return d >= 0 && d <= 9 ? d : -1; + } + + public static int indexOfChar(byte[] value, int ch, int fromIndex) { + return indexOfChar(value, ch, fromIndex, value.length); + } + + public static int indexOfChar(byte[] value, int ch, int fromIndex, int max) { + if (INDEX_OF_CHAR_LATIN1 == null) { + return indexOfChar0(value, ch, fromIndex, max); + } + try { + return (int) INDEX_OF_CHAR_LATIN1.invokeExact(value, ch, fromIndex, max); + } catch (Throwable e) { + throw new JSONException(e.getMessage()); + } + } + + private static int indexOfChar0(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 long hexDigit8(byte[] bytes, int offset) { + long v = Long.reverseBytes(UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset)); + v = (v & 0x0F0F0F0F_0F0F0F0FL) + ((((v & 0x40404040_40404040L) >> 2) | ((v & 0x40404040_40404040L) << 1)) >>> 4); + v = ((v >>> 28) & 0xF0000000L) + + ((v >>> 24) & 0xF000000) + + ((v >>> 20) & 0xF00000) + + ((v >>> 16) & 0xF0000) + + ((v >>> 12) & 0xF000) + + ((v >>> 8) & 0xF00) + + ((v >>> 4) & 0xF0) + + (v & 0xF); + return v; + } + + public static int hexDigit4(byte[] bytes, int offset) { + int v = Integer.reverseBytes(UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset)); + v = (v & 0x0F0F0F0F) + ((((v & 0x40404040) >> 2) | ((v & 0x40404040) << 1)) >>> 4); + v = ((v >>> 12) & 0xF000) + + ((v >>> 8) & 0xF00) + + ((v >>> 4) & 0xF0) + + (v & 0xF); + return v; + } } diff --git a/core/src/main/java/com/alibaba/fastjson2/util/JDKUtils.java b/core/src/main/java/com/alibaba/fastjson2/util/JDKUtils.java index 3d31f7cd0c..67287fb09e 100644 --- a/core/src/main/java/com/alibaba/fastjson2/util/JDKUtils.java +++ b/core/src/main/java/com/alibaba/fastjson2/util/JDKUtils.java @@ -59,6 +59,7 @@ public class JDKUtils { public static final MethodHandle METHOD_HANDLE_HAS_NEGATIVE; public static final Predicate PREDICATE_IS_ASCII; + public static final MethodHandle INDEX_OF_CHAR_LATIN1; static final MethodHandles.Lookup IMPL_LOOKUP; static volatile MethodHandle CONSTRUCTOR_LOOKUP; @@ -337,6 +338,21 @@ public class JDKUtils { METHOD_HANDLE_HAS_NEGATIVE = handle; } + MethodHandle indexOfCharLatin1 = null; + if (JVM_VERSION > 9) { + try { + Class cStringLatin1 = Class.forName("java.lang.StringLatin1"); + MethodHandles.Lookup lookup = trustedLookup(cStringLatin1); + indexOfCharLatin1 = lookup.findStatic( + cStringLatin1, + "indexOfChar", + MethodType.methodType(int.class, byte[].class, int.class, int.class, int.class)); + } catch (Throwable ignored) { + // ignore + } + } + INDEX_OF_CHAR_LATIN1 = indexOfCharLatin1; + Boolean compact_strings = null; try { if (JVM_VERSION == 8) { diff --git a/core/src/test/java/com/alibaba/fastjson2/primitves/UUIDTest.java b/core/src/test/java/com/alibaba/fastjson2/primitves/UUIDTest.java index 69a9a844bd..6d07918611 100644 --- a/core/src/test/java/com/alibaba/fastjson2/primitves/UUIDTest.java +++ b/core/src/test/java/com/alibaba/fastjson2/primitves/UUIDTest.java @@ -75,6 +75,8 @@ public void test_utf8() { public void test_utf8_1() { String str = "d9ac58be-c854-496b-b550-56f0b773d241"; UUID uuid = UUID.fromString(str); + UUID parsed = JSON.parseObject("\"" + str + "\"", UUID.class); + assertEquals(uuid, parsed); byte[] utf8Bytes = JSON.toJSONBytes(uuid); assertEquals("\"d9ac58be-c854-496b-b550-56f0b773d241\"", new String(utf8Bytes)); } diff --git a/core/src/test/java/com/alibaba/fastjson2/util/DateUtilsTest.java b/core/src/test/java/com/alibaba/fastjson2/util/DateUtilsTest.java index 673a98e802..41a9f94148 100644 --- a/core/src/test/java/com/alibaba/fastjson2/util/DateUtilsTest.java +++ b/core/src/test/java/com/alibaba/fastjson2/util/DateUtilsTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.nio.charset.StandardCharsets; import java.time.*; import java.time.chrono.IsoChronology; import java.time.format.DateTimeFormatter; @@ -2037,14 +2038,31 @@ public void parseLocalDateTime16_1() { @Test public void parseLocalDateTime16_2() { + LocalDateTime expected = LocalDateTime.of(2021, 7, 8, 4, 5, 6); assertEquals( - LocalDateTime.of(2021, 7, 8, 4, 5, 6), + expected, DateUtils.parseLocalDateTime("2021-07-08T4:5:6", 0, 16) ); assertEquals( - LocalDateTime.of(2021, 7, 8, 4, 5, 6), + expected, + DateUtils.parseLocalDateTime("2021-07-08T4:5:6".getBytes(StandardCharsets.UTF_8), 0, 16) + ); + assertEquals( + expected, + DateUtils.parseLocalDateTime("2021-07-08T4:5:6".toCharArray(), 0, 16) + ); + assertEquals( + expected, DateUtils.parseLocalDateTime("2021-07-08 4:5:6", 0, 16) ); + assertEquals( + expected, + DateUtils.parseLocalDateTime("2021-07-08 4:5:6".toCharArray(), 0, 16) + ); + assertEquals( + expected, + DateUtils.parseLocalDateTime("2021-07-08 4:5:6".getBytes(StandardCharsets.UTF_8), 0, 16) + ); } @Test @@ -2625,27 +2643,27 @@ public void date2String1() { @Test public void month() { - assertEquals(0, DateUtils.month('J', 'u', 'a')); - assertEquals(0, DateUtils.month('J', 'a', 'a')); - assertEquals(0, DateUtils.month('F', 'a', 'a')); - assertEquals(0, DateUtils.month('F', 'e', 'a')); - assertEquals(0, DateUtils.month('A', 'e', 'a')); - assertEquals(0, DateUtils.month('A', 'p', 'a')); - assertEquals(0, DateUtils.month('M', 'p', 'a')); - assertEquals(0, DateUtils.month('M', 'a', 'a')); - assertEquals(0, DateUtils.month('J', 'a', 'a')); - assertEquals(0, DateUtils.month('J', 'u', 'a')); - assertEquals(0, DateUtils.month('A', 'a', 'a')); - assertEquals(0, DateUtils.month('A', 'u', 'a')); - assertEquals(0, DateUtils.month('S', 'u', 'a')); - assertEquals(0, DateUtils.month('S', 'e', 'a')); - assertEquals(0, DateUtils.month('O', 'e', 'a')); - assertEquals(0, DateUtils.month('O', 'c', 'a')); - assertEquals(0, DateUtils.month('N', 'c', 'a')); - assertEquals(0, DateUtils.month('N', 'o', 'a')); - assertEquals(0, DateUtils.month('D', 'o', 'a')); - assertEquals(0, DateUtils.month('D', 'e', 'a')); - assertEquals(0, DateUtils.month('K', 'e', 'a')); + assertEquals(-1, DateUtils.month('J', 'u', 'a')); + assertEquals(-1, DateUtils.month('J', 'a', 'a')); + assertEquals(-1, DateUtils.month('F', 'a', 'a')); + assertEquals(-1, DateUtils.month('F', 'e', 'a')); + assertEquals(-1, DateUtils.month('A', 'e', 'a')); + assertEquals(-1, DateUtils.month('A', 'p', 'a')); + assertEquals(-1, DateUtils.month('M', 'p', 'a')); + assertEquals(-1, DateUtils.month('M', 'a', 'a')); + assertEquals(-1, DateUtils.month('J', 'a', 'a')); + assertEquals(-1, DateUtils.month('J', 'u', 'a')); + assertEquals(-1, DateUtils.month('A', 'a', 'a')); + assertEquals(-1, DateUtils.month('A', 'u', 'a')); + assertEquals(-1, DateUtils.month('S', 'u', 'a')); + assertEquals(-1, DateUtils.month('S', 'e', 'a')); + assertEquals(-1, DateUtils.month('O', 'e', 'a')); + assertEquals(-1, DateUtils.month('O', 'c', 'a')); + assertEquals(-1, DateUtils.month('N', 'c', 'a')); + assertEquals(-1, DateUtils.month('N', 'o', 'a')); + assertEquals(-1, DateUtils.month('D', 'o', 'a')); + assertEquals(-1, DateUtils.month('D', 'e', 'a')); + assertEquals(-1, DateUtils.month('K', 'e', 'a')); String[] strings = new String[]{ "Jan", diff --git a/core/src/test/java/com/alibaba/fastjson2/util/IOUtilsTest.java b/core/src/test/java/com/alibaba/fastjson2/util/IOUtilsTest.java index 5d58c2c3c9..05f33de805 100644 --- a/core/src/test/java/com/alibaba/fastjson2/util/IOUtilsTest.java +++ b/core/src/test/java/com/alibaba/fastjson2/util/IOUtilsTest.java @@ -5,6 +5,8 @@ import java.nio.charset.StandardCharsets; +import static com.alibaba.fastjson2.util.JDKUtils.ARRAY_BYTE_BASE_OFFSET; +import static com.alibaba.fastjson2.util.JDKUtils.UNSAFE; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -51,7 +53,7 @@ public void encodeUTF8_error() { @Test public void getChars() { - int[] values = new int[] { + int[] values = new int[]{ 1, 10, 100, @@ -94,7 +96,7 @@ public void getChars() { @Test public void getCharsLong() { - long[] values = new long[] { + long[] values = new long[]{ 1, 10, 100, @@ -143,4 +145,232 @@ public void getCharsLong() { assertEquals(str_n, new String(chars_n)); } } + + @Test + public void digit4() { + byte[] bytes = new byte[4]; + for (int x0 = -1; x0 <= 10; x0++) { + bytes[0] = (byte) (x0 + '0'); + for (int x1 = -1; x1 <= 10; x1++) { + bytes[1] = (byte) (x1 + '0'); + for (int x2 = -1; x2 <= 10; x2++) { + bytes[2] = (byte) (x2 + '0'); + for (int x3 = -1; x3 <= 10; x3++) { + bytes[3] = (byte) (x3 + '0'); + int d4 = IOUtils.digit4(bytes, 0); + int expect; + if (x0 < 0 || x0 > 9 || x1 < 0 || x1 > 9 || x2 < 0 || x2 > 9 || x3 < 0 || x3 > 9) { + expect = -1; + } else { + expect = x0 * 1000 + x1 * 100 + x2 * 10 + x3; + } + assertEquals(expect, d4); + } + } + } + } + } + + @Test + public void digit4_chars() { + assertEquals(1972, + IOUtils.digit4( + "1972".toCharArray(), 0)); + + char[] chars = new char[4]; + for (int x0 = -1; x0 <= 10; x0++) { + chars[0] = (char) (x0 + '0'); + for (int x1 = -1; x1 <= 10; x1++) { + chars[1] = (char) (x1 + '0'); + for (int x2 = -1; x2 <= 10; x2++) { + chars[2] = (char) (x2 + '0'); + for (int x3 = -1; x3 <= 10; x3++) { + chars[3] = (char) (x3 + '0'); + int d4 = IOUtils.digit4(chars, 0); + int expect; + if (x0 < 0 || x0 > 9 || x1 < 0 || x1 > 9 || x2 < 0 || x2 > 9 || x3 < 0 || x3 > 9) { + expect = -1; + } else { + expect = x0 * 1000 + x1 * 100 + x2 * 10 + x3; + } + assertEquals(expect, d4); + } + } + } + } + } + + @Test + public void digit3_chars() { + assertEquals(197, + IOUtils.digit3( + "1972".toCharArray(), 0)); + + char[] chars = new char[4]; + for (int x0 = -1; x0 <= 10; x0++) { + chars[0] = (char) (x0 + '0'); + for (int x1 = -1; x1 <= 10; x1++) { + chars[1] = (char) (x1 + '0'); + for (int x2 = -1; x2 <= 10; x2++) { + chars[2] = (char) (x2 + '0'); + int d3 = IOUtils.digit3(chars, 0); + int expect; + if (x0 < 0 || x0 > 9 || x1 < 0 || x1 > 9 || x2 < 0 || x2 > 9) { + expect = -1; + } else { + expect = x0 * 100 + x1 * 10 + x2; + } + assertEquals(expect, d3); + } + } + } + } + + @Test + public void digit3() { + assertEquals(197, + IOUtils.digit3( + "1972".getBytes(StandardCharsets.UTF_8), 0)); + + byte[] bytes = new byte[4]; + for (int x0 = -1; x0 <= 10; x0++) { + bytes[0] = (byte) (x0 + '0'); + for (int x1 = -1; x1 <= 10; x1++) { + bytes[1] = (byte) (x1 + '0'); + for (int x2 = -1; x2 <= 10; x2++) { + bytes[2] = (byte) (x2 + '0'); + int d3 = IOUtils.digit3(bytes, 0); + int expect; + if (x0 < 0 || x0 > 9 || x1 < 0 || x1 > 9 || x2 < 0 || x2 > 9) { + expect = -1; + } else { + expect = x0 * 100 + x1 * 10 + x2; + } + assertEquals(expect, d3); + } + } + } + } + + @Test + public void digit2() { + byte[] bytes = new byte[2]; + for (int x0 = -1; x0 <= 10; x0++) { + bytes[0] = (byte) (x0 + '0'); + for (int x1 = -1; x1 <= 10; x1++) { + bytes[1] = (byte) (x1 + '0'); + int d2 = IOUtils.digit2(bytes, 0); + int expect; + if (x0 < 0 || x0 > 9 || x1 < 0 || x1 > 9) { + expect = -1; + } else { + expect = x0 * 10 + x1; + } + assertEquals(expect, d2); + } + } + } + + @Test + public void digit2_chars() { + assertEquals(19, + IOUtils.digit2( + "19".toCharArray(), 0)); + + char[] bytes = new char[2]; + for (int x0 = -1; x0 <= 10; x0++) { + bytes[0] = (char) (x0 + '0'); + for (int x1 = -1; x1 <= 10; x1++) { + bytes[1] = (char) (x1 + '0'); + int d2 = IOUtils.digit2(bytes, 0); + int expect; + if (x0 < 0 || x0 > 9 || x1 < 0 || x1 > 9) { + expect = -1; + } else { + expect = x0 * 10 + x1; + } + assertEquals(expect, d2); + } + } + } + + @Test + public void printDigit() { + System.out.println("0xF " + Integer.toBinaryString(0xF)); + System.out.println("0xF0 " + Integer.toBinaryString(0xF0)); + System.out.println("0x60" + Integer.toBinaryString(0x60)); + System.out.println(); + + for (int i = 0; i < 10; i++) { + char c = (char) ('0' + i); + System.out.println(c + " " + Integer.toBinaryString(c) + + " & " + Integer.toBinaryString(0xF0) + + " = " + Integer.toBinaryString(c & 0xF0)); + } + + System.out.println(); + for (int i = 0; i < 10; i++) { + char c = (char) ('0' + i); + System.out.println(c + " ((" + Integer.toBinaryString(c) + + ") & " + Integer.toBinaryString(0xF) + + " + " + Integer.toBinaryString(0x60) + + ") & " + Integer.toBinaryString(0xF0) + + " = " + Integer.toBinaryString(((c & 0xF) + 0x60) & 0xF0)); + } + } + + @Test + public void printDigitHex() { + char[] chars = "0123456789abcdefABCDEF".toCharArray(); + System.out.println("0xF " + Integer.toBinaryString(0xF)); + System.out.println("0xF0 " + Integer.toBinaryString(0xF0)); + System.out.println("0x60" + Integer.toBinaryString(0x60)); + System.out.println(); + + long X = 0xA_000A_0000_0000L; + for (char c : chars) { + System.out.println(c + "\t" + ((int) c) + + "\t" + Long.toBinaryString(c) + + "\t" + Long.toHexString((c & 0xF0) >> 4) + + "\t" + Long.toHexString(c & 0xF) + + "\t" + Long.toHexString(((c & 0xF0) >> 1)) + + "\t" + Long.toHexString(((X >> ((c & 0xF0) >> 1))) & 0xFF) + + "\t" + Long.toHexString(((c & 0xF) + ((X >> ((c & 0xF0) >> 1))) & 0xFF)) + ); + } + } + + @Test + public void hexDigit4() { + byte[] bytes = "1234ABcd".getBytes(StandardCharsets.UTF_8); + System.out.println(Integer.toHexString(IOUtils.hexDigit4(bytes, 0))); + } + + static int hexDigit4(byte[] bytes, int offset) { + long v = Long.reverseBytes(UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset)); + v = (v & 0x0F0F0F0F_0F0F0F0FL) + ((((v & 0x40404040_40404040L) >> 2) | ((v & 0x40404040_40404040L) << 1)) >>> 4); + v = ((v >>> 28) & 0xF0000000L) + + ((v >>> 24) & 0xF000000) + + ((v >>> 20) & 0xF00000) + + ((v >>> 16) & 0xF0000) + + ((v >>> 12) & 0xF000) + + ((v >>> 8) & 0xF00) + + ((v >>> 4) & 0xF0) + + (v & 0xF); + return (int) v; + } + + @Test + public void indexOf() throws Throwable { + byte[] bytes = "abcda".getBytes(StandardCharsets.UTF_8); + assertEquals(2, + IOUtils.indexOfChar( + bytes, 'c', 0)); + assertEquals(0, + IOUtils.indexOfChar( + bytes, 'a', 0)); + assertEquals(4, + IOUtils.indexOfChar( + bytes, 'a', 1)); + } }