我有以下时间戳字符串"2021010112:12:12.10:00"
,我想将其转换为java.time.Instant
.
解析字符串的问题DateTimeFormatter
是由于最后 4 位数字之前没有时区符号。逻辑上它是yyyyMMddHH:mm:ss.
并且10:00
是时区偏移量,例如UTC+10:00
,但问题是它没有符号。
如何将此字符串解析为Instant
对象?
我有以下时间戳字符串"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
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
或者,您可以使用正则表达式,\.(\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);
}
}
使用此替代解决方案的好处如 Ole VV 的以下评论中所述:
只是推测,在负 UTC 偏移的情况下可能会出现一个减号。如果是这样,可以
strDateTime.replaceFirst("\\.(\\d{1,2}:\\d{1,2})", ".+$1")
在正偏移情况下使用获取 2021010112:12:12.+10:00 ,之后可以解析正负偏移(和零)。
已经有两个很好的答案。这是我的建议。
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 中重用的类,我个人对此感到好奇。