如果给定无效的时区ID,为什么TimeZone.getTimeZone()方法不抛出错误?相反,它返回"如果给定的ID不能被理解,则返回GMT区域"。这个决定背后的理由是什么?
我不确定其基本原理,但他们确实为您提供了一个getAvailableIDs()
方法,使您能够确保您的时区有效。他们在javadoc中提到了这一点:
您可以使用getAvailableIDs方法遍历所有的支持的时区id。然后,您可以选择一个受支持的ID来获取时区。如果您想要的时区不是由支持的ID,然后可以指定要生成的自定义时区ID一个时区
Java出现这种和类似问题的一个原因(必须特别注意避免依赖于系统的默认语言环境、字符集和时区,以免在读取文本文件或写入文本文件失败时出现异常,因为磁盘已满等)可能是Java首先应用于编程用户界面,而不是服务器后端:在UI中,显示错误输出可能比完全失败要好,因为用户通常可以找出错误并正确解释现有输出。然而,我认为TimeZone.getTimeZone(String)
中例外的遗漏是一个设计错误。
无论如何,现在有新的更好的API可用。获取时区的现代方法(从Java 8开始)是
TimeZone.getTimeZone(ZoneId.of(zoneId));
会为无效的zone ID抛出异常。ZoneId.of(String)
接受的zone ID格式与TimeZone.getTimeZone(String)
不完全相同,但如ZoneId.of(String)
的Javadoc所示,大多数区域ID是兼容的。
基于@Jaan的回答建议使用ZoneId.of()
。以下是一种安全的方法,以防止ZoneId的ID与TimeZone的ID不完全相同:首先使用TimeZone.getAvailableIDs()
检查提供的时区ID是否像"欧洲/罗马"这样的字符串,其次使用ZoneId.of()如果它是固定偏移ID,否则无效。
/* Returns null if the timezoneID is invalid */
private static TimeZone getTimeZone(String timezoneID) {
final String[] availableTimezoneIDs = TimeZone.getAvailableIDs();
if ( ! Arrays.asList(availableTimezoneIDs).contains(timezoneID) ) {
// Unknown timezone ID, maybe a fixed offset timezone id?
if (timezoneID.equals("Z") ||
timezoneID.startsWith("+") || timezoneID.startsWith("-") ||
timezoneID.startsWith("UTC") || timezoneID.startsWith("UT") || timezoneID.startsWith("GMT")
) {
try {
return TimeZone.getTimeZone(ZoneId.of(timezoneID));
} catch (DateTimeException e) {
// Invalid fixed-offset timezone id
return null;
}
} else
// Not even a fixed offset timezone id
return null;
} else
return TimeZone.getTimeZone(timezoneID);
}