Skip to content

Commit fe72f3f

Browse files
committed
Correct parsing of Long date values
1 parent eca936d commit fe72f3f

File tree

4 files changed

+48
-42
lines changed

4 files changed

+48
-42
lines changed

src/main/com/mongodb/util/BSONSerializerFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ public void serialize(Object obj,
395395
BSONObjectSerializer serializer, StringBuilder buf) {
396396
Date d = (Date) obj;
397397
serializer.serialize(
398-
new BasicDBObject("$date", Long.valueOf(d.getTime() / 1000L)), buf);
398+
new BasicDBObject("$date", Long.valueOf(d.getTime())), buf);
399399
}
400400

401401
});

src/main/com/mongodb/util/JSONCallback.java

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -64,41 +64,36 @@ public Object objectDone(){
6464
BSONObject b = (BSONObject)o;
6565

6666
// override the object if it's a special type
67-
if ( ! _lastArray ) {
68-
if ( b.containsField( "$oid" ) ) {
69-
o = new ObjectId((String)b.get("$oid"));
70-
if (!isStackEmpty()) {
71-
gotObjectId( name, (ObjectId)o);
72-
} else {
73-
setRoot(o);
74-
}
75-
} else if ( b.containsField( "$date" ) ) {
76-
SimpleDateFormat format =
77-
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
78-
GregorianCalendar calendar = new GregorianCalendar(new SimpleTimeZone(0, "GMT"));
79-
format.setCalendar(calendar);
67+
if (!_lastArray) {
68+
if (b.containsField("$oid")) {
69+
o = new ObjectId((String) b.get("$oid"));
70+
if (!isStackEmpty()) {
71+
gotObjectId(name, (ObjectId) o);
72+
} else {
73+
setRoot(o);
74+
}
75+
} else if (b.containsField("$date")) {
8076

81-
String txtdate = b.get("$date").toString();
77+
if(b.get("$date") instanceof Number){
78+
o = new Date(((Number)b.get("$date")).longValue());
79+
}else {
80+
SimpleDateFormat format = new SimpleDateFormat(_msDateFormat);
81+
format.setCalendar(new GregorianCalendar(new SimpleTimeZone(0, "GMT")));
82+
o = format.parse(b.get("$date").toString(), new ParsePosition(0));
8283

83-
try {
84-
// Convert from seconds to ms to match consistency
85-
// with strict JSON serialization
86-
o = new Date( Long.parseLong(txtdate) * 1000l);
87-
} catch (NumberFormatException e) {
88-
o = format.parse(txtdate, new ParsePosition(0));
8984
if (o == null) {
9085
// try older format with no ms
91-
format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
92-
format.setCalendar(calendar);
93-
o = format.parse(txtdate, new ParsePosition(0));
86+
format = new SimpleDateFormat(_secDateFormat);
87+
format.setCalendar(new GregorianCalendar(new SimpleTimeZone(0, "GMT")));
88+
o = format.parse(b.get("$date").toString(), new ParsePosition(0));
9489
}
9590
}
96-
if (!isStackEmpty()) {
97-
cur().put( name, o );
98-
} else {
99-
setRoot(o);
100-
}
101-
} else if ( b.containsField( "$regex" ) ) {
91+
if (!isStackEmpty()) {
92+
cur().put(name, o);
93+
} else {
94+
setRoot(o);
95+
}
96+
} else if ( b.containsField( "$regex" ) ) {
10297
o = Pattern.compile( (String)b.get( "$regex" ),
10398
BSON.regexFlags( (String)b.get( "$options" )) );
10499
if (!isStackEmpty()) {
@@ -158,6 +153,9 @@ public Object objectDone(){
158153
}
159154
return o;
160155
}
161-
156+
162157
private boolean _lastArray = false;
158+
159+
public static final String _msDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
160+
public static final String _secDateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'";
163161
}

src/test/com/mongodb/util/BSONSerializationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ public void testStrictSerialization() {
193193
Date d = new Date();
194194
buf = new StringBuilder();
195195
serializer.serialize(d, buf);
196-
assertEquals(buf.toString(), "{ \"$date\" : "+(d.getTime()/1000l)+"}");
196+
assertEquals(buf.toString(), "{ \"$date\" : "+(d.getTime())+"}");
197197
}
198198

199199
@org.testng.annotations.Test(groups = {"basic"})
Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.mongodb.util;
22

3+
import java.text.ParsePosition;
34
import java.text.SimpleDateFormat;
45
import java.util.Date;
56
import java.util.GregorianCalendar;
@@ -9,22 +10,29 @@ public class JSONCallbackTest extends com.mongodb.util.TestCase {
910

1011
@org.testng.annotations.Test(groups = {"basic"})
1112
public void dateParsing(){
12-
long currentTime = System.currentTimeMillis();
13-
Date rightNow = new Date();
14-
rightNow.setTime(currentTime);
1513

16-
SimpleDateFormat format =
17-
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
14+
SimpleDateFormat format = new SimpleDateFormat(JSONCallback._msDateFormat);
1815
format.setCalendar(new GregorianCalendar(new SimpleTimeZone(0, "GMT")));
16+
17+
Date rightNow = new Date();
18+
rightNow.setTime(System.currentTimeMillis());
1919

20-
Date parsedDate = (Date)JSON.parse("{ \"$date\" : "+rightNow.getTime()/1000l+"}");
21-
assertEquals(format.format(rightNow), format.format(parsedDate));
20+
Date parsedDate = (Date)JSON.parse("{ \"$date\" : "+rightNow.getTime()+"}");
21+
assertEquals(rightNow.compareTo(parsedDate), 0);
2222

23-
parsedDate = (Date)JSON.parse("{ \"$date\" : \""+rightNow.getTime()/1000l+"\"}");
24-
assertEquals(format.format(rightNow), format.format(parsedDate));
23+
// Test formatted dates with ms granularity
24+
parsedDate = (Date)JSON.parse("{ \"$date\" : \""+format.format(rightNow)+"\"}");
25+
assertEquals(
26+
parsedDate.compareTo(format.parse(format.format(rightNow), new ParsePosition(0))), 0);
27+
28+
// Test formatted dates with sec granularity
29+
format = new SimpleDateFormat(JSONCallback._secDateFormat);
30+
format.setCalendar(new GregorianCalendar(new SimpleTimeZone(0, "GMT")));
2531

2632
parsedDate = (Date)JSON.parse("{ \"$date\" : \""+format.format(rightNow)+"\"}");
27-
assertEquals(format.format(rightNow), format.format(parsedDate));
33+
assertEquals(
34+
parsedDate.compareTo(format.parse(format.format(rightNow), new ParsePosition(0))), 0);
35+
2836
}
2937

3038
}

0 commit comments

Comments
 (0)