我正在尝试从时间戳字符串的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.time
API 与 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。
如果您知道GMT
和BST
是您需要的唯一时区缩写,并且您知道英国夏令时是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);
如果您不知道数据中可能会出现哪个时区缩写,或者您不确定每个时区缩写的正确解释,我认为最好放弃这项任务。不好意思。这些缩写往往是模棱两可的。与其错误地解释缩写而导致错误结果,您的用户更喜欢一条消息,说明您无法解释时区缩写。
链接:时区缩写 - 全球列表。