如何解析格式为yyyy-mm的utc时间戳-ddthh:mm:ss.sss+zzzz

fkaflof6  于 2021-07-06  发布在  Java
关注(0)|答案(3)|浏览(362)

我有时间戳 2020-12-03T05:35:59.398+0000String 正在流式处理批处理中接收的格式。
我只想 2020-12-03 05:35:59 作为 java.sql.Timestamp 示例,以便能够与其他示例进行比较 Timestamp 示例。
获取以下错误 Timestamp.valueOf() 功能:

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 我尝试过在这里给出的格式之间进行转换,但仍然没有解决方案。
wierd有时间戳格式吗 + 介于两者之间 398+0000 ?

63lcw9qa

63lcw9qa1#

您可以使用自定义 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));
    }
}

输出

2020-12-03 05:35:59
z0qdvdin

z0qdvdin2#

wierd+在398+0000之间是否有时间戳格式?
这个 398 部分是秒的分数(毫秒),而 +0000 零件是区域偏移零件。
你可以解析 2020-12-03T05:35:59.398+0000 变成一个 OffsetDateTime 使用格式模式, uuuu-MM-dd'T'HH:mm:ss.SSSX .
演示:

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);
    }
}

输出:

2020-12-03T05:35:59.398Z

查看datetimeformatter文档页以了解有关用于格式化的字母的更多信息。
你可以用 isBefore 以及 isAfter 的功能 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);
        OffsetDateTime odtNow = OffsetDateTime.now();
        System.out.println(odtNow.isBefore(odt));
        System.out.println(odtNow.isAfter(odt));
    }
}

输出:

false
true

在trail:date-time了解有关现代日期时间api的更多信息。如果您正在为一个android项目工作,并且您的android api级别仍然不符合java-8,请检查通过desugaring提供的java8+api以及如何在android项目中使用threetenabp。
api的日期时间 java.util 以及它们的格式化api, SimpleDateFormat 过时且容易出错。建议完全停止使用它们,并切换到现代日期时间api。自 java.sql.Timestamp 延伸 java.util.Date ,建议也停止使用。但是,无论出于何种原因,如果仍要在现代日期时间api和传统日期时间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);
    }
}

输出:

2020-12-03 05:35:59.398
7hiiyaii

7hiiyaii3#

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");
    }

此示例的输出为:
2020-12-03t05:35:59.398+0000更早
这个 +0000 在上面的前一个字符串中是utc的偏移量-偏移量为00小时00分钟。因为它是零,我们知道时间是utc。我不知道另一个字符串的时区或utc偏移量。你需要知道,否则你会得到不正确的结果。在上面的代码中,我假设另一个字符串也是utc格式的。

不使用时间戳

我尝试了这里给出的答案,转换确实发生了,但时间变为 2020-12-03 11:05:59 这是多么令人困惑的事情 Timestamp 班级是。您得到了正确的时间戳值。当你打印 Timestamp 对象,是指您正在(隐式或显式)调用 toString 方法。 Timestamp.toString() 使用jvm的默认时区来呈现字符串会令人困惑。因此,如果您的时间戳等于2020-12-03t05:35:59.398 utc,并且您的时区是,例如,亚洲/加尔各答,那么时间将转换为亚洲/加尔各答时区和字符串 2020-12-03 11:05:59 返回并打印。
你没有什么好用的老式的 java.sql.Timestamp 为…上课。它最初是用来将带时区和不带时区的时间戳值传输到sql数据库和从sql数据库传输时间戳值。由于JDBC4.2,我们更喜欢 OffsetDateTime , Instant 以及 LocalDateTime 为此目的。所以忘了那些 Timestamp 班级。

链接

oracle教程:date time解释如何使用java.time。

相关问题