簡體   English   中英

將 UTC 日期轉換為毫秒

[英]Convert UTC date into milliseconds

我對當前的 UTC 時間(以毫秒為單位)不感興趣,也不需要弄亂時區。 我的原始日期已存儲為 UTC 時間戳。

我有一個以 UTC 時間存儲在數據庫中的日期,“2012-06-14 05:01:25”。 我對日期時間不感興趣,而只是對它的日期部分感興趣。 因此,在用 Java 檢索日期並排除小時、分鍾和秒之后 - 我只剩下“2012-06-14”。

如何將其轉換為 UTC 毫秒?

編輯:我錯過了“忽略一天中的時間”部分。 它現在存在,但接近尾聲......

最簡單的方法可能是使用SimpleDateFormat ,並適當設置時區:

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));

Date date = format.parse(text);
long millis = date.getTime();

(設置時區是這里的重要部分,否則它會將值解釋為本地時區。)

或者,如果您正在做任何比這更重要的事情,請使用Joda Time ,這是一個更好的日期/時間 API。 特別是, SimpleDateFormat不是線程安全的,而DateTimeFormatter是:

// This can be reused freely across threads after construction.
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
    .withLocale(Locale.US)
    .withZoneUTC();

// Option 1
DateTime datetime = formatter.parseDateTime(text);
long millis = dateTime.getMillis();

// Option 2, more direct, but harder to diagnose errors
long millis = formatter.parseMillis(text);

到目前為止,我們已經解析了整個堆。 忽略日期部分的最簡單方法就是將它四舍五入——畢竟,Java 不觀察閏秒,所以我們可以截斷它:

long millisPerDay = 24L * 60L * 60L * 1000L; // Or use TimeUnit
long dayMillis = (millis / millisPerDay) * millisPerDay;

這將“接近 1970 年”,因此如果您1970 年之前有一個日期,它將四舍五入到一天結束- 但我懷疑這不太可能成為問題。

使用 Joda Time 版本,您可以改為使用它:

DateTime dateTime = formatter.parseDateTime(text);
long millis = dateTime.toLocalDate().getLocalMillis();

我個人不會同意只取一個子字符串的想法。 盡管您實際上對保留小時/分鍾/秒並不感興趣,但我認為解析您獲得的內容然后丟棄信息是合適的。 除此之外,它會使您的代碼因錯誤數據而適當失敗,例如

"2012-06-100"

要么

"2012-06-14 25:01:25"

指出為您提供數據的任何內容中的問題,最好發現它而不是僅僅因為前 10 個字符沒問題而盲目地繼續。

更新:Ole VV的正確答案中查看使用java.time類的現代解決方案。

更簡單

Jon Skeet回答是正確的。 他很好地指出了在解析時包括而不是截斷時間信息。

但是,他的代碼可以簡化。 特別是因為Joda-Time在最新版本中獲得了一個重要的新方法: withTimeAtStartOfDay 此方法取代了現在已棄用的所有與“午夜”相關的類和方法。

指定Locale是一個好習慣,如他的代碼所示。 但在這種特殊情況下,Locale 不是必需的。

他的回答正確地暗示了 Joda-Time 庫,遠優於使用 java.util.Date、.Calendar 和 java.text.SimpleTextFormat。 這些類是出了名的麻煩,應該避免。 而是使用 Joda-Time 或 Java 8 中內置的新java.time 包(受 Joda-Time 啟發,由 JSR 310 定義)。

一天中的第一刻

如果您想要的是自紀元以來的毫秒數,則不能忽略時間。 我懷疑您想要的是將時間更改為當天的第一時刻。 在 UTC 中,這始終表示時間00:00:00.000 但請注意,在當地時區,由於夏令時和可能的其他異常情況,第一時刻可能是不同的時間。

ISO 8601

您的字符串幾乎采用標准ISO 8601格式,但我們需要將T替換為中間的空格。 然后我們可以將結果字符串直接提供給 Joda-Time,因為 Joda-Time 具有默認用於標准字符串的內置格式化程序

示例代碼

以下示例代碼假定您的問題的目的是將字符串解析為UTC時區中的日期時間值,將時間調整為當天的第一時刻,然后轉換為自Unix 紀元(開始於UTC 時間為 1970 年)。

String inputRaw = "2012-06-14 05:01:25";
String input = inputRaw.replace( " ", "T" );  // Replace SPACE with a 'T'.
DateTime dateTime = new DateTime( input, DateTimeZone.UTC );  // Parse, assuming UTC.
DateTime dateTimeTopOfTheDay = dateTime.withTimeAtStartOfDay();  // Adjust to first moment of the day.
long millisecondsSinceUnixEpoch = dateTimeTopOfTheDay.getMillis();  // Convert to millis. Use a 'long', not an 'int'.

java.time 和 JDBC 4.2

我正在提供現代答案。 現在(以及最近幾年)您應該使用 java.time,現代 Java 日期和時間 API,來處理您的日期和時間工作。 從 JDBC 4.2 開始,您可以直接從數據庫中檢索 java.time 對象(並將它們存儲到其中)。 現代 JPA 實現(至少從 Hibernate 5 開始是 Hibernate)將很樂意做同樣的事情。 所以忘記在大多數舊答案中使用的SimpleDateFormatDate和其他舊類。 提到的那些設計很差,而 java.time 使用起來要好得多。

從數據庫中檢索正確的日期時間對象

我還建議您不要從數據庫中以字符串形式檢索 UTC 時間。 如果 SQL 中的數據類型是timestamp with time zone (推薦用於 UTC 時間),則檢索OffsetDateTime 例如:

    PreparedStatement pStmt = yourDatabaseConnection
            .prepareStatement("select utc_time from your_table where id = 7;");
    ResultSet rs = pStmt.executeQuery();
    if (rs.next()) {
        OffsetDateTime utcDateTime = rs.getObject("utc_time", OffsetDateTime.class);
        long millisecondsSinceEpoch = utcDateTime.truncatedTo(ChronoUnit.DAYS)
                .toInstant()
                .toEpochMilli();
        System.out.println("Milliseconds since the epoch: " + millisecondsSinceEpoch);
    }

如果 SQL 中的類型是dateTime或沒有時區的timestamp ,我們可能需要檢索LocalDateTime (具體取決於您的 JDBC 驅動程序和數據庫會話的時區)。 它以同樣的方式進行。 要將LocalDateTime轉換為OffsetDateTime ,請參閱下面的轉換。

如果您需要從字符串轉換

如果您無法避免將 UTC 時間作為問題中的字符串,請將其解析為LocalDateTime並從那里轉換。 例如:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
    String utcTimeString = "2012-06-14 05:01:25";
    long millisecondsSinceEpoch = LocalDateTime.parse(utcTimeString, formatter)
            .atOffset(ZoneOffset.UTC)
            .toInstant()
            .toEpochMilli();
    System.out.println("Milliseconds since the epoch: " + millisecondsSinceEpoch);

輸出:

自紀元以來的毫秒數:1339650085000

關聯

將 Date 對象與 SimpleDateFormat 結合使用。

Date 中有一個名為 getTime() 的方法,它將為您返回毫秒。

解決您的問題的示例:

Date truc = new SimpleDateFormat( "y-m-d").parse( "2010-06-14");
System.out.println(truc.getTime());
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd"); //or whatever format you have
Date t = ft.parse('2014-03-20');

String result = String.format("%tQ", t);

System.out.printf("%tQ", t);

這里有兩種方法:

  1. 你把結果毫秒到一個可變的結果
  2. 直接打印出來。

我使用簡單直接的方法:

Date date = new Date(utcDateInString);
long utcDateInMilliSeconds = date.getTime();

暫無
暫無

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

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