一个问题是短时区名称喜欢CEST
和CET
是模棱两可的而不是标准的。理想的情况是使用IANA 时区名称(始终采用格式Continent/City
,例如America/Sao_Paulo
或Europe/Berlin
)。
我假设那CEST
是中欧夏令时,许多不同的国家都在使用它(这就是它模棱两可的原因:你不知道它是哪个国家或地区,因为它的范围太广了)。
尽管大多数缩写不被识别(由于其模糊性),但出于追溯兼容性的原因,假定了一些“默认值”。在我使用的版本(JDK 1.8.0_131)中,它默认为Europe/Paris
,但不确定这是否是您需要的。并且不能保证适用于所有缩写。在这种情况下,您可以定义要使用的首选时区(这将是一个任意选择,但没有其他方法,因为CEST
它不明确)。
另一个问题是月份和星期几是英文(Aug
and Mon
),而您没有指定java.util.Locale
. 在这种情况下,DateTimeFormatter
采用系统的默认语言环境(可能不是英语 - 检查 的值Locale.getDefault()
)。无论如何,即使在运行时,默认区域设置也可以更改,恕不另行通知,因此最好在处理本地化数据(如月份和星期几名称)时指定一个。
因此,您必须指定一个语言环境并定义一个任意时区作为首选时区,以便在CEST
找到类似名称时使用。为此,您可以使用 a java.time.format.DateTimeFormatterBuilder
、一组首选时区和 a java.time.format.TextStyle
:
// create set of preferred timezones
Set<ZoneId> zones = new HashSet<>();
// my arbitrary choice for CEST
zones.add(ZoneId.of("Europe/Brussels"));
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
// date and time
.appendPattern("EEE dd MMM yyyy hh:mm a ")
// timezone short name with custom set of preferred zones
.appendZoneText(TextStyle.SHORT, zones)
// create formatter (use English locale for month and day of week)
.toFormatter(Locale.ENGLISH);
String input = "Mon 14 Aug 2017 02:00 AM CEST";
System.out.println(ZonedDateTime.parse(input, formatter));
输出将是:
2017-08-14T02:00+02:00[欧洲/布鲁塞尔]
请注意,我用作Europe/Brussels
首选时区。您可以使用 . 检查所有可用的区域名称(并相应地选择)ZoneId.getAvailableZoneIds()
。
我正在使用hh
小时,即小时时钟字段(值从 1 到 12)。但是在您使用的代码中KK
,它是hour-of-am-pm字段(值从 0 到 11)。检查哪一个最适合您的情况。
时区是一个地区在其历史上拥有、拥有和将要拥有的所有不同偏移量的集合,以及夏令时开始和结束的日期等。如果 2 个地区在这段历史中存在一些差异,它们将有不同的时区(即使他们今天使用相同的规则)。
仅仅因为巴黎和布鲁塞尔今天使用相同的规则(CET
和CEST
),并不意味着它会永远这样(因为时区规则是由政府和法律定义的,并且不能保证它们在任何时候都不会改变在将来)。
这就是为什么您必须定义一些特定的时区而不是依赖于模棱两可的短名称(即使它们的使用很普遍且广泛)。