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

Java 如何解析格式为yyyy-MM-ddTHH:MM:ss.SSS+ZZZZ的UTC时间戳,java,scala,timestamp,utc,timestamp-with-timezone,Java,Scala,Timestamp,Utc,Timestamp With Timezone,我的时间戳为2020-12-03T05:35:59.398+0000,为字符串格式,正在流式批处理中接收 我只想要2020-12-03 05:35:59作为java.sql.Timestamp实例,以便能够将其与其他Timestamp实例进行比较 使用Timestamp.valueOf函数获取以下错误: Exception in thread "main" java.time.format.DateTimeParseException : Text '2020-12-03T0

我的时间戳为2020-12-03T05:35:59.398+0000,为字符串格式,正在流式批处理中接收

我只想要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之间是否有时间戳格式?

对于非标准格式,您可以使用自定义日期格式化程序。下面是您的用例的工作示例

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

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数据库之间传输带时区和不带时区的时间戳值。由于JDBC4.2,我们更喜欢OffsetDateTime、Instant和LocalDateTime。所以,忘了Timestamp类吧

链接 解释如何使用java.time

wierd+在398+0000之间的时间戳是否有格式

398部分是毫秒的分数,+0000部分是分区偏移部分

您可以使用格式模式uuu-MM dd'T'HH:MM:ss.SSSX将2020-12-03T05:35:59.398+0000解析为OffsetDateTime

演示:

输出:

检查以了解有关用于格式化的字母的详细信息

您可以使用OffsetDateTime的isBefore和isAfter函数来比较它的两个实例

演示:

输出:

了解有关现代日期时间API的更多信息,请访问。如果您正在为Android项目工作,并且您的Android API级别仍然不符合Java-8,请检查并确认

java.util的日期时间API及其格式化API SimpleDataFormat已经过时,并且容易出错。建议完全停止使用,并切换到。因为,建议也停止使用它。但是,出于任何原因,如果您仍然希望使用现代和传统日期时间API之间的转换,请使用作为桥接

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);
    }
}
输出:


欢迎对问题投反对票。请在编辑后立即检查。是否可以避免使用时间戳?那门课设计拙劣,令人困惑,而且早已过时。如果您告诉我们其他时间戳的来源,我们可能能够提供更好的替代方法,例如使用OffsetDateTIme替换或转换为类。听起来您有两个字符串类型的日期,您希望将它们转换为日期/时间类型,以便对其调用比较方法。对吗?如果是这样的话,我建议使用java.time库,不要使用java.sql.Timestamp,它是旧的和过时的java.util.Date的薄包装,但是时间被更改为2020-12-03 11:05:59。不,没有改变。它刚印在你的时区,可能是亚洲/加尔各答。注意格式样式字母的情况。大写的YYYY将在新年前后带给你惊喜。
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
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
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