SimpleDateFormat's getTimeZone().getID()
方法返回亚洲/耶路撒冷而非亚洲/加尔各答的格式为EEE MMM dd HH:mm:ss z yyyy
的日期。实际上,在我的开发机器中,它按预期返回亚洲/加尔各答。但在其他一些机器(生产环境)中,它返回亚洲/耶路撒冷而不是亚洲/加尔各答。知道是什么导致了这个以及如何解决它。源代码如下:
String input = "Mon Jun 12 13:29:47 IST 2017";
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
sdf.parse(input);
TimeZone timeZone = sdf.getTimeZone();
System.out.println(timeZone.getID());
答案 0 :(得分:2)
任何想法导致这个......
这是一个众所周知的问题,有三个和四个字母的时区缩写。 IST的第三种解释是爱尔兰标准时间(欧洲/都柏林)。我不知道是什么原因导致一个JVM更喜欢一种解释而不是另一种解释。在至少一种情况下,我看到它更喜欢其默认时区设置而不是其他解释。因此,如果您的开发机器具有亚洲/加尔各答时区设置而您的生产机器没有,那么这可能就是解释。但是,我不会依赖于此作为一个确定的事实,而且我还想编写足够强大的代码,以便在具有不同时区设置的计算机和JVM上运行。
......以及如何解决它。
理想解决方案:避免使用带有三个或四个字母时区缩写的日期时间字符串。首选区域偏离UTC和/或时区名称的形式为洲/城市。我承认这并非总是可行。
鉴于您的输入字符串,由于SimpleDateFormat
和TimeZone
已过时,现代Java日期和时间API对程序员更友好,并且您还使用ZonedDateTime
标记了您的问题class,现代API的一部分,让我们先采用现代解决方案:
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.appendPattern("EEE MMM dd HH:mm:ss ")
.appendZoneText(TextStyle.SHORT, Collections.singleton(ZoneId.of("Asia/Kolkata")))
.appendPattern(" uuuu")
.toFormatter(Locale.ROOT);
ZonedDateTime dateTime = ZonedDateTime.parse(input, dtf);
System.out.println(dateTime.getZone());
打印:
Asia/Kolkata
我传递给appendZoneText()
的第二个参数是一组首选时区。在the documentation中,它表示“如果要解析的纹理区域名称不唯一,将使用匹配的首选区域ID。”这就是我们在此之后的内容。
在我的计算机上,我还能够使用过时的类在您的代码中解决问题。我在解析之前插入了以下行。
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
然而,旧类的文档很模糊,所以我不太确定这个解决方案总是有效。
顺便说一句,无论您使用旧类还是现代类,我建议您始终为解析提供明确的语言环境。 “Mon”和“Jun”是英文的,因此除非您指定区域设置,否则解析将无法在具有非英语区域设置的计算机上运行。让我猜一下,你的日期字符串不是英文的,因为它来自英语区域,但仅仅因为英语是计算中的通用语言。如果是这样,我认为Locale.ROOT
是合适的。我已经在我的代码中使用它了。要在你的中使用它,请将它作为参数添加到构造函数中:
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ROOT);
Locale.ENGLISH
和其他说英语的语言区域一样有效。