简体   繁体   English

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

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

I have timestamp as 2020-12-03T05:35:59.398+0000 in String format being recieved in a streaming batch.我的时间戳为2020-12-03T05:35:59.398+0000在流式批处理中收到的String格式。

I want only 2020-12-03 05:35:59 as java.sql.Timestamp instance in order to be able to compare it with other Timestamp instance.我只想要2020-12-03 05:35:59作为java.sql.Timestamp实例,以便能够将其与其他Timestamp实例进行比较。

Getting following error with Timestamp.valueOf() function: 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

I tried the answer given here , and conversion did happen but the time was changed to 2020-12-03 11:05:59我尝试了这里给出的答案,并且确实发生了转换,但时间更改为2020-12-03 11:05:59

I have tried changing between the formats given here but still no solution.我尝试在此处给出的格式之间进行更改,但仍然没有解决方案。

Is there even a format for timestamp with wierd + in between 398+0000 ?甚至在398+0000之间有带有奇怪+的时间戳格式吗?

java.time java.time

I recommend that you use java.time, the modern Java date and time API, for your date and time work.我建议您使用 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 from this example is:此示例中的 Output 是:

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

The +0000 in the former string above is an offset from UTC — an offset of 00 hours 00 minutes.上面前一个字符串中的+0000是与 UTC 的偏移量 - 00 小时 00 分钟的偏移量。 Since it is zero, we know that the time is in UTC.由于它为零,我们知道时间是 UTC。 I don't know the time zone or UTC offset of the other string.我不知道另一个字符串的时区或 UTC 偏移量。 You need to know, or you will get incorrect results.你需要知道,否则你会得到不正确的结果。 In the code above I have assumed that the other string is in UTC too.在上面的代码中,我假设另一个字符串也是 UTC。

Don't use Timestamp不要使用时间戳

I tried the answer given here, and conversion did happen but the time was changed to 2020-12-03 11:05:59我尝试了这里给出的答案,确实发生了转换,但时间改为2020-12-03 11:05:59

This is how confusing the Timestamp class is.这就是Timestamp class 的混乱程度。 You got the correct timestamp value.你得到了正确的时间戳值。 What happens when you print the Timestamp object, is that you are (implicitly or explicitly) calling its toString method.当您打印Timestamp object 时会发生什么,是您(隐式或显式)调用其toString方法。 Timestamp.toString() confusingly uses the default time zone of your JVM for rendering the string. Timestamp.toString()混淆使用 JVM 的默认时区来呈现字符串。 So if your timestamp is equal to 2020-12-03T05:35:59.398 UTC and your time zone is, say, Asia/Kolkata, then time is converted to Asia/Kolkata time zone and the string 2020-12-03 11:05:59 is returned and printed.因此,如果您的时间戳等于 2020-12-03T05:35:59.398 UTC 并且您的时区是亚洲/加尔各答,那么时间将转换为亚洲/加尔各答时区和字符串2020-12-03 11:05:59返回并打印。

You have nothing good to use the old-fashioned java.sql.Timestamp class for.你没有什么好用的老式java.sql.Timestamp class 。 It was originally meant for transferring timestamp values with and without time zone to and from SQL databases.它最初用于在 SQL 数据库之间传输带和不带时区的时间戳值。 Since JDBC 4.2 we prefer OffsetDateTime , Instant and LocalDateTime for that purpose.由于 JDBC 4.2 我们更喜欢OffsetDateTimeInstantLocalDateTime为此目的。 So just forget about the Timestamp class.所以忘记Timestamp class。

Link关联

Oracle tutorial: Date Time explaining how to use java.time. Oracle 教程:日期时间解释如何使用 java.time。

Is there even a format for timestamp with wierd + in between 398+0000?在 398 + 0000 之间是否有带有奇怪 + 的时间戳格式?

The 398 part is fraction-of-second (millisecond) while the +0000 part is the zone offset part. 398部分是秒的分数(毫秒),而+0000部分是区域偏移部分。

