我正在尝试从格式为(yyyy-MM-dd HH:mm z)的字符串解析ZonedDateTime。输入字符串(2019-08-29 00:00 IST)生成UTC时间戳。
调试使我想到了将IST的ZoneId映射到的位置 大西洋/雷克雅未克没有意义。应该将其映射到亚洲。
timestamp = ZonedDateTime.parse(timeInput, DATE_WITH_TIMEZONE_FORMATTER)
.toInstant().toEpochMilli()
其中
DateTimeFormatter DATE_WITH_TIMEZONE_FORMATTER = DateTimeFormatter
.ofPattern(DATE_TIME_WITH_TIMEZONE_PATTERN).withChronology(IsoChronology.INSTANCE);
我在这里想念东西吗?
答案 0 :(得分:2)
我不知道您为什么要进入冰岛,即使在主TZDB IST
中也仅参考爱尔兰标准时间(以及1968年以前错误的爱尔兰夏令时),以色列标准时间和印度标准时间出现。冰岛的出现可能是Java时区数据库中的错误。
经过进一步调查,我发现仅当当前语言环境的 语言 设置为某些非空值时,才会出现该问题。如果创建没有指定语言的语言环境,则会得到Asia/Kolkata
,但是如果存在该语言(任何语言),它将返回Atlantic/Reykjavik
。这很可能是Java实现中的错误。
String input = "2019-08-29 00:00 IST";
Locale loc = new Locale.Builder().setRegion("US").build(); // Note no language
System.out.println(loc.toString());
DateTimeFormatter DATE_WITH_TIMEZONE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm z").withLocale(loc);
ZonedDateTime zdt = ZonedDateTime.parse(input, DATE_WITH_TIMEZONE_FORMATTER);
System.out.println(zdt);
这产生
_US
2019-08-29T00:00+05:30[Asia/Kolkata]
但要改变
Locale loc = new Locale.Builder().setLanguage("ta").build();
产生
ta
2019-08-29T00:00Z[Atlantic/Reykjavik]
无论如何,裸露的时区IST
在上下文之外都是模棱两可的。为避免混淆,如果希望IST
始终为Asia/Kolkata
,则可能必须在解析之前修改传入的数据。
答案 1 :(得分:2)
首先,如果有什么可以避免的方法,请不要依赖三个字母的时区缩写。它们是模棱两可的,可能更多。当您说IST应该映射到亚洲时,仍然保留在Asia / Tel_Aviv和Asia / Kolkata之间进行选择(以及这两个别名,即Asia / Jerusalem和Asia / Calcutta)。在世界其他地方,IST可能意味着爱尔兰的夏令时,也可能意味着冰岛的标准时间(或类似的时间;它当然是有道理的)。这不是我第一次看到IST被认可为Atlantic / Reykjavik。
如果您无法避免解析IST
,请通过appendZoneText
的两个参数DateTimeFormatterBuilder
来控制解释。它接受一组首选区域:
DateTimeFormatter DATE_WITH_TIMEZONE_FORMATTER = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd HH:mm ")
.appendZoneText(TextStyle.SHORT, Collections.singleton(ZoneId.of("Asia/Kolkata")))
.toFormatter(Locale.ENGLISH);
用我放置Asia/Kolkata
的首选首选区域替换。其余的应该不会造成麻烦:
String timeInput = "2019-08-29 00:00 IST";
ZonedDateTime zdt = ZonedDateTime.parse(timeInput, DATE_WITH_TIMEZONE_FORMATTER);
System.out.println("Parsed ZonedDateTime: "+ zdt);
long timestamp = zdt
.toInstant().toEpochMilli();
System.out.println("timestamp: " + timestamp);
输出:
Parsed ZonedDateTime: 2019-08-29T00:00+05:30[Asia/Kolkata] timestamp: 1567017000000
链接: Time Zone Abbreviations – Worldwide List(您会注意到IST在列表中排名第三,而其他缩写也含糊不清)。