我正在尝试使用mongodb来获取一些带有日期字段的记录,下面显示了示例记录,并希望将使用jayway jsonpath解析的日期字段转换为java.util.Date长整数。转换后的长整数与原始整数不匹配。请帮忙。
测试人员集合中的样本记录:
{
"_id" : ObjectId("5b3fe6f91e618afb473dc644"),
"dateField" : ISODate("2018-07-06T15:46:55.819Z")
}
使用jongo获取记录的Java代码如下:
List<Tester> list= jongo.runCommand("{aggregate : 'tester',pipeline:[],cursor : {batchSize :10}}")
.field("cursor")
.as(Tester.class);
for(Tester t : list)
{
System.out.println("dateField test: : : : "+t.getDateField()+" : : : : "+t.getDateField().getTime());
// Output is perfectly fine : dateField test: : : : Fri Jul 06 21:16:55 IST 2018 : : : : 1530892015819
Gson gson = new Gson();
String str = gson.toJson(t);
DocumentContext docCtx = JsonPath.parse(str);
JsonPath jsonPath = JsonPath.compile("$.dateField");
Object obj = docCtx.read(jsonPath);
System.out.println(obj);
//After parsing with jsonPath the date is retained - Jul 6, 2018 9:16:55 PM
SimpleDateFormat format = new SimpleDateFormat("MMM dd, yyyy hh:mm:ss aaa");
Date d = format.parse(obj.toString());
System.out.println(d + " : : : " + d.getTime());
//Fri Jul 06 21:16:55 IST 2018 : : : 1530892015000 - Time is not retained
}
预期: t.getDateField()。getTime()==== d.getTime()
请帮助
致谢
克里斯
答案 0 :(得分:2)
示例:
Instant // Represent a moment in UTC, with a resolution as fine as nanoseconds.
.parse( "2018-07-06T15:46:55.819Z" ) // Parse a string in standard ISO 8601 format. The `Z` on the end means UTC, pronounced “Zulu”.
.atZone( ZoneId.of( "Asia/Kolkata" ) ) // Adjust from UTC to a desired time zone. Same moment, same point on the timeline, different wall-clock time. Returns a `ZonedDateTime` object.
.toString() // Generate a String in standard ISO 8601 format. Represents the moment in our `ZonedDateTime` object.
从旧式java.util.Date
类转换为现代java.time.Instant
,然后再次返回。废话范例:
java.util.Date.from( // Convert from modern `Instant` to legacy `Date`.
myJavaUtilDate.toInstant() // Convert from legacy `Date` to modern `Instant`.
)
您正在使用非常麻烦的旧日期时间类:Date
和SimpleDateFormat
。几年前,这些被现代的 java.time 类所取代。
您的输入2018-07-06T15:46:55.819Z
为标准ISO 8601格式。解析或生成字符串时, java.time 类默认使用ISO 8601格式。因此,无需指定格式设置模式。
最后的Z
发音为Zulu
,表示UTC。 Instant
类代表UTC的时刻。
Instant instant = Instant.parse( "2018-07-06T15:46:55.819Z" ) ;
生成ISO 8601格式的输出字符串。
String output = instant.toString() ;
2018-07-06T15:46:55.819Z
您的代码忽略了时区的关键问题。与其隐式依赖JVM当前的默认时区,不如使用ZoneId
进行显式显示,即使它是ZoneId.systemDefault()
。
以continent/region
的格式指定proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用3-4个字母的缩写,例如EST
或IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。例如,您的IST
可能表示爱尔兰标准时间,印度标准时间,伊朗标准时间或其他名称。
从UTC调整为特定时区后,我们在时间轴上仍具有相同的时刻和相同的时间点。只有挂钟时间不同。
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ; // Or `ZoneId.systemDefault()`.
ZonedDateTime zdt = instant.atZone( z ) ; // Adjust from UTC to a specific time zone.
生成一个扩展为ISO 8601格式的输出字符串,以将时区名称附加在方括号中。
String output = zdt.toString() ;
2018-07-06T21:16:55.819 + 05:30 [亚洲/加尔各答]
请注意,小数秒(毫秒)仍保持不变。
由于尚未更新为支持 java.time 的旧代码,也许您必须与java.util.Date
接口(您的问题尚不清楚)。
您会发现方便的转换方法,将新方法添加到旧类中。
从java.util.Date
到java.time.Instant
。
Instant myInstant = myJavaUtilDate.toInstant() ;
按上述步骤进行。调整到所需的时区,并生成一个String
。
从现代Instant
类到传统类Date
的另一方向。
java.util.Date myDate = java.util.Date.from( myInstant ) ;
java.time 类被设计为thread-safe,并使用immutable objects模式。请注意,上面的代码如何根据原始值生成新对象,而不是更改(“变异”)原始对象。
java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
目前位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
在哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval
,YearWeek
,YearQuarter
和more。
答案 1 :(得分:1)
new SimpleDateFormat("MMM dd, yyyy hh:mm:ss aaa");
您将舍弃输入的毫秒部分,这将导致您看到的完全不同。改用它:
new SimpleDateFormat("MMM dd, yyyy hh:mm:ss.SSS aaa");
^^^^