You can parse 2020-12-03T05:35:59.398+0000 into an OffsetDateTime using the format pattern, uuuu-MM-dd'T'HH:mm:ss.SSSX .您可以使用格式模式uuuu-MM-dd'T'HH:mm:ss.SSSX2020-12-03T05:35:59.398+0000解析为OffsetDateTime

Demo:演示:

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: Output:

2020-12-03T05:35:59.398Z

Check the DateTimeFormatter documentation page to learn more about the letters used for formatting.查看DateTimeFormatter 文档页面以了解有关用于格式化的字母的更多信息。

You can use isBefore and isAfter functions of OffsetDateTime to compare its two instances.您可以使用isBeforeOffsetDateTimeisAfter函数来比较它的两个实例。

Demo:演示:

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: Output:

false
true

Learn more about the modern date-time API at Trail: Date Time .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 . 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 .

The date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. java.util 的日期时间java.util及其格式 API、 SimpleDateFormat已过时且容易出错。 It is recommended to stop using them completely and switch to the modern date-time API .建议完全停止使用它们并切换到现代日期时间 API Since java.sql.Timestamp extends java.util.Date , it is recommended to stop using that as well.由于java.sql.Timestamp扩展java.util.Date ,因此建议也停止使用它。 However, for any reason, if you still want to use conversion between the modern and the legacy date-time API, use Instant as the bridge.但是,无论出于何种原因,如果您仍想在现代日期时间和旧日期时间 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: Output:

2020-12-03 05:35:59.398

You can use a custom DateFormatter for non-standard formats.您可以将自定义DateFormatter用于非标准格式。 Here is a working example for your use case.这是您的用例的工作示例。

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 Output

2020-12-03 05:35:59

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将时间戳从yyyy-MM-ddThh:mm:ss:SSSZ格式转换为MM / dd / yyyy hh:mm:ss.SSS格式?从ISO8601到UTC - How can I convert a timestamp from yyyy-MM-ddThh:mm:ss:SSSZ format to MM/dd/yyyy hh:mm:ss.SSS format? From ISO8601 to UTC 了解具体的UTC时间格式YYYY-MM-DDTHH:MM:SS.SSSZ - Understanding specific UTC time format YYYY-MM-DDTHH:MM:SS.SSSZ 无法理解“ YYYY-MM-DDTHH:MM:SS”日期格式 - Not able to understand “YYYY-MM-DDTHH:MM:SS” date format 将sql时间戳转换为yyyy-mm-ddThh:mm:ss.sssZ - Convert sql timestamp to yyyy-mm-ddThh:mm:ss.sssZ YYYY-MM-DDThh:mm:ss在Java中老化的字符串 - YYYY-MM-DDThh:mm:ss string to age in java ISO 8601 DateTimeFormatter 截断此格式的毫秒:'YYYY-MM-DDTHH:mm:ss.sssZ' - ISO 8601 DateTimeFormatter truncates the ms of this format:'YYYY-MM-DDTHH:mm:ss.sssZ' 日期时间格式 (yyyy-mm-ddThh:mm:ss) ISO8601 格式的正则表达式 - regular expression for datetimeformat (yyyy-mm-ddThh:mm:ss) ISO8601 format 尝试在Android中将yyyy-MM-ddTHH:mm:ss-07:00转换为正确的时间 - Trying to convert yyyy-MM-ddTHH:mm:ss-07:00 to correct time in Android 如何比较 java 格式“EEE MMM dd HH:mm:ss zzz yyyy”和“yyyy-MM-dd hh:mm:sss”的日期时间? - How to compare the datetime of format "EEE MMM dd HH:mm:ss zzz yyyy" and "yyyy-MM-dd hh:mm:sss" in java? 无法使用 DateUtils.parseDate 从字符串中解析日期 YYYY-MM-DDThh:mm:ssTZD - Unable to parse date YYYY-MM-DDThh:mm:ssTZD from string using DateUtils.parseDate
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM