将 java 时间戳字符串转换为 java 时间戳对象

convert java timestamp string to java timestamp object

我有以下时间戳字符串 "2021010112:12:12.10:00",我想将其转换为 java.time.Instant

通过 DateTimeFormatter 解析字符串的问题是由于最后 4 位数字之前缺少时区符号。从逻辑上讲,它是 yyyyMMddHH:mm:ss.10:00 是时区偏移量,例如 UTC+10:00,但问题是它没有符号。

如何将此字符串解析为 Instant 对象?

不是很优雅,但您可以 split 按点输入。这会将日期时间部分与偏移量分开,您可以将所需(和必需)的符号与值连接起来。

这就需要你知道申请哪个牌子了!代码猜不出来...

也许写一个方法接受这个输入 String 和一个符号作为参数。

由于似乎无法解析偏移量的无符号 String 表示,因此您需要如下内容:

public static void main(String[] args) {
    String timestamp = "2021010112:12:12.10:00";
    // provide a formatter that parses the datetime (the part before the dot)
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuuMMddHH:mm:ss");
    // split the timestamp String by the dot to separate datetime from offset
    String[] split = timestamp.split("\.");
    // parse the datetime part using the formatter defined above
    LocalDateTime ldt = LocalDateTime.parse(split[0], dtf);
    // and build up an offset using offset part adding a plus sign
    ZoneOffset zoneOffset = ZoneOffset.of("+" + split[1]);
    // then create an OffsetDateTime from the LocalDateTime and the ZoneOffset
    OffsetDateTime result = OffsetDateTime.of(ldt, zoneOffset);
    // finally get an Instant from it
    Instant instant = result.toInstant();  // <--- INSTANT HERE
    // and print the values
    System.out.println(result + " = " + instant.toEpochMilli());
}

这输出

2021-01-01T12:12:12+10:00 = 1609467132000

是正确的。此答案显示了解决此问题的更简单方法。

您可以使用 regex(\.)(\d{1,2}:\d{1,2}) 将时区偏移部分(正则表达式中的组#2)之前的 .(正则表达式中的组#1)替换为+.

演示:

import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2021010112:12:12.10:00";
        strDateTime = strDateTime.replaceFirst("(\.)(\d{1,2}:\d{1,2})", "+");

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuuMMddHH:mm:ssXXX", Locale.ENGLISH);
        Instant instant = OffsetDateTime.parse(strDateTime, dtf).toInstant();
        System.out.println(instant);
    }
}

输出:

2021-01-01T02:12:12Z

ONLINE DEMO

或者,您可以使用 regex\.(\d{1,2}:\d{1,2}) 并在第 1 组前面加上 + 符号。请注意,DateTimeFormatter 需要相应地进行调整。

import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2021010112:12:12.10:00";
        strDateTime = strDateTime.replaceFirst("\.(\d{1,2}:\d{1,2})", ".+");

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuuMMddHH:mm:ss.XXX", Locale.ENGLISH);
        Instant instant = OffsetDateTime.parse(strDateTime, dtf).toInstant();
        System.out.println(instant);
    }
}

ONLINE DEMO

使用此替代解决方案的好处如 Ole V.V 的以下评论所述:

Just speculating, maybe a minus sign would be present in case of a negative UTC offset. If so, maybe use strDateTime.replaceFirst("\.(\d{1,2}:\d{1,2})", ".+") to obtain 2021010112:12:12.+10:00 in the positive offset case, after which both positive and negative offset (and zero) could be parsed.

解析位置

已经有两个很好的答案了。这是我的建议。

    String timestampString = "2021010112:12:12.10:00";
    
    ParsePosition position = new ParsePosition(0);
    TemporalAccessor parsed = PARSER.parse(timestampString, position);
    LocalDateTime dateTime = LocalDateTime.from(parsed);
    
    String offsetString = timestampString.substring(position.getIndex());
    if (Character.isDigit(offsetString.charAt(0))) { // no sign
        offsetString = "+" + offsetString;
    }
    ZoneOffset offset = ZoneOffset.of(offsetString);
    
    Instant timestamp = dateTime.atOffset(offset).toInstant();
    
    System.out.println(timestamp);

输出:

2021-01-01T02:12:12Z

缺点是 TemporalAccessor 接口的使用,这是我们通常不应在应用程序代码中使用的低级接口。好处包括代码在偏移量之前接受带符号和不带符号的字符串,我们不需要任何拆分操作或其他正则表达式的应用。如果 UTC 偏移量为负,则符号必须存在,否则我们无法分辨。我们也试试这个:

    String timestampString = "2021010112:12:12.-10:00";

2021-01-01T22:12:12Z

我相信 ParsePosition class 是旧 java.text 包中唯一在 java.time 中重复使用的 class,我个人认为好奇。