繁体   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