1.概述
提到时间戳,用户的要求可能比想象的要高。他们希望程序能够自动检测时区,并用正确的时区显示时间戳。
本文将介绍修改JVM时区的几种方法。此外,还会介绍时区管理相关一些陷阱。
2.时区简介
JVM默认会从操作系统读取时区信息。时区信息会传给TimeZone类,它会存储时区并计算夏令时。
调用getDefault方法将返回应用程序所在的时区。此外,还可以调用TimeZone.getAvailableIDs()获取应用程序支持的时区ID列表。
Java采用tz数据库规范命名时区。
3.更改时区
这节将介绍在JVM中更改时区的几种方法。
3.1.设置环境变量
让我们看看如何使用环境变量修改时区。可以添加或修改环境变量TZ。
例如,在Linux中可以使用export命令:
export TZ="America/Sao_Paulo"
设置环境变量后,程序时区现在变为America/Sao_Paulo:
Calendar calendar = Calendar.getInstance();
assertEquals(calendar.getTimeZone(), TimeZone.getTimeZone("America/Sao_Paulo"));
3.2.设置JVM参数
另一种方法是设置user.timezone参数。这个JVM参数优先于环境变量TZ。
例如,可以使用-D标志启动应用程序:
java -Duser.timezone="Asia/Kolkata" com.company.Main
同样,也可以通过应用程序设置JVM参数:
System.setProperty("user.timezone", "Asia/Kolkata");
现在可以看到时区变成了Asia/Kolkata:
Calendar calendar = Calendar.getInstance();
assertEquals(calendar.getTimeZone(), TimeZone.getTimeZone("Asia/Kolkata"));
3.3.在Java程序中设置时区
最后,还可以使用TimeZone类在Java应程序中修改JVM时区。这种方法的优先级高于环境变量和JVM参数。
设置默认时区很容易:
TimeZone.setDefault(TimeZone.getTimeZone("Portugal"));
不出所料,时区现在变成了Portugal:
Calendar calendar = Calendar.getInstance();
assertEquals(calendar.getTimeZone(), TimeZone.getTimeZone("Portugal"));
4.时间管理陷阱
4.1.使用三个字母的时区ID
尽管Java支持,但不建议使用三个字母的ID表示时区。
由于三个字母的ID含糊不清,应该使用更长的时区名称。例如,IST可以表示印度标准时间、爱尔兰标准时间,也可以是以色列标准时间。
4.2.全局设置
请注意,上面介绍的方法都是为应用程序设置全局时区。现在的应用程序中,通常设置时区的粒度更细。
例如,可能需要将时间转换为最终用户的时区,因此设置全局时区的意义就不大了。如果不用全局时区,可以考虑直接在每个date-time实例上指定时区。可以使用或ZonedDateTime 或 OffsetDateTime工具类。
5.总结
本文介绍了几种修改JVM时区的方法。可以设置系统环境变量、修改JVM参数或者在应用程序中用编程的方式修改。
所有示例代码都能在GitHub上找到。