簡體   English   中英

如何解析格式 yyyy-MM-ddTHH:mm:ss.SSS+ZZZZ 的 UTC 時間戳

[英]How to parse UTC timestamp of format yyyy-MM-ddTHH:mm:ss.SSS+ZZZZ

我的時間戳為2020-12-03T05:35:59.398+0000在流式批處理中收到的String格式。

我只想要2020-12-03 05:35:59作為java.sql.Timestamp實例,以便能夠將其與其他Timestamp實例進行比較。

Timestamp.valueOf() function 出現以下錯誤:

Exception in thread "main" java.time.format.DateTimeParseException : Text '2020-12-03T05:35:59.398+0000' could not be parsed at index 23

我嘗試了這里給出的答案,並且確實發生了轉換,但時間更改為2020-12-03 11:05:59

我嘗試在此處給出的格式之間進行更改,但仍然沒有解決方案。

甚至在398+0000之間有帶有奇怪+的時間戳格式嗎?

java.time

我建議您使用 java.time,現代 Java 日期和時間 API,用於您的日期和時間工作。

    DateTimeFormatter isoFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSxx");
    DateTimeFormatter sqlTimestampFormatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral(' ')
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .toFormatter();
    
    String aTimestampString = "2020-12-03T05:35:59.398+0000";
    String anotherTimestampString = "2020-12-04 06:43:58.556385";
    
    Instant anInstant = isoFormatter.parse(aTimestampString, Instant::from);
    Instant anotherInstant = LocalDateTime.parse(anotherTimestampString, sqlTimestampFormatter)
            .atOffset(ZoneOffset.UTC)
            .toInstant();
    
    if (anInstant.isBefore(anotherInstant)) {
        System.out.println(aTimestampString + " is earlier");
    } else {
        System.out.println(anotherTimestampString + " is earlier");
    }

此示例中的 Output 是:

2020-12-03T05:35:59.398+0000 更早

上面前一個字符串中的+0000是與 UTC 的偏移量 - 00 小時 00 分鍾的偏移量。 由於它為零,我們知道時間是 UTC。 我不知道另一個字符串的時區或 UTC 偏移量。 你需要知道,否則你會得到不正確的結果。 在上面的代碼中,我假設另一個字符串也是 UTC。

不要使用時間戳

我嘗試了這里給出的答案,確實發生了轉換,但時間改為2020-12-03 11:05:59

這就是Timestamp class 的混亂程度。 你得到了正確的時間戳值。 當您打印Timestamp object 時會發生什么,是您(隱式或顯式)調用其toString方法。 Timestamp.toString()混淆使用 JVM 的默認時區來呈現字符串。 因此,如果您的時間戳等於 2020-12-03T05:35:59.398 UTC 並且您的時區是亞洲/加爾各答,那么時間將轉換為亞洲/加爾各答時區和字符串2020-12-03 11:05:59返回並打印。

你沒有什么好用的老式java.sql.Timestamp class 。 它最初用於在 SQL 數據庫之間傳輸帶和不帶時區的時間戳值。 由於 JDBC 4.2 我們更喜歡OffsetDateTimeInstantLocalDateTime為此目的。 所以忘記Timestamp class。

關聯

Oracle 教程:日期時間解釋如何使用 java.time。

在 398 + 0000 之間是否有帶有奇怪 + 的時間戳格式?

398部分是秒的分數(毫秒),而+0000部分是區域偏移部分。

您可以使用格式模式uuuu-MM-dd'T'HH:mm:ss.SSSX2020-12-03T05:35:59.398+0000解析為OffsetDateTime

演示:

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String text = "2020-12-03T05:35:59.398+0000";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSX");
        OffsetDateTime odt = OffsetDateTime.parse(text, formatter);
        System.out.println(odt);
    }
}

Output:

2020-12-03T05:35:59.398Z

查看DateTimeFormatter 文檔頁面以了解有關用於格式化的字母的更多信息。

您可以使用isBeforeOffsetDateTimeisAfter函數來比較它的兩個實例。

演示:

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String text = "2020-12-03T05:35:59.398+0000";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSX");
        OffsetDateTime odt = OffsetDateTime.parse(text, formatter);
        OffsetDateTime odtNow = OffsetDateTime.now();
        System.out.println(odtNow.isBefore(odt));
        System.out.println(odtNow.isAfter(odt));
    }
}

Output:

false
true

Trail: Date Time中了解有關現代日期時間 API 的更多信息。 If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project .

java.util 的日期時間java.util及其格式 API、 SimpleDateFormat已過時且容易出錯。 建議完全停止使用它們並切換到現代日期時間 API 由於java.sql.Timestamp擴展java.util.Date ,因此建議也停止使用它。 但是,無論出於何種原因,如果您仍想在現代日期時間和舊日期時間 API 之間使用轉換,請使用Instant作為橋梁。

import java.sql.Timestamp;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String text = "2020-12-03T05:35:59.398+0000";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSX");
        OffsetDateTime odt = OffsetDateTime.parse(text, formatter);
        Instant instant = odt.toInstant();
        Timestamp timestamp = new Timestamp(instant.toEpochMilli());
        System.out.println(timestamp);
    }
}

Output:

2020-12-03 05:35:59.398

您可以將自定義DateFormatter用於非標准格式。 這是您的用例的工作示例。

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;

import static java.time.temporal.ChronoField.*;

public class Main {

    private static final DateTimeFormatter INPUT_NON_STANDARD_FORMAT;

    static {
        INPUT_NON_STANDARD_FORMAT =
                new DateTimeFormatterBuilder()
                        .parseCaseInsensitive()
                        .append(DateTimeFormatter.ISO_LOCAL_DATE)
                        .appendLiteral('T')
                        .appendValue(HOUR_OF_DAY, 2)
                        .appendLiteral(':')
                        .appendValue(MINUTE_OF_HOUR, 2)
                        .optionalStart()
                        .appendLiteral(':')
                        .appendValue(SECOND_OF_MINUTE, 2)
                        .optionalStart()
                        .appendLiteral('.')
                        .appendValue(MILLI_OF_SECOND, 3)
                        .appendLiteral("+0000")
                        .toFormatter();
    }

    public static void main(String[] args) {
        String timestamp = "2020-12-03T05:35:59.398+0000";
        final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss");
        LocalDateTime localDateTime = LocalDateTime.parse(timestamp, INPUT_NON_STANDARD_FORMAT);
        System.out.println(localDateTime.format(dateTimeFormatter));
    }
}

Output

2020-12-03 05:35:59

暫無
暫無

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

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