如何将这种格式的字符串转换为Java8次并转换为long毫秒
How to convert string with this format to Java 8 time and convert to long milliseconds
我有一个 MapperUtility class 需要从发送字符串时间的 Web 服务映射字符串 "Fri Nov 22 2013 12:12:13 GMT+0000 (UTC)"
现在,我使用以下代码将其转换为 LocalDateTime:
String time = "Fri Nov 22 2013 12:12:13 GMT+0000 (UTC)";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("E MMM dd yyyy HH:mm:ssZ");
dtf.withZone(ZoneId.of("UTC"));
LocalDateTime convertedDate = LocalDateTime.parse(time, dtf);
但我在 GMT+0000 (UTC) 开始时遇到异常。
当我删除格林威治标准时间以外的字符时,它会起作用。
将它们转换为日期时间后,我需要将它们转换为长毫秒。
请指教。谢谢
让解析器逐字接受字符串的低效方法是:
String[] timezones = {"UTC", "BST", "CET", "PST", ...};
StringBuilder sb = new StringBuilder(timezones.length * 8 + 38);
sb.append("E MMM dd yyyy HH:mm:ss' GMT'Z' ('");
for(String timezone : timezones)
sb.append("['").append(timezone).append("']");
sb.append("')'");
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(sb.toString());
String time = "Fri Nov 22 2013 12:12:13 GMT+0000 (UTC)";
ZonedDateTime convertedDate = ZonedDateTime.parse(time, dtf);
System.out.println(convertedDate);
我也改为 ZonedDateTime
因为否则它会丢弃时区并且总是 returns 12:12:13 无论 GMT+
之后是什么。
但它很快变得笨拙,因为可能的列表无穷无尽time zone abbreviations。
更好的方法是预处理字符串:
String time = "Fri Nov 22 2013 12:12:13 GMT+0000 (UTC)";
String preprocessed = time.replaceAll("(.*) GMT([+-][0-9]{4}).*", "");
System.out.println(preprocessed);
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("E MMM dd yyyy HH:mm:ssZ");
ZonedDateTime convertedDate = ZonedDateTime.parse(preprocessed, dtf);
System.out.println(convertedDate);
然后在广泛的 java.time
API 中找到到毫秒的转换有点棘手,但最终它变得如此简单:
convertedDate.toInstant().toEpochMilli()
您可以使用 DateTimeFormatterBuilder
:
构建这样的模式
static final DateTimeFormatter DF = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ofPattern("E MMM dd yyyy HH:mm:ss"))
.appendLiteral(" GMT")
.appendOffset("+HHmm", "+0000")
.optionalStart()
.appendLiteral(" (")
.appendZoneId()
.appendLiteral(')')
.optionalEnd()
.toFormatter()
.withLocale(Locale.US);
然后,只需:
String date = "Fri Nov 22 2013 12:12:13 GMT+0000 (UTC)";
long ms = OffsetDateTime.parse(date, DF).toInstant().toEpochMilli(); // 1385122333000
String time = "Fri Nov 22 2013 12:12:13 GMT+0000 (UTC)";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("E MMM dd yyyy HH:mm:ss 'GMT'xx (zzz)", Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(time, dtf);
OffsetDateTime odt = OffsetDateTime.parse(time, dtf);
boolean offsetAgrees = zdt.getOffset().equals(odt.getOffset());
if (offsetAgrees) {
long millisecondsSinceEpoch = odt.toInstant().toEpochMilli();
System.out.println("Milliseoncds: " + millisecondsSinceEpoch);
} else {
System.out.println("Offset " + odt.getOffset() + " does not agree with time zone " + zdt.getZone());
}
输出:
Milliseoncds: 1385122333000
我将 GMT
解析为文字,将 +0000
解析为偏移量,将 UTC
解析为时区缩写。对于偏移量,我们可以使用 xx
或 ZZZ
。由于 Fri
和 Nov
是英文的,我们需要指定英语语言环境。
与您的代码相比,我添加了一点复杂性,因为我们要验证偏移量和时区是否一致。 OffsetDateTime.parse
直接使用偏移量 (+0000
),而 ZonedDateTime.parse
从时区 (UTC
) 导出偏移量。我的支票非常简单,可以扩展以接受从夏令时 (DST) 和多个时区共享相同缩写的过渡中的两个可能的偏移量。
PS 不要使用 LocalDateTime
。这种类型既不能保存偏移量也不能保存时区,因此您不能再将日期和时间附加到时间线上的特定点,您需要这样做才能获得自纪元以来的毫秒数。
我有一个 MapperUtility class 需要从发送字符串时间的 Web 服务映射字符串 "Fri Nov 22 2013 12:12:13 GMT+0000 (UTC)"
现在,我使用以下代码将其转换为 LocalDateTime:
String time = "Fri Nov 22 2013 12:12:13 GMT+0000 (UTC)";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("E MMM dd yyyy HH:mm:ssZ");
dtf.withZone(ZoneId.of("UTC"));
LocalDateTime convertedDate = LocalDateTime.parse(time, dtf);
但我在 GMT+0000 (UTC) 开始时遇到异常。 当我删除格林威治标准时间以外的字符时,它会起作用。 将它们转换为日期时间后,我需要将它们转换为长毫秒。 请指教。谢谢
让解析器逐字接受字符串的低效方法是:
String[] timezones = {"UTC", "BST", "CET", "PST", ...};
StringBuilder sb = new StringBuilder(timezones.length * 8 + 38);
sb.append("E MMM dd yyyy HH:mm:ss' GMT'Z' ('");
for(String timezone : timezones)
sb.append("['").append(timezone).append("']");
sb.append("')'");
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(sb.toString());
String time = "Fri Nov 22 2013 12:12:13 GMT+0000 (UTC)";
ZonedDateTime convertedDate = ZonedDateTime.parse(time, dtf);
System.out.println(convertedDate);
我也改为 ZonedDateTime
因为否则它会丢弃时区并且总是 returns 12:12:13 无论 GMT+
之后是什么。
但它很快变得笨拙,因为可能的列表无穷无尽time zone abbreviations。
更好的方法是预处理字符串:
String time = "Fri Nov 22 2013 12:12:13 GMT+0000 (UTC)";
String preprocessed = time.replaceAll("(.*) GMT([+-][0-9]{4}).*", "");
System.out.println(preprocessed);
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("E MMM dd yyyy HH:mm:ssZ");
ZonedDateTime convertedDate = ZonedDateTime.parse(preprocessed, dtf);
System.out.println(convertedDate);
然后在广泛的 java.time
API 中找到到毫秒的转换有点棘手,但最终它变得如此简单:
convertedDate.toInstant().toEpochMilli()
您可以使用 DateTimeFormatterBuilder
:
static final DateTimeFormatter DF = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ofPattern("E MMM dd yyyy HH:mm:ss"))
.appendLiteral(" GMT")
.appendOffset("+HHmm", "+0000")
.optionalStart()
.appendLiteral(" (")
.appendZoneId()
.appendLiteral(')')
.optionalEnd()
.toFormatter()
.withLocale(Locale.US);
然后,只需:
String date = "Fri Nov 22 2013 12:12:13 GMT+0000 (UTC)";
long ms = OffsetDateTime.parse(date, DF).toInstant().toEpochMilli(); // 1385122333000
String time = "Fri Nov 22 2013 12:12:13 GMT+0000 (UTC)";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("E MMM dd yyyy HH:mm:ss 'GMT'xx (zzz)", Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(time, dtf);
OffsetDateTime odt = OffsetDateTime.parse(time, dtf);
boolean offsetAgrees = zdt.getOffset().equals(odt.getOffset());
if (offsetAgrees) {
long millisecondsSinceEpoch = odt.toInstant().toEpochMilli();
System.out.println("Milliseoncds: " + millisecondsSinceEpoch);
} else {
System.out.println("Offset " + odt.getOffset() + " does not agree with time zone " + zdt.getZone());
}
输出:
Milliseoncds: 1385122333000
我将 GMT
解析为文字,将 +0000
解析为偏移量,将 UTC
解析为时区缩写。对于偏移量,我们可以使用 xx
或 ZZZ
。由于 Fri
和 Nov
是英文的,我们需要指定英语语言环境。
与您的代码相比,我添加了一点复杂性,因为我们要验证偏移量和时区是否一致。 OffsetDateTime.parse
直接使用偏移量 (+0000
),而 ZonedDateTime.parse
从时区 (UTC
) 导出偏移量。我的支票非常简单,可以扩展以接受从夏令时 (DST) 和多个时区共享相同缩写的过渡中的两个可能的偏移量。
PS 不要使用 LocalDateTime
。这种类型既不能保存偏移量也不能保存时区,因此您不能再将日期和时间附加到时间线上的特定点,您需要这样做才能获得自纪元以来的毫秒数。