in core/src/main/java/com/alibaba/druid/util/MySqlUtils.java [1436:1915]
public static ZonedDateTime parseDateTime(final byte[] str, final int off, final int len, ZoneId zoneId) {
if (str == null) {
throw new IllegalArgumentException("str not be null");
}
if (len < 8) {
throw new IllegalArgumentException(new String(str, UTF8));
}
byte y0 = str[off];
byte y1 = str[off + 1];
byte y2 = str[off + 2];
byte y3 = str[off + 3];
byte M0 = 0, M1 = 0, d0 = 0, d1 = 0;
byte h0 = 0, h1 = 0, m0 = 0, m1 = 0, s0 = 0, s1 = 0, S0 = '0', S1 = '0', S2 = '0';
final byte c4 = str[off + 4];
final byte c5 = str[off + 5];
final byte c6 = str[off + 6];
final byte c7 = str[off + 7];
byte c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18;
int nanos = 0;
switch (len) {
case 8:
// yyyyMMdd
if (c4 == '-' && c6 == '-') {
M0 = '0';
M1 = c5;
d0 = '0';
d1 = c7;
} else if (y2 == ':' && c5 == ':') {
h0 = y0;
h1 = y1;
m0 = y3;
m1 = c4;
s0 = c6;
s1 = c7;
y0 = '1';
y1 = '9';
y2 = '7';
y3 = '0';
M0 = '0';
M1 = '1';
d0 = '0';
d1 = '1';
} else {
M0 = c4;
M1 = c5;
d0 = c6;
d1 = c7;
}
break;
case 9:
// yyyy-M-dd or yyyy-MM-d
c8 = str[off + 8];
if (c4 != '-') {
throw new IllegalArgumentException(new String(str, UTF8));
}
if (c6 == '-') {
M0 = '0';
M1 = c5;
d0 = c7;
d1 = c8;
} else if (c7 == '-') {
M0 = c5;
M1 = c6;
d0 = '0';
d1 = c8;
} else {
throw new IllegalArgumentException(new String(str, UTF8));
}
break;
case 10:
c8 = str[off + 8];
c9 = str[off + 9];
// yyyy-MM-dd
if (c4 != '-' || c7 != '-') {
throw new IllegalArgumentException(new String(str, UTF8));
}
M0 = c5;
M1 = c6;
d0 = c8;
d1 = c9;
break;
case 14:
c8 = str[off + 8];
c9 = str[off + 9];
c10 = str[off + 10];
c11 = str[off + 11];
c12 = str[off + 12];
c13 = str[off + 13];
if (c8 == ' ') {
// yyyy-M-d H:m:s
if (c4 == '-' && c6 == '-' & c10 == ':' && c12 == ':') {
M0 = '0';
M1 = c5;
d0 = '0';
d1 = c7;
h0 = '0';
h1 = c9;
m0 = '0';
m1 = c11;
s0 = '0';
s1 = c13;
} else {
throw new IllegalArgumentException(new String(str, UTF8));
}
} else {
// yyyyMMddHHmmss
M0 = c4;
M1 = c5;
d0 = c6;
d1 = c7;
h0 = c8;
h1 = c9;
m0 = c10;
m1 = c11;
s0 = c12;
s1 = c13;
}
break;
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 26:
case 27:
case 28:
case 29:
if (len == 19 || len >= 23) {
c8 = str[off + 8];
c9 = str[off + 9];
c10 = str[off + 10];
c11 = str[off + 11];
c12 = str[off + 12];
c13 = str[off + 13];
c14 = str[off + 14];
c15 = str[off + 15];
c16 = str[off + 16];
c17 = str[off + 17];
c18 = str[off + 18];
// yyyy-MM-dd HH:mm:ss
if (c4 == '-' && c7 == '-'
&& (c10 == ' ' || c10 == 'T')
&& c13 == ':' && c16 == ':') {
M0 = c5;
M1 = c6;
d0 = c8;
d1 = c9;
h0 = c11;
h1 = c12;
m0 = c14;
m1 = c15;
s0 = c17;
s1 = c18;
if (len == 19) {
break;
}
// yyyy-MM-dd HH:mm:ss.SSS
final byte c19 = str[off + 19];
final byte c20 = str[off + 20];
final byte c21 = str[off + 21];
final byte c22 = str[off + 22];
if (len == 23) {
if (c19 == '.') {
S0 = c20;
S1 = c21;
S2 = c22;
} else if (c19 == ' ' && c20 == 'U' && c21 == 'T' && c22 == 'C') {
// skip
zoneId = ZoneOffset.UTC;
} else {
throw new IllegalArgumentException(new String(str, UTF8));
}
break;
}
if (c19 == '.') {
S0 = c20;
S1 = c21;
S2 = c22;
} else {
throw new IllegalArgumentException(new String(str, UTF8));
}
if (len == 29) {
final byte c23 = str[off + 23];
final byte c24 = str[off + 24];
final byte c25 = str[off + 25];
final byte c26 = str[off + 26];
final byte c27 = str[off + 27];
final byte c28 = str[off + 28];
if (c23 < '0' || c23 > '9'
|| c24 < '0' || c24 > '9'
|| c25 < '0' || c25 > '9'
|| c26 < '0' || c26 > '9'
|| c27 < '0' || c27 > '9'
|| c28 < '0' || c28 > '9') {
throw new IllegalArgumentException(new String(str, UTF8));
}
nanos = (c23 - '0') * 100000
+ (c24 - '0') * 10000
+ (c25 - '0') * 1000
+ (c26 - '0') * 100
+ (c27 - '0') * 10
+ (c28 - '0');
} else if (len == 28) {
final byte c23 = str[off + 23];
final byte c24 = str[off + 24];
final byte c25 = str[off + 25];
final byte c26 = str[off + 26];
final byte c27 = str[off + 27];
if (c23 < '0' || c23 > '9'
|| c24 < '0' || c24 > '9'
|| c25 < '0' || c25 > '9'
|| c26 < '0' || c26 > '9'
|| c27 < '0' || c27 > '9') {
throw new IllegalArgumentException(new String(str, UTF8));
}
nanos = (c23 - '0') * 100000
+ (c24 - '0') * 10000
+ (c25 - '0') * 1000
+ (c26 - '0') * 100
+ (c27 - '0') * 10;
} else if (len == 27) {
final byte c23 = str[off + 23];
final byte c24 = str[off + 24];
final byte c25 = str[off + 25];
final byte c26 = str[off + 26];
if (c23 < '0' || c23 > '9'
|| c24 < '0' || c24 > '9'
|| c25 < '0' || c25 > '9'
|| c26 < '0' || c26 > '9') {
throw new IllegalArgumentException(new String(str, UTF8));
}
nanos = (c23 - '0') * 100000
+ (c24 - '0') * 10000
+ (c25 - '0') * 1000
+ (c26 - '0') * 100;
} else if (len == 26) {
final byte c23 = str[off + 23];
final byte c24 = str[off + 24];
final byte c25 = str[off + 25];
if (c23 < '0' || c23 > '9'
|| c24 < '0' || c24 > '9'
|| c25 < '0' || c25 > '9') {
throw new IllegalArgumentException(new String(str, UTF8));
}
nanos = (c23 - '0') * 100000
+ (c24 - '0') * 10000
+ (c25 - '0') * 1000;
}
break;
}
}
if (c4 != '-') {
throw new IllegalArgumentException(new String(str, UTF8));
}
int off2;
if (c6 == '-') {
M0 = '0';
M1 = c5;
off2 = off + 7;
} else if (c7 == '-') {
M0 = c5;
M1 = c6;
off2 = off + 8;
} else {
throw new IllegalArgumentException(new String(str, UTF8));
}
{
byte n0 = str[off2];
byte n1, n2;
if ((n1 = str[off2 + 1]) == ' ' || n1 == 'T') {
d0 = '0';
d1 = n0;
off2 += 2;
} else if ((n2 = str[off2 + 2]) == ' ' || n2 == 'T') {
d0 = n0;
d1 = n1;
off2 += 3;
} else {
throw new IllegalArgumentException(new String(str, UTF8));
}
}
{
byte n0 = str[off2];
byte n1, n2;
if ((n1 = str[off2 + 1]) == ':') {
h0 = '0';
h1 = n0;
off2 += 2;
} else if ((n2 = str[off2 + 2]) == ':') {
h0 = n0;
h1 = n1;
off2 += 3;
} else {
throw new IllegalArgumentException(new String(str, UTF8));
}
}
{
byte n0 = str[off2];
byte n1, n2;
if ((n1 = str[off2 + 1]) == ':') {
m0 = '0';
m1 = n0;
off2 += 2;
} else if (off2 + 2 < off + len && (n2 = str[off2 + 2]) == ':') {
m0 = n0;
m1 = n1;
off2 += 3;
} else {
throw new IllegalArgumentException(new String(str, UTF8));
}
}
if (off2 == off + len - 1) {
s0 = '0';
s1 = str[off2];
} else if (off2 == off + len - 2) {
byte n0 = str[off2];
byte n1 = str[off2 + 1];
if (n1 == '.') {
s0 = '0';
s1 = n0;
} else {
s0 = n0;
s1 = n1;
}
} else {
byte x0 = str[off + len - 1];
byte x1 = str[off + len - 2];
byte x2 = str[off + len - 3];
byte x3 = str[off + len - 4];
int lastOff;
if (x0 == '.') {
// skip
lastOff = off + len - 2;
} else if (x1 == '.') {
S0 = x0;
lastOff = off + len - 3;
} else if (x2 == '.') {
S0 = x1;
S1 = x0;
lastOff = off + len - 4;
} else if (x3 == '.') {
S0 = x2;
S1 = x1;
S2 = x0;
lastOff = off + len - 5;
} else {
throw new IllegalArgumentException(new String(str, UTF8));
}
byte k0 = str[lastOff];
byte k1 = str[lastOff - 1];
byte k2 = str[lastOff - 2];
if (k1 == ':') {
s0 = '0';
s1 = k0;
} else if (k2 == ':') {
s1 = k0;
s0 = k1;
} else {
throw new IllegalArgumentException(new String(str, UTF8));
}
}
break;
default:
throw new IllegalArgumentException(new String(str, UTF8));
}
if (y0 < '0' || y0 > '9'
|| y1 < '0' || y1 > '9'
|| y2 < '0' || y2 > '9'
|| y3 < '0' || y3 > '9') {
throw new IllegalArgumentException(new String(str, UTF8));
}
int year = (y0 - '0') * 1000
+ (y1 - '0') * 100
+ (y2 - '0') * 10
+ (y3 - '0');
if (M0 < '0' || M0 > '1') {
throw new IllegalArgumentException(new String(str, UTF8));
}
if (M1 < '0' || M1 > '9') {
throw new IllegalArgumentException(new String(str, UTF8));
}
int month = (M0 - '0') * 10 + (M1 - '0');
if (month < 1 || month > 12) {
throw new IllegalArgumentException(new String(str, UTF8));
}
if (d0 < '0' || d0 > '9') {
throw new IllegalArgumentException(new String(str, UTF8));
}
if (d1 < '0' || d1 > '9') {
throw new IllegalArgumentException(new String(str, UTF8));
}
int dayOfMonth = (d0 - '0') * 10 + (d1 - '0');
if (dayOfMonth < 1) {
throw new IllegalArgumentException(new String(str, UTF8));
}
final int maxDayOfMonth;
switch (month) {
case 2:
maxDayOfMonth = 29;
break;
case 4:
case 6:
case 9:
case 11:
maxDayOfMonth = 30;
break;
default:
maxDayOfMonth = 31;
break;
}
if (dayOfMonth > maxDayOfMonth) {
throw new IllegalArgumentException(new String(str, UTF8));
}
ZonedDateTime zdt;
if (h0 == 0) {
zdt = LocalDate
.of(year, month, dayOfMonth)
.atStartOfDay(zoneId);
} else {
int hour = (h0 - '0') * 10 + (h1 - '0');
int minute = (m0 - '0') * 10 + (m1 - '0');
int second = (s0 - '0') * 10 + (s1 - '0');
int nanoSecond = ((S0 - '0') * 100 + (S1 - '0') * 10 + (S2 - '0')) * 1000000 + nanos;
if (hour > 24 || minute > 60 || second > 61) {
throw new IllegalArgumentException(new String(str, UTF8));
}
zdt = LocalDateTime
.of(year, month, dayOfMonth, hour, minute, second, nanoSecond)
.atZone(zoneId);
}
return zdt;
}