Skip to content

Commit abe65f7

Browse files
committed
implement "$date": "2015-04-14T14:55:57.626Z" and "$date": "2015-04-14T14:55:57+02:00" extended json parsing in JsonReader
1 parent 1b8aad1 commit abe65f7

File tree

2 files changed

+60
-6
lines changed

2 files changed

+60
-6
lines changed

bson/src/main/org/bson/json/JsonReader.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,7 @@ private BsonBinary visitHexDataConstructor() {
784784
}
785785

786786
private long visitDateTimeConstructor() {
787-
DateFormat df = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss z");
787+
DateFormat format = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss z", Locale.ENGLISH);
788788

789789
verifyToken("(");
790790

@@ -795,7 +795,7 @@ private long visitDateTimeConstructor() {
795795
verifyToken(")");
796796
String s = token.getValue(String.class);
797797
ParsePosition pos = new ParsePosition(0);
798-
Date dateTime = df.parse(s, pos);
798+
Date dateTime = format.parse(s, pos);
799799
if (dateTime != null && pos.getIndex() == s.length()) {
800800
return dateTime.getTime();
801801
} else {
@@ -870,11 +870,26 @@ private BsonBinary visitBinDataExtendedJson() {
870870
private long visitDateTimeExtendedJson() {
871871
verifyToken(":");
872872
JsonToken valueToken = popToken();
873-
if (valueToken.getType() != JsonTokenType.INT32 && valueToken.getType() != JsonTokenType.INT64) {
874-
throw new JsonParseException("JSON reader expected an integer but found '%s'.", valueToken.getValue());
875-
}
876873
verifyToken("}");
877-
return valueToken.getValue(Long.class);
874+
875+
if (valueToken.getType() == JsonTokenType.INT32 || valueToken.getType() == JsonTokenType.INT64) {
876+
return valueToken.getValue(Long.class);
877+
} else if (valueToken.getType() == JsonTokenType.STRING) {
878+
String dateString = valueToken.getValue(String.class);
879+
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
880+
ParsePosition pos = new ParsePosition(0);
881+
format.setLenient(true);
882+
883+
Date date = format.parse(dateString, pos);
884+
885+
if (date != null && pos.getIndex() == dateString.length()) {
886+
return date.getTime();
887+
}
888+
889+
throw new JsonParseException("JSON reader expected an ISO-8601 date string but found.", dateString);
890+
} else {
891+
throw new JsonParseException("JSON reader expected an integer or string but found '%s'.", valueToken.getValue());
892+
}
878893
}
879894

880895
private MaxKey visitMaxKeyExtendedJson() {

bson/src/test/unit/org/bson/json/JsonReaderTest.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,45 @@ public void testDateTimeStrict() {
127127
assertEquals(AbstractBsonReader.State.DONE, bsonReader.getState());
128128
}
129129

130+
@Test
131+
public void testDateTimeISOString() {
132+
String json = "{ \"$date\" : \"2015-04-16T14:55:57.626Z\" }";
133+
bsonReader = new JsonReader(json);
134+
assertEquals(BsonType.DATE_TIME, bsonReader.readBsonType());
135+
assertEquals(1429196157626L, bsonReader.readDateTime());
136+
assertEquals(AbstractBsonReader.State.DONE, bsonReader.getState());
137+
}
138+
139+
@Test
140+
public void testDateTimeISOStringWithTimeOffset() {
141+
String json = "{ \"$date\" : \"2015-04-16T16:55:57.626+02:00\" }";
142+
bsonReader = new JsonReader(json);
143+
assertEquals(BsonType.DATE_TIME, bsonReader.readBsonType());
144+
assertEquals(1429196157626L, bsonReader.readDateTime());
145+
assertEquals(AbstractBsonReader.State.DONE, bsonReader.getState());
146+
}
147+
148+
@Test(expected = JsonParseException.class)
149+
public void testInvalidDateTimeISOString1() {
150+
String json = "{ \"$date\" : \"2015-04-16T16:55:57.626+02:000\" }";
151+
bsonReader = new JsonReader(json);
152+
bsonReader.readBsonType();
153+
}
154+
155+
@Test(expected = JsonParseException.class)
156+
public void testInvalidDateTimeISOString2() {
157+
String json = "{ \"$date\" : \"2015-04-16T16:55:57.626Z invalid string\" }";
158+
bsonReader = new JsonReader(json);
159+
bsonReader.readBsonType();
160+
}
161+
162+
@Test(expected = JsonParseException.class)
163+
public void testInvalidDateTimeValue() {
164+
String json = "{ \"$date\" : {} }";
165+
bsonReader = new JsonReader(json);
166+
bsonReader.readBsonType();
167+
}
168+
130169
@Test
131170
public void testDateTimeTengen() {
132171
String json = "new Date(0)";

0 commit comments

Comments
 (0)