如何从字符串中查找某个时间的时区 ID 例如"19-Jul-21 1:08:22 PM BST"?



我正在尝试从时间戳字符串的csv制作时间戳,

例如"21-Mar-21 05:01:26 GMT" and "19-Jul-21 1:08:22 BST"

SimpleDateFormat("dd-MMM-yy hh:mm:ss")获取日期。

是否可以从"GMT"或"BST"字符串中获取ZoneId?(BST是英国夏令时)

还是我需要对将一个结构映射到另一个的结构进行硬编码?

java.time

java.util日期-时间 API 及其格式设置 APISimpleDateFormat已过时且容易出错。由于java.sql.Timestamp扩展java.util.Date,它从它的父类型继承了所有不需要的东西。建议完全停止使用它们,并切换到现代日期-时间 API*

使用java.time的解决方案,现代日期时间 API:

import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "21-Mar-21 05:01:26 GMT";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd-MMM-uu HH:mm:ss VV", Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
System.out.println(zdt);
// Getting ZoneId
ZoneId zoneId = zdt.getZone();
System.out.println(zoneId);
// If required, get OffsetDateTime from the ZonedDateTime
OffsetDateTime odt = zdt.toOffsetDateTime();
System.out.println(odt);
}
}

输出:

2021-03-21T05:01:26Z[GMT]
GMT
2021-03-21T05:01:26Z

在线演示

查看此答案和此答案以了解如何将java.timeAPI 与 JDBC 配合使用。

如果您需要java.sql.Timestamp

出于任何原因,如果您需要java.sql.Timestamp,只需从ZonedDateTime中获取Instant并使用Timestamp#from得出Timestamp的值。

Timestamp timestamp = Timestamp.from(zdt.toInstant());
System.out.println(timestamp);

如果你只需要java.sql.Timestamp,你可以用以下更简单的替代方式来完成:

import java.sql.Timestamp;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "21-Mar-21 05:01:26 GMT";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd-MMM-uu HH:mm:ss VV", Locale.ENGLISH);
Instant instant = Instant.from(dtf.parse(strDateTime));
Timestamp timestamp = Timestamp.from(instant);
System.out.println(timestamp);
}
}

输出:

2021-03-21 05:01:26.0

在线演示

要了解有关现代日期-时间 API*的更多信息,请访问跟踪:日期时间

更新:

此更新基于Ole V.V.的以下宝贵评论:

new DateTimeFormatterBuilder().appendPattern("dd-MMM-uu H:mm:ss ").appendZoneText(TextStyle.SHORT, Set.of(ZoneId.of("Europe/London"))).toFormatter(Locale.ENGLISH)19-Jul-21 1:08:22 BST解析为2021-07-19T01:08:22+01:00[Europe/London],这与 OP通缉。提到的日期时间字符串有 1 位数字小时,1, 所以我们只需要一个H(反过来也05接受来自 其他字符串示例)。

演示:

import java.sql.Timestamp;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.TextStyle;
import java.util.Locale;
import java.util.Set;
public class Main {
public static void main(String[] args) {
String strDateTime = "19-Jul-21 1:08:22 BST";

DateTimeFormatter dtf = 
new DateTimeFormatterBuilder()
.appendPattern("dd-MMM-uu H:mm:ss ")
.appendZoneText(TextStyle.SHORT, Set.of(ZoneId.of("Europe/London")))
.toFormatter(Locale.ENGLISH);

Instant instant = Instant.from(dtf.parse(strDateTime));
Timestamp timestamp = Timestamp.from(instant);
System.out.println(timestamp);
}
}

输出:

2021-03-21 05:01:26.0

在线演示


* 出于任何原因,如果你必须坚持使用 Java 6 或 Java 7,你可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到 Java 6 和 7。如果您正在为 Android 项目工作,并且您的 Android API 级别仍然不符合 Java-8,请查看通过脱糖提供的 Java 8+ API 和如何在 Android Project 中使用 ThreeTenABP。

如果您知道GMTBST是您需要的唯一时区缩写,并且您知道英国夏令时BST的预期解释,则可以安全地使用Arvind Kumar Avinash的好答案。

如果您的输入中可能有更多时区缩写,并且您也知道这些缩写的正确解释,则扩展答案并不困难。只需将一组更大的首选时区传递给DateTimeFormatterBuilder.appendZoneText()。为了以下格式化程序的示例,我指定BST是英国夏令时,PST是皮特凯恩标准时间,CST表示古巴标准时间。

Set<ZoneId> preferredZones = Set.of(ZoneId.of("Europe/London"),
ZoneId.of("Pacific/Pitcairn"), ZoneId.of("America/Havana"));
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.appendPattern("dd-MMM-uu H:mm:ss ")
.appendZoneText(TextStyle.SHORT, preferredZones)
.toFormatter(Locale.ENGLISH);

如果您不知道数据中可能会出现哪个时区缩写,或者您不确定每个时区缩写的正确解释,我认为最好放弃这项任务。不好意思。这些缩写往往是模棱两可的。与其错误地解释缩写而导致错误结果,您的用户更喜欢一条消息,说明您无法解释时区缩写。

链接:时区缩写 - 全球列表。

相关内容

最新更新