簡體   English   中英

java中保留時間的差異(以毫秒為單位)

[英]Discrepancy in java retaining time in 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;博士

  • 格式化模式省略了小數秒,因此輸出中不會出現毫秒數。
  • 您正在使用過時的日期時間類。 請改用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.systemDefault() ,也要使用ZoneId顯式。

continent/region的格式指定適當的時區名稱 ,例如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.util.Date接口(您的問題不明確),因為舊的代碼尚未更新以支持java.time

您將找到方便的轉換方法,舊方法中添加了新方法。

java.util.Datejava.time.Instant

Instant myInstant = myJavaUtilDate.toInstant() ;

繼續如上所示。 調整到您想要的時區,並生成一個String

走向另一個方向,從現代的Instant類到傳統的類Date

java.util.Date myDate = java.util.Date.from( myInstant ) ;

不可變的物體

java.time類設計為線程安全的 ,並使用不可變對象模式。 注意上面的代碼如何根據原始值生成新對象,而不是改變(“改變”)原始對象。


關於java.time

java.time框架內置於Java 8及更高版本中。 這些類取代了麻煩的舊遺留日期時間類,如java.util.DateCalendarSimpleDateFormat

現在處於維護模式Joda-Time項目建議遷移到java.time類。

要了解更多信息,請參閱Oracle教程 並搜索Stack Overflow以獲取許多示例和解釋。 規范是JSR 310

您可以直接與數據庫交換java.time對象。 使用符合JDBC 4.2或更高版本的JDBC驅動程序 不需要字符串,不需要java.sql.*類。

從哪里獲取java.time類?

ThreeTen-Extra項目使用其他類擴展了java.time。 該項目是未來可能添加到java.time的試驗場。 您可以在這里找到一些有用的類,比如IntervalYearWeekYearQuarter ,和更多

new SimpleDateFormat("MMM dd, yyyy hh:mm:ss aaa");

您正在丟棄輸入的毫秒部分,這會導致您看到的差異。 請改用:

new SimpleDateFormat("MMM dd, yyyy hh:mm:ss.SSS aaa");
                                           ^^^^

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM