fix(mongodb): preserve date-shaped string values

This commit is contained in:
t8y2 2026-07-18 00:10:49 +08:00
parent fec458dc2d
commit 0f02e216aa
2 changed files with 46 additions and 29 deletions

View File

@ -906,10 +906,9 @@ public final class MongoAgent {
return converted;
}
if (value instanceof String text) {
// Plain JSON strings must retain their BSON type; only explicit shell date syntax
// is converted here. Extended JSON $date values are decoded by Document.parse.
Date date = parseMongoShellDate(text);
if (date == null) {
date = parseLegacyDateDisplay(text);
}
return date == null ? value : date;
}
return value;
@ -938,28 +937,6 @@ public final class MongoAgent {
}
}
static Date parseLegacyDateDisplay(String value) {
String trimmed = value.trim();
if (!trimmed.matches("\\d{4}-\\d{2}-\\d{2}[ T]\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,3})?")) {
return null;
}
String normalized = trimmed.replace(' ', 'T');
int dot = normalized.indexOf('.');
if (dot < 0) {
normalized = normalized + ".000";
} else {
int millisStart = dot + 1;
int millisEnd = normalized.length();
normalized = normalized.substring(0, millisStart)
+ String.format("%-3s", normalized.substring(millisStart, millisEnd)).replace(' ', '0');
}
try {
return Date.from(Instant.parse(normalized + "Z"));
} catch (Exception e) {
return null;
}
}
private static Object dispatch(String method, JsonObject params) {
return switch (method) {
case AgentProtocol.METHOD_HANDSHAKE -> AgentProtocol.handshakeResult();

View File

@ -569,12 +569,52 @@ class MongoAgentTest {
}
@Test
void documentForWriteParsesLegacyDateDisplayStrings() {
Document doc = MongoAgent.documentForWrite("{\"$set\":{\"CreateDate\":\"2025-08-14 02:25:43.718\"}}");
void documentForWritePreservesDateShapedStrings() {
Document doc = MongoAgent.documentForWrite(
"{\"$set\":{\"CreateDate\":\"2025-08-14 02:25:43.718\"," +
"\"nested\":{\"updated\":\"2025-08-14T02:25:43\"}," +
"\"items\":[\"2025-08-14 02:25:43\"]}}"
);
Document set = (Document) doc.get("$set");
assertTrue(set.get("CreateDate") instanceof Date);
assertEquals(1_755_138_343_718L, ((Date) set.get("CreateDate")).getTime());
assertEquals("2025-08-14 02:25:43.718", set.getString("CreateDate"));
assertEquals("2025-08-14T02:25:43", ((Document) set.get("nested")).getString("updated"));
assertEquals("2025-08-14 02:25:43", ((List<?>) set.get("items")).get(0));
}
@Test
void documentForWriteParsesExtendedJsonDates() {
Document doc = MongoAgent.documentForWrite(
"{\"created\":{\"$date\":\"2026-06-10T13:59:31.287Z\"}," +
"\"items\":[{\"updated\":{\"$date\":{\"$numberLong\":\"1781100000000\"}}}]}"
);
assertTrue(doc.get("created") instanceof Date);
Document item = (Document) ((List<?>) doc.get("items")).get(0);
assertTrue(item.get("updated") instanceof Date);
}
@Test
void updatePipelinePreservesStringsAndParsesExplicitDates() {
List<Document> pipeline = MongoAgent.updatePipelineForWrite(
"[{\"$set\":{\"label\":\"2025-08-14 02:25:43.718\"," +
"\"created\":\"ISODate(\\\"2026-06-10T13:59:31.287Z\\\")\"}}]"
);
Document set = (Document) pipeline.get(0).get("$set");
assertEquals("2025-08-14 02:25:43.718", set.getString("label"));
assertTrue(set.get("created") instanceof Date);
}
@Test
void filterDocumentsPreserveDateShapedStrings() {
Document filter = MongoAgent.documentForWrite(
"{\"created\":\"2025-08-14 02:25:43.718\"," +
"\"updated\":{\"$date\":\"2026-06-10T13:59:31.287Z\"}}"
);
assertEquals("2025-08-14 02:25:43.718", filter.getString("created"));
assertTrue(filter.get("updated") instanceof Date);
}
@Test