使用Joda-Time为Mongo插入形成正确的ISODate
我正在尝试更新需要ISODate格式的mongo中的日期字段。 在mongo中,它看起来像这样:
"crDt" : ISODate("2013-08-19T17:21:57.549Z")
我正在使用的Java框架限制使用字符串作为我的测试参数,所以我试图将该字符串与DateTimeFormatter
一起使用,以使其进入正确的ISODateTimeFormat
,然后将其传递给mongo。 我不能只传入一个看起来像我上面的字符串。 试图这样做搞砸了mongo的领域。 我正在使用的Joda-Time代码的相关位如下所示:
//I can't get this right. String crDt = "2013-01-19T15:28:58.851Z"; DateTimeFormatter parser = ISODateTimeFormat.dateHourMinuteSecondMillis(); parser.parseDateTime(crDt); // this method updates the record in mongo. This method totally works, so no // point in pasting it here, I just can't get the parser object correct to be // in the correct format once inserted, it needs to be the correct ISODate form. mongo.setCrDt(recordId, parser);
当代码运行时,我从.parseDateTime方法得到这样的错误:
java.lang.IllegalArgumentException: Invalid format: "2013-01-19T15:28:58.851Z" is malformed at "Z" at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:866)
我可以告诉我给出的字符串是不正确的解析。 我试过离开Z
,我尝试了其他组合,但每次它说它都是畸形的。 所以基本上,我的起始字符串需要什么来使.parseDateTime
工作并给我一个看起来正确的对象?
编辑:
更新以尝试下面提供的建议。 我现在遇到的问题是IllegalArgumentException,无法序列化类org.joda.time.DateTime。 所以它似乎坚持joda时间对象在禁止? 我还查看了另一个建议,查看了像Spring Data这样的mapper框架。 看起来还有很多东西需要进入这个。 真的没有简单的方法可以将其持久化为mongo吗?
EDIT2:
好的,我想我现在拥有它。 我可能没有完全掌握所有的机制,但是BasicDBObject对于DateTime不会很好。 日期对象似乎是唯一的方法,至少在我正在处理的实现中。 我做了以下事情:
DateTimeFormatter parser = ISODateTimeFormat.dateTime(); DateTime result; Date newResult; result = parser.parseDateTime(crDt); newResult = result.toDate();
然后我传入了newResult for BasicDBObject,然后在mongo中更新记录。 它工作正常,记录正确更新。
您的输入字符串格式是正确的,只要用于表示UTC即可。
更改解析器以使用与此格式匹配的解析器:
DateTimeFormatter parser = ISODateTimeFormat.dateTime();
你的其余部分对我来说没有多大意义。 您不应该传递parser
,而是传递parseDateTime
的返回值,您似乎没有捕获它。
DateTime result = parser.parseDateTime(crDt); mongo.setCrDt(recordId, result.toDate());
最后一行是否有效取决于该函数接受的内容。
我通过在Service类的构造函数中添加“Encoding Hook”解决了这个问题,我在其中对MongoDB进行了更新。 这将允许您在代码中使用org.joda.time.DateTime,并将其保存为MongoDB中的java.util.Date。
MyService.java
@Inject public MyService(com.mongodb.Client client) { BSON.addEncodingHook(DateTime.class, new JodaTimeTransformer()); BSON.addDecodingHook(Date.class, new JodaTimeTransformer()); this.mongoClient = mongoClient; }
JodaTimeTransformer.java
import java.util.Date; import org.joda.time.DateTime; public class JodaTimeTransformer implements org.bson.Transformer { @Override public Object transform(Object o) { if(o instanceof DateTime) { return ((DateTime)o).toDate(); } else if(o instanceof Date) { return new DateTime((Date) o); } throw new IllegalArgumentException("JodaTimeTransformer can only be used with DateTime or Date"); } }
马特约翰逊的回答是正确的。 但它可能更简单:将( ISO 8601 )字符串直接传递给DateTime的构造函数。 不需要格式化程序。
注意时区。 与java.util.Date对象不同,Joda-Time中的DateTime对象确实知道自己指定的时区。 您是否希望为DateTime对象分配JVM的默认时区,没有时区(UTC)或特定时区?
为日期时间分配默认时区。
DateTime dateTime = new DateTime( "2013-01-19T15:28:58.851Z" );
对于指定的UTC / GMT的日期时间(无时区偏移)。
DateTime dateTime = new DateTime( "2013-01-19T15:28:58.851Z", DateTimeZone.UTC );
对于指定特定时区的日期时间。
DateTime dateTime = new DateTime( "2013-01-19T15:28:58.851Z", DateTimeZone.forId( "Europe/Paris" ) );