0

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

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

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

4

3 回答 3

2

不是很优雅,但您可以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
于 2021-08-30T11:32:28.740 回答
2

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

您可以使用regex(\.)(\d{1,2}:\d{1,2})将时.区偏移部分(正则表达式中的 group#2)之前的(正则表达式中的 group#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})", "+$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

或者,您可以使用正则表达式\.(\d{1,2}:\d{1,2})并在 group#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})", ".+$1");

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

ONLINE DEMO

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

只是推测,在负 UTC 偏移的情况下可能会出现一个减号。如果是这样,可以 strDateTime.replaceFirst("\\.(\\d{1,2}:\\d{1,2})", ".+$1")在正偏移情况下使用获取 2021010112:12:12.+10:00 ,之后可以解析正负偏移(和零)。

于 2021-08-30T14:29:59.903 回答
2

解析位置

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

    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该类是旧java.text包中唯一在 java.time 中重用的类,我个人对此感到好奇。

于 2021-08-30T18:42:51.167 回答