From a7853abf649d33559f0569cc34b32207d7e7d365 Mon Sep 17 00:00:00 2001 From: Amir Gur Date: Tue, 2 Sep 2014 17:00:27 -0700 Subject: [PATCH 1/4] Added a util method to wrap dates with colons with double quotes. --- JSONDateUtils.java | 60 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 JSONDateUtils.java diff --git a/JSONDateUtils.java b/JSONDateUtils.java new file mode 100644 index 000000000..148dd65ad --- /dev/null +++ b/JSONDateUtils.java @@ -0,0 +1,60 @@ +package org.json; + +import java.text.ParseException; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.junit.Test; + +/** + * Use where a date format is known to have colons the values and lack wrapping double quotes, such as "{date_time:2013-06-15 09:30:09.234}" + * And the value will be correctly wrapped with double quotes. + * + * @author Amir Gur + * @since 9/2/2014 + */ + +public class JSONDateUtils { + + public static String fixJSONTimeFormat(String text, String jsonName, SimpleDateFormat sdf) throws ParseException { + int pos = text.indexOf(jsonName); + if(pos < 0) { + throw new ParseException("Can't find json name: " + jsonName, pos); + } + + int p = pos + jsonName.length() + 1; + Date date = sdf.parse(text, new ParsePosition(p)); + if(date == null) { + throw new IllegalArgumentException("Can't parse date pattern: " + sdf.toPattern() + ", in text: " + text + ", at pos: " + pos ); + } + String dateString = sdf.format(date); + return text.replace(dateString, "\"" + dateString + "\""); + } + + @Test + public void testGetDate() throws ParseException { + testOne("{date_time:2013-06-15 01:30:09.234}", "yyyy-MM-dd HH:mm:ss.SSS"); + testOne("{date_time:2013-06-15 02:30:09.234, abc:222}", "yyyy-MM-dd HH:mm:ss.SSS"); + testOne("{date_time:2013-06-15 03:30:09.234-0700}", "yyyy-MM-dd HH:mm:ss.SSSZ"); + testOne("{date_time:2013-06-15 04:30:09.234-0700, abc:222}", "yyyy-MM-dd HH:mm:ss.SSSZ"); + testOne("{ab: xyz, date_time:2013-06-15 05:30:09.234-0700}", "yyyy-MM-dd HH:mm:ss.SSSZ"); + testOne("{date_time:2013-06-15 06:30:09.234-0700, abc:222}", "yyyy-MM-dd HH:mm:ss.SSSZ"); + testOne("{date_time: 2013-06-15 07:30:09.234-0700, abc:222}", "yyyy-MM-dd HH:mm:ss.SSSZ"); + try { + testOne("{date_time:\"2013-06-15 08:30:09.234-0700\", abc:222}", "yyyy-MM-dd HH:mm:ss.SSSZ"); + } catch(IllegalArgumentException e) { + System.out.println("Exception for not legal input is expected here, since value starts with a double quote."); + } + } + + private void testOne(String jsonStr, String pattern) throws ParseException { + String jsonName = "date_time"; + SimpleDateFormat sdf = new SimpleDateFormat(pattern); + String fixed = fixJSONTimeFormat(jsonStr, jsonName, sdf); + JSONObject jsonObject = new JSONObject(fixed); + Object value = jsonObject.get(jsonName); + System.out.println("fixed: " + fixed + ", value: " + value); + } + +} From 66d5be02fa5d626fbf0332d85a5774e5476d19b7 Mon Sep 17 00:00:00 2001 From: Amir Gur Date: Tue, 2 Sep 2014 17:59:33 -0700 Subject: [PATCH 2/4] Added option to fix multiple date strings. --- JSONDateUtils.java | 52 +++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/JSONDateUtils.java b/JSONDateUtils.java index 148dd65ad..7f0976e33 100644 --- a/JSONDateUtils.java +++ b/JSONDateUtils.java @@ -11,13 +11,23 @@ * Use where a date format is known to have colons the values and lack wrapping double quotes, such as "{date_time:2013-06-15 09:30:09.234}" * And the value will be correctly wrapped with double quotes. * + * Sent as a pull request at: {@link "https://github.com/douglascrockford/JSON-java/pull/103"} + * * @author Amir Gur * @since 9/2/2014 */ public class JSONDateUtils { - public static String fixJSONTimeFormat(String text, String jsonName, SimpleDateFormat sdf) throws ParseException { + public static String fixJSONTimeFormat(String text, SimpleDateFormat sdf, String[] jsonNames) throws ParseException { + String ret = null; + for(String name : jsonNames) { + ret = fixJSONTimeFormat(ret == null ? text : ret, sdf, name); + } + return ret; + } + + public static String fixJSONTimeFormat(String text, SimpleDateFormat sdf, String jsonName) throws ParseException { int pos = text.indexOf(jsonName); if(pos < 0) { throw new ParseException("Can't find json name: " + jsonName, pos); @@ -26,35 +36,49 @@ public static String fixJSONTimeFormat(String text, String jsonName, SimpleDateF int p = pos + jsonName.length() + 1; Date date = sdf.parse(text, new ParsePosition(p)); if(date == null) { - throw new IllegalArgumentException("Can't parse date pattern: " + sdf.toPattern() + ", in text: " + text + ", at pos: " + pos ); + throw new IllegalArgumentException("Can't parse date pattern: " + sdf.toPattern() + ", in text: " + text + ", at pos: " + p); } String dateString = sdf.format(date); - return text.replace(dateString, "\"" + dateString + "\""); + String relevantString = text.substring(p); + String prefix = text.substring(0, p); + return prefix + relevantString.replaceFirst(dateString, "\"" + dateString + "\""); } @Test public void testGetDate() throws ParseException { - testOne("{date_time:2013-06-15 01:30:09.234}", "yyyy-MM-dd HH:mm:ss.SSS"); - testOne("{date_time:2013-06-15 02:30:09.234, abc:222}", "yyyy-MM-dd HH:mm:ss.SSS"); - testOne("{date_time:2013-06-15 03:30:09.234-0700}", "yyyy-MM-dd HH:mm:ss.SSSZ"); - testOne("{date_time:2013-06-15 04:30:09.234-0700, abc:222}", "yyyy-MM-dd HH:mm:ss.SSSZ"); - testOne("{ab: xyz, date_time:2013-06-15 05:30:09.234-0700}", "yyyy-MM-dd HH:mm:ss.SSSZ"); - testOne("{date_time:2013-06-15 06:30:09.234-0700, abc:222}", "yyyy-MM-dd HH:mm:ss.SSSZ"); - testOne("{date_time: 2013-06-15 07:30:09.234-0700, abc:222}", "yyyy-MM-dd HH:mm:ss.SSSZ"); + testOne("{date_time:2013-06-15 01:30:09.234}", "yyyy-MM-dd HH:mm:ss.SSS", "date_time"); + testOne("{date_time:2013-06-15 02:30:09.234, abc:222}", "yyyy-MM-dd HH:mm:ss.SSS", "date_time"); + testOne("{date_time:2013-06-15 03:30:09.234-0700}", "yyyy-MM-dd HH:mm:ss.SSSZ", "date_time"); + testOne("{date_time:2013-06-15 04:30:09.234-0700, abc:222}", "yyyy-MM-dd HH:mm:ss.SSSZ", "date_time"); + testOne("{ab: xyz, date_time:2013-06-15 05:30:09.234-0700}", "yyyy-MM-dd HH:mm:ss.SSSZ", "date_time"); + testOne("{date_time:2013-06-15 06:30:09.234-0700, abc:222}", "yyyy-MM-dd HH:mm:ss.SSSZ", "date_time"); + testOne("{date_time: 2013-06-15 07:30:09.234-0700, abc:222}", "yyyy-MM-dd HH:mm:ss.SSSZ", "date_time"); try { - testOne("{date_time:\"2013-06-15 08:30:09.234-0700\", abc:222}", "yyyy-MM-dd HH:mm:ss.SSSZ"); + testOne("{date_time:\"2013-06-15 08:30:09.234-0700\", abc:222}", "yyyy-MM-dd HH:mm:ss.SSSZ", "date_time"); } catch(IllegalArgumentException e) { System.out.println("Exception for not legal input is expected here, since value starts with a double quote."); } + testFew("{date_time:2013-06-15 09:30:09.234-0700, abc:222, date2_time:2013-06-15 09:30:09.234-0700}", "yyyy-MM-dd HH:mm:ss.SSSZ", new String[]{"date_time", "date2_time"}); + testFew("{date_time:2013-06-15 10:30:09.234-0700, abc:222, date2_time:2013-06-15 11:30:09.234-0700}", "yyyy-MM-dd HH:mm:ss.SSSZ", new String[]{"date_time", "date2_time"}); + testFew("{date_time:2013-06-15 12:30:09.234-0700, abc:222, date_time2:2013-06-15 12:30:09.234-0700}", "yyyy-MM-dd HH:mm:ss.SSSZ", new String[]{"date_time", "date_time2"}); + testFew("{date_time:2013-06-15 13:30:09.234-0700, abc:222, date_time2:2013-06-15 14:30:09.234-0700}", "yyyy-MM-dd HH:mm:ss.SSSZ", new String[]{"date_time", "date_time2"}); } - private void testOne(String jsonStr, String pattern) throws ParseException { - String jsonName = "date_time"; + private void testOne(String jsonStr, String pattern, String jsonName) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat(pattern); - String fixed = fixJSONTimeFormat(jsonStr, jsonName, sdf); + String fixed = fixJSONTimeFormat(jsonStr, sdf, jsonName); JSONObject jsonObject = new JSONObject(fixed); Object value = jsonObject.get(jsonName); System.out.println("fixed: " + fixed + ", value: " + value); } + private void testFew(String jsonStr, String pattern, String[] jsonNames) throws ParseException { + SimpleDateFormat sdf = new SimpleDateFormat(pattern); + String fixed = fixJSONTimeFormat(jsonStr, sdf, jsonNames); + JSONObject jsonObject = new JSONObject(fixed); + for(String jsonName : jsonNames) { + Object value = jsonObject.get(jsonName); + System.out.println("fixed: " + fixed + ", value: " + value); + } + } } From c0c705dab01bf8f394d0d37cf7b2b5d54acb45a4 Mon Sep 17 00:00:00 2001 From: Amir Gur Date: Fri, 5 Sep 2014 09:10:07 -0700 Subject: [PATCH 3/4] Single digit for millis is more flexible. --- JSONDateUtils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/JSONDateUtils.java b/JSONDateUtils.java index 7f0976e33..0cfd9aa85 100644 --- a/JSONDateUtils.java +++ b/JSONDateUtils.java @@ -62,6 +62,10 @@ public void testGetDate() throws ParseException { testFew("{date_time:2013-06-15 10:30:09.234-0700, abc:222, date2_time:2013-06-15 11:30:09.234-0700}", "yyyy-MM-dd HH:mm:ss.SSSZ", new String[]{"date_time", "date2_time"}); testFew("{date_time:2013-06-15 12:30:09.234-0700, abc:222, date_time2:2013-06-15 12:30:09.234-0700}", "yyyy-MM-dd HH:mm:ss.SSSZ", new String[]{"date_time", "date_time2"}); testFew("{date_time:2013-06-15 13:30:09.234-0700, abc:222, date_time2:2013-06-15 14:30:09.234-0700}", "yyyy-MM-dd HH:mm:ss.SSSZ", new String[]{"date_time", "date_time2"}); + testOne("{date_time: 2013-06-15 14:30:09.234, abc:222}", "yyyy-MM-dd HH:mm:ss.S", "date_time"); + testOne("{date_time: 2013-06-15 15:30:09.23, abc:222}", "yyyy-MM-dd HH:mm:ss.S", "date_time"); + testOne("{date_time: 2013-06-15 16:30:09.2, abc:222}", "yyyy-MM-dd HH:mm:ss.S", "date_time"); + testOne("{date_time: 2013-06-15 17:30:09.0, abc:222}", "yyyy-MM-dd HH:mm:ss.S", "date_time"); } private void testOne(String jsonStr, String pattern, String jsonName) throws ParseException { From 222015f2d3ee131d8760429e15ec6817c5c8c990 Mon Sep 17 00:00:00 2001 From: Amir Gur Date: Mon, 8 Sep 2014 13:19:10 -0700 Subject: [PATCH 4/4] Fixed a bug failing invalid json. It now handles lastModifiedDate ending with .006 on milliseconds. Removed dependency on SimpleDateFormat.format(), and kept using only the parse method. --- JSONDateUtils.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/JSONDateUtils.java b/JSONDateUtils.java index 0cfd9aa85..81d860b4d 100644 --- a/JSONDateUtils.java +++ b/JSONDateUtils.java @@ -38,10 +38,15 @@ public static String fixJSONTimeFormat(String text, SimpleDateFormat sdf, String if(date == null) { throw new IllegalArgumentException("Can't parse date pattern: " + sdf.toPattern() + ", in text: " + text + ", at pos: " + p); } - String dateString = sdf.format(date); String relevantString = text.substring(p); String prefix = text.substring(0, p); - return prefix + relevantString.replaceFirst(dateString, "\"" + dateString + "\""); + int relevantEnd = relevantString.indexOf(','); + if(relevantEnd < 0) + relevantEnd = relevantString.indexOf('}'); + if(relevantEnd < 0) + throw new ParseException("Can't find end of value: " + jsonName + ", relevantString: " + relevantString, relevantEnd); + String suffix = relevantString.substring(relevantEnd); + return prefix + "\"" + relevantString.substring(0,relevantEnd) + "\"" + suffix; } @Test @@ -66,6 +71,7 @@ public void testGetDate() throws ParseException { testOne("{date_time: 2013-06-15 15:30:09.23, abc:222}", "yyyy-MM-dd HH:mm:ss.S", "date_time"); testOne("{date_time: 2013-06-15 16:30:09.2, abc:222}", "yyyy-MM-dd HH:mm:ss.S", "date_time"); testOne("{date_time: 2013-06-15 17:30:09.0, abc:222}", "yyyy-MM-dd HH:mm:ss.S", "date_time"); + testFew("{creationDate:2014-08-15 19:01:11.588, lastModifiedDate:2014-09-08 14:44:00.006}", "yyyy-MM-dd HH:mm:ss.S", new String[]{"creationDate", "lastModifiedDate"}); } private void testOne(String jsonStr, String pattern, String jsonName) throws ParseException { @@ -79,6 +85,7 @@ private void testOne(String jsonStr, String pattern, String jsonName) throws Par private void testFew(String jsonStr, String pattern, String[] jsonNames) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat(pattern); String fixed = fixJSONTimeFormat(jsonStr, sdf, jsonNames); + System.out.println("jsonStr: " + jsonStr + ", fixed: " + fixed); JSONObject jsonObject = new JSONObject(fixed); for(String jsonName : jsonNames) { Object value = jsonObject.get(jsonName);