java - Java保留时间的差异(以毫秒为单位)

标签 java mongodb datetime milliseconds

我正在尝试使用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()

请帮忙

问候

克里斯

最佳答案

tl; dr


您的格式化模式省略了小数秒,因此输出中不会出现毫秒。
您正在使用过时的日期时间类。使用java.time代替。


例:

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`.
)


java.time

您正在使用非常麻烦的旧日期时间类:DateSimpleDateFormat。这些在几年前被现代的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/MontrealAfrica/CasablancaPacific/Auckland。切勿使用3-4个字母的缩写,例如ESTIST,因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。例如,您的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.Datejava.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.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

现在位于Joda-Time中的maintenance mode项目建议迁移到java.time类。

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

您可以直接与数据库交换java.time对象。使用与JDBC driver或更高版本兼容的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?


Java SE 8Java SE 9Java SE 10和更高版本


内置的
标准Java API的一部分,具有捆绑的实现。
Java 9添加了一些次要功能和修复。

Java SE 6Java SE 7


ThreeTen-Backport中的大部分java.time功能都已反向移植到Java 6和7。

Android


更高版本的Android捆绑了java.time类的实现。
对于早期的Android(<26),ThreeTenABP项目改编为ThreeTen-Backport(如上所述)。请参见How to use ThreeTenABP…



ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

关于java - Java保留时间的差异(以毫秒为单位),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51218990/

相关文章:

java - 如何在 Jersey 2中注册对象(ResourceConfig)

java - 如何在java unicode中读取€字符

python-2.7 - Django - 'datetime.date' 对象没有属性 'tzinfo'

java - 当我从数据库读取 java.sql.Date 时,如何考虑它的时区?

java - 使用 Class 作为 HashMap 的键是否会导致不良影响?

ios - 在使用 Swift 3 的 iOS 上通过主键检索 Realm 对象失败

mongodb - 如何获取mongodb中所有具有对象id的记录

node.js - 更新模型内的模型

javascript - 如何在 jquery 中使用特定时区的 php 脚本中的值创建一个新的 Date() ?

java - 有效 Java 项目 47 : Know and use your libraries - Flawed random integer method example