diff --git a/src/main/java/com/alibaba/fastjson/parser/JSONScanner.java b/src/main/java/com/alibaba/fastjson/parser/JSONScanner.java index ec74e66f8..96262ebd4 100755 --- a/src/main/java/com/alibaba/fastjson/parser/JSONScanner.java +++ b/src/main/java/com/alibaba/fastjson/parser/JSONScanner.java @@ -2346,8 +2346,44 @@ public final class JSONScanner implements JSONLexer { public boolean scanISO8601DateIfMatch(boolean strict) { int rest = text.length() - bp; + + if ((!strict) && rest > 13) { + char c0 = charAt(bp); + char c1 = charAt(bp + 1); + char c2 = charAt(bp + 2); + char c3 = charAt(bp + 3); + char c4 = charAt(bp + 4); + char c5 = charAt(bp + 5); + + char c_r0 = charAt(bp + rest - 1); + char c_r1 = charAt(bp + rest - 2); + if (c0 == '/' && c1 == 'D' && c2 == 'a' && c3 == 't' && c4 == 'e' && c5 == '(' && c_r0 == '/' && c_r1 == ')') { + int plusIndex = -1; + for (int i = 6; i < rest; ++i) { + char c = charAt(bp + i); + if (c == '+') { + plusIndex = i; + } else if (c < '0' || c > '9') { + break; + } + } + if (plusIndex == -1) { + return false; + } + int offset = bp + 6; + String numberText = this.subString(offset, plusIndex - offset); + long millis = Long.parseLong(numberText); + + Locale local = Locale.getDefault(); + calendar = Calendar.getInstance(TimeZone.getDefault(), local); + calendar.setTimeInMillis(millis); + + token = JSONToken.LITERAL_ISO8601_DATE; + return true; + } + } - if (rest == 8) { + if (rest == 8 || rest == 14 || rest == 17) { if (strict) { return false; } @@ -2360,26 +2396,54 @@ public final class JSONScanner implements JSONLexer { char M1 = charAt(bp + 5); char d0 = charAt(bp + 6); char d1 = charAt(bp + 7); - - if (!checkYear(y0, y1, y2, y3)) { - return false; - } - if (!checkMonth(M0, M1)) { - return false; - } - - if (!checkDay(d0, d1)) { + if (!checkDate(y0, y1, y2, y3, M0, M1, d0, d1)) { return false; } setCalendar(y0, y1, y2, y3, M0, M1, d0, d1); - - calendar.set(Calendar.HOUR_OF_DAY, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.SECOND, 0); - calendar.set(Calendar.MILLISECOND, 0); + if (rest != 8) { + char h0 = charAt(bp + 8); + char h1 = charAt(bp + 9); + char m0 = charAt(bp + 10); + char m1 = charAt(bp + 11); + char s0 = charAt(bp + 12); + char s1 = charAt(bp + 13); + + if(!checkTime(h0, h1, m0, m1, s0, s1)) { + return false; + } + + int millis; + if (rest == 17) { + char S0 = charAt(bp + 14); + char S1 = charAt(bp + 15); + char S2 = charAt(bp + 16); + if (S0 < '0' || S0 > '9') { + return false; + } + if (S1 < '0' || S1 > '9') { + return false; + } + if (S2 < '0' || S2 > '9') { + return false; + } + + millis = digits[S0] * 100 + digits[S1] * 10 + digits[S2]; + } else { + millis = 0; + } + + int hour = digits[h0] * 10 + digits[h1]; + int minute = digits[m0] * 10 + digits[m1]; + int seconds = digits[s0] * 10 + digits[s1]; + + calendar.set(Calendar.HOUR_OF_DAY, hour); + calendar.set(Calendar.MINUTE, minute); + calendar.set(Calendar.SECOND, seconds); + calendar.set(Calendar.MILLISECOND, millis); + } token = JSONToken.LITERAL_ISO8601_DATE; return true; } @@ -2388,31 +2452,22 @@ public final class JSONScanner implements JSONLexer { return false; } - char y0 = charAt(bp); - char y1 = charAt(bp + 1); - char y2 = charAt(bp + 2); - char y3 = charAt(bp + 3); - if (!checkYear(y0, y1, y2, y3)) { - return false; - } - if (charAt(bp + 4) != '-') { return false; } - - char M0 = charAt(bp + 5); - char M1 = charAt(bp + 6); - if (!checkMonth(M0, M1)) { - return false; - } - if (charAt(bp + 7) != '-') { return false; } + char y0 = charAt(bp); + char y1 = charAt(bp + 1); + char y2 = charAt(bp + 2); + char y3 = charAt(bp + 3); + char M0 = charAt(bp + 5); + char M1 = charAt(bp + 6); char d0 = charAt(bp + 8); char d1 = charAt(bp + 9); - if (!checkDay(d0, d1)) { + if (!checkDate(y0, y1, y2, y3, M0, M1, d0, d1)) { return false; } @@ -2437,59 +2492,21 @@ public final class JSONScanner implements JSONLexer { return false; } - char h0 = charAt(bp + 11); - char h1 = charAt(bp + 12); - if (h0 == '0') { - if (h1 < '0' || h1 > '9') { - return false; - } - } else if (h0 == '1') { - if (h1 < '0' || h1 > '9') { - return false; - } - } else if (h0 == '2') { - if (h1 < '0' || h1 > '4') { - return false; - } - } else { - return false; - } - if (charAt(bp + 13) != ':') { return false; } - - char m0 = charAt(bp + 14); - char m1 = charAt(bp + 15); - if (m0 >= '0' && m0 <= '5') { - if (m1 < '0' || m1 > '9') { - return false; - } - } else if (m0 == '6') { - if (m1 != '0') { - return false; - } - } else { - return false; - } - if (charAt(bp + 16) != ':') { return false; } + char h0 = charAt(bp + 11); + char h1 = charAt(bp + 12); + char m0 = charAt(bp + 14); + char m1 = charAt(bp + 15); char s0 = charAt(bp + 17); char s1 = charAt(bp + 18); - if (s0 >= '0' && s0 <= '5') { - if (s1 < '0' || s1 > '9') { - return false; - } - } else if (s0 == '6') { - if (s1 != '0') { - return false; - } - } else { - return false; - } + + checkTime(h0, h1, m0, m1, s0, s1); int hour = digits[h0] * 10 + digits[h1]; int minute = digits[m0] * 10 + digits[m1]; @@ -2534,6 +2551,50 @@ public final class JSONScanner implements JSONLexer { return true; } + private boolean checkTime(char h0, char h1, char m0, char m1, char s0, char s1) { + if (h0 == '0') { + if (h1 < '0' || h1 > '9') { + return false; + } + } else if (h0 == '1') { + if (h1 < '0' || h1 > '9') { + return false; + } + } else if (h0 == '2') { + if (h1 < '0' || h1 > '4') { + return false; + } + } else { + return false; + } + + if (m0 >= '0' && m0 <= '5') { + if (m1 < '0' || m1 > '9') { + return false; + } + } else if (m0 == '6') { + if (m1 != '0') { + return false; + } + } else { + return false; + } + + if (s0 >= '0' && s0 <= '5') { + if (s1 < '0' || s1 > '9') { + return false; + } + } else if (s0 == '6') { + if (s1 != '0') { + return false; + } + } else { + return false; + } + + return true; + } + private void setCalendar(char y0, char y1, char y2, char y3, char M0, char M1, char d0, char d1) { Locale local = Locale.getDefault(); calendar = Calendar.getInstance(TimeZone.getDefault(), local); @@ -2545,7 +2606,32 @@ public final class JSONScanner implements JSONLexer { calendar.set(Calendar.DAY_OF_MONTH, day); } - static boolean checkDay(char d0, char d1) { + static boolean checkDate(char y0, char y1, char y2, char y3, char M0, char M1, int d0, int d1) { + if (y0 != '1' && y0 != '2') { + return false; + } + if (y1 < '0' || y1 > '9') { + return false; + } + if (y2 < '0' || y2 > '9') { + return false; + } + if (y3 < '0' || y3 > '9') { + return false; + } + + if (M0 == '0') { + if (M1 < '1' || M1 > '9') { + return false; + } + } else if (M0 == '1') { + if (M1 != '0' && M1 != '1' && M1 != '2') { + return false; + } + } else { + return false; + } + if (d0 == '0') { if (d1 < '1' || d1 > '9') { return false; @@ -2565,38 +2651,6 @@ public final class JSONScanner implements JSONLexer { return true; } - static boolean checkMonth(char M0, char M1) { - if (M0 == '0') { - if (M1 < '1' || M1 > '9') { - return false; - } - } else if (M0 == '1') { - if (M1 != '0' && M1 != '1' && M1 != '2') { - return false; - } - } else { - return false; - } - - return true; - } - - static boolean checkYear(char y0, char y1, char y2, char y3) { - if (y0 != '1' && y0 != '2') { - return false; - } - if (y1 < '0' || y1 > '9') { - return false; - } - if (y2 < '0' || y2 > '9') { - return false; - } - if (y3 < '0' || y3 > '9') { - return false; - } - return true; - } - public Calendar getCalendar() { return this.calendar; } diff --git a/src/test/java/com/alibaba/json/bvt/parser/deser/DateParseTest7.java b/src/test/java/com/alibaba/json/bvt/parser/deser/DateParseTest7.java index 3aa639de3..591c0cab4 100644 --- a/src/test/java/com/alibaba/json/bvt/parser/deser/DateParseTest7.java +++ b/src/test/java/com/alibaba/json/bvt/parser/deser/DateParseTest7.java @@ -18,7 +18,7 @@ public class DateParseTest7 extends TestCase { System.out.println(new Date().toString()); //1369273142603 - String text = "\"19790714130723456\""; + String text = "\"19790714130723\""; Date date = JSON.parseObject(text, Date.class); Calendar calendar = Calendar.getInstance(); calendar.setTime(date); @@ -30,6 +30,6 @@ public class DateParseTest7 extends TestCase { Assert.assertEquals(13, calendar.get(Calendar.HOUR_OF_DAY)); Assert.assertEquals(7, calendar.get(Calendar.MINUTE)); Assert.assertEquals(23, calendar.get(Calendar.SECOND)); - Assert.assertEquals(456, calendar.get(Calendar.MILLISECOND)); + Assert.assertEquals(0, calendar.get(Calendar.MILLISECOND)); } } diff --git a/src/test/java/com/alibaba/json/bvt/parser/deser/DateParseTest8.java b/src/test/java/com/alibaba/json/bvt/parser/deser/DateParseTest8.java new file mode 100644 index 000000000..86b9f1255 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/parser/deser/DateParseTest8.java @@ -0,0 +1,35 @@ +package com.alibaba.json.bvt.parser.deser; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.fastjson.JSON; + + +public class DateParseTest8 extends TestCase { + public void test_date() throws Exception { + System.out.println(System.currentTimeMillis()); + + System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("1970-01-01 20:00:01").getTime()); + System.out.println(new Date().toString()); + + //1369273142603 + String text = "\"19790714130723456\""; + Date date = JSON.parseObject(text, Date.class); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + + Assert.assertEquals(1979, calendar.get(Calendar.YEAR)); + Assert.assertEquals(6, calendar.get(Calendar.MONTH)); + Assert.assertEquals(14, calendar.get(Calendar.DAY_OF_MONTH)); + + Assert.assertEquals(13, calendar.get(Calendar.HOUR_OF_DAY)); + Assert.assertEquals(7, calendar.get(Calendar.MINUTE)); + Assert.assertEquals(23, calendar.get(Calendar.SECOND)); + Assert.assertEquals(456, calendar.get(Calendar.MILLISECOND)); + } +} diff --git a/src/test/java/com/alibaba/json/bvt/parser/deser/DateParseTest9.java b/src/test/java/com/alibaba/json/bvt/parser/deser/DateParseTest9.java new file mode 100644 index 000000000..7d9725d0b --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/parser/deser/DateParseTest9.java @@ -0,0 +1,17 @@ +package com.alibaba.json.bvt.parser.deser; + +import java.util.Date; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.fastjson.JSON; + + +public class DateParseTest9 extends TestCase { + public void test_date() throws Exception { + String text = "\"/Date(1242357713797+0800)/\""; + Date date = JSON.parseObject(text, Date.class); + Assert.assertEquals(date.getTime(), 1242357713797L); + } +}