[英]Portable way to parse local date/time (with implicit time zone)
我需要解析包含本地日期和时间的字符串。 时区未明确指定,但时间戳是特定地点的本地时间。
挑战是:
(这也意味着 DST 到标准时间切换期间的时间戳是模棱两可的,但对于那个特定的极端情况,我可以忍受一个小时的不准确。)
这是我得到的结果:
/*
* Let timestampString be the date/time string, examples:
* "2023-01-28 20:36"
* "2022-07-07 13:37"
*/
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm zzzz");
Date date = dateFormat.parse(timestampString + " CET");
System.out.println("Timestamp: " + dateFormat.format(date));
问题:这将所有内容都解释为中欧标准时间,全年无休 - 在夏季,时间偏差一小时。
使用诸如Europe/Brussels
之类的时区名称而不是CET
(它与 Java 8 上的DateTimeFormatter
和ZonedDateTime
一起使用)不起作用,因为无法识别该字符串。
Java 7 是否提供类似的东西? (最好不必求助于外部库。)
两个通用选项:
优点:面向未来; 不会遭受 Java 的Date
和相关类中的错误; 给你 一些 Java 8 个 API
缺点:将在 API 26 (Android 8) 之前的 Android 上运行,但不能在 JRE7 上运行; 可能需要工具链升级(无论如何你最终都需要这样做)
这是首选方式,至少如果您不必支持旧桌面 Java 版本。 Java 8 对 Android 的支持(至少部分支持)是通过称为脱糖的过程完成的。
首先,确保您至少使用 Gradle 6.1.1 和 Android Gradle 插件的 4.0.0 版。
您的build.gradle
不应指定buildToolsVersion
除非您需要一个特定的版本(然后需要为 29.0.2 或更高版本)。
然后将以下内容添加到您的build.gradle
:
android {
defaultConfig {
multiDexEnabled true
}
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.8'
}
版本 1.1.8 等同于 1.2.2 (谷歌在 2023 年 1 月推荐的版本),但适用于旧版本的 R8/D8 编译器(我在 1.2.2 上遇到错误,但 1.1.8 有效)。
到目前为止的所有更改仅适用于 Android 版本。 对于您可能在其上运行代码的其他平台,没有任何变化。
这允许您运行以下 Java 代码:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
.withZone(ZoneId.of("Europe/Brussels"));
try {
ZonedDateTime zonedDate = ZonedDateTime.parse(rawDate, formatter);
System.out.println("Timestamp: " + zonedDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm zzzz")))
} catch (DateTimeParseException e) {
// do whatever is necessary here
}
如果您需要将其传递给需要Date
的对象,您可以使用Date.from(zonedDate.toInstant())
进行转换。
优点:适用于任何 Java 7 API,无论是台式机还是 Android
缺点:不是面向未来的(因为您使用的是已弃用的类); 仍然存在 Java 的Date
和相关类中的所有错误; 将解决此特定的 API 不兼容问题,但不会解决其他问题
DateFormat
有一个setTimeZone()
方法,它接受一个TimeZone
参数(反过来,可以从Europe/Brussels
等字符串生成)。 设置它将导致日期/时间字符串被解析为该时区的本地时间,并自动调整 DST。 不需要 append 任何被解析的字符串。
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
dateFormat.setTimeZone(TimeZone.getTimeZone("Europe/Brussels"));
Date date = dateFormat.parse(timestampString);
/*
* dateFormat no longer contains a time zone, so use a separate format
* for output (with the time zone)
*/
SimpleDateFormat dateFormatOut = new SimpleDateFormat("yyyy-MM-dd HH:mm zzzz");
dateFormatOut.setTimeZone(TimeZone.getTimeZone("Europe/Brussels"));
System.out.println("Timestamp: " + dateFormatOut.format(date));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.