如何确保明确指定java系统属性`user.timezone`?
How to ensure that java system property `user.timezone` is explicitly specified?
我想确保我的 Java 程序总是 运行 明确指定 user.timezone
属性。我通过 -Duser.timezone=XXX
作为命令行设置。
但是,当我完全省略那个系统 属性,然后在我的程序中检查 System.getProperty("user.timezone")
的值时,它不是 null
,而是包含系统时区。所以,我无法终止我的程序,因为 属性 的值永远不会为空。
我知道我可以使用自定义系统 属性 名称(比如 tz
)来接受时区 ID,然后在我的代码中执行 TimeZone.setDefault(System.getProperty("tz"))
,但我更喜欢使用系统 属性 user.timezone
,旨在用于该原因。
有什么方法可以使用 user.timezone
系统 属性 来实现我所需要的吗?
明确指定时区作为方法调用的参数
依赖于 JVM 当前的默认时区本质上是不可靠的。 JVM 中任何应用程序的任何线程中的任何代码都可以随时通过调用 TimeZone.setDefault
来更改默认设置。这样的调用会立即影响依赖该默认值的所有其他代码。
相反,始终明确指定您 desire/expect 的时区。
此外,TimeZone
已过时,多年前被 JSR 310 中定义的现代 java.time 类 取代。具体来说,ZoneId
和 ZoneOffset
。您可以将这些 类 的对象作为可选参数传递给所有相关方法。
ZoneId z = ZoneId.of( "Africa/Casablanca" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;
UTC 是唯一的真实时间
在服务器上,通常最佳做法是将主机 OS 和 JVM 的默认时区设置为 UTC(与 UTC 的偏移量为零)。
而且您的大部分业务逻辑、日志记录和调试也都应该使用 UTC。
只需要一个时区:
- 当本地化显示给用户时。
- 特定业务规则要求的地方。
顺便说一下,属性 user.timezone
没有被列为 Java 11.
中的 standard default properties 之一
我非常同意 Basil Bourque 的回答:您的解决方案是编写您的代码,使其独立于 JVM 默认时区。同样如评论中所述,当通过 JDBC 4.2(或更高版本)将 java.time 类型与您的 SQL 数据库一起使用时,没有默认时区干扰。
此外,据我所知,驱动程序倾向于使用数据库会话时区,而不是 JVM 默认时区。您可能需要搜索数据库文档和 JDBC 驱动程序文档以了解控制会话时区的方法。
但是要回答你的问题:
String userTimezoneProp = System.getProperty("user.timezone");
boolean timezonePropertyEmpty = userTimezoneProp == null || userTimezoneProp.isEmpty();
if (timezonePropertyEmpty) {
System.err.println("You must set the user.timezone property to the same time zone as the database time zone.");
System.exit(-1);
}
只有您必须在执行任何使用默认时区的操作之前执行此操作。一旦执行了这样的操作,JVM 将查询操作系统的默认时区并相应地设置系统 属性(如果成功)。
根据文档 System.getProperty()
应该 return null
对于尚未设置的系统 属性。在此示例中,我的 Java return 编辑了一个空字符串。所以我考虑了这两种可能性。它可能对 user.timezone
来说有些特别。我没有找到任何提及它的文档。我仍然不保证该方法是防弹的。
我想确保我的 Java 程序总是 运行 明确指定 user.timezone
属性。我通过 -Duser.timezone=XXX
作为命令行设置。
但是,当我完全省略那个系统 属性,然后在我的程序中检查 System.getProperty("user.timezone")
的值时,它不是 null
,而是包含系统时区。所以,我无法终止我的程序,因为 属性 的值永远不会为空。
我知道我可以使用自定义系统 属性 名称(比如 tz
)来接受时区 ID,然后在我的代码中执行 TimeZone.setDefault(System.getProperty("tz"))
,但我更喜欢使用系统 属性 user.timezone
,旨在用于该原因。
有什么方法可以使用 user.timezone
系统 属性 来实现我所需要的吗?
明确指定时区作为方法调用的参数
依赖于 JVM 当前的默认时区本质上是不可靠的。 JVM 中任何应用程序的任何线程中的任何代码都可以随时通过调用 TimeZone.setDefault
来更改默认设置。这样的调用会立即影响依赖该默认值的所有其他代码。
相反,始终明确指定您 desire/expect 的时区。
此外,TimeZone
已过时,多年前被 JSR 310 中定义的现代 java.time 类 取代。具体来说,ZoneId
和 ZoneOffset
。您可以将这些 类 的对象作为可选参数传递给所有相关方法。
ZoneId z = ZoneId.of( "Africa/Casablanca" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;
UTC 是唯一的真实时间
在服务器上,通常最佳做法是将主机 OS 和 JVM 的默认时区设置为 UTC(与 UTC 的偏移量为零)。
而且您的大部分业务逻辑、日志记录和调试也都应该使用 UTC。
只需要一个时区:
- 当本地化显示给用户时。
- 特定业务规则要求的地方。
顺便说一下,属性 user.timezone
没有被列为 Java 11.
我非常同意 Basil Bourque 的回答:您的解决方案是编写您的代码,使其独立于 JVM 默认时区。同样如评论中所述,当通过 JDBC 4.2(或更高版本)将 java.time 类型与您的 SQL 数据库一起使用时,没有默认时区干扰。
此外,据我所知,驱动程序倾向于使用数据库会话时区,而不是 JVM 默认时区。您可能需要搜索数据库文档和 JDBC 驱动程序文档以了解控制会话时区的方法。
但是要回答你的问题:
String userTimezoneProp = System.getProperty("user.timezone");
boolean timezonePropertyEmpty = userTimezoneProp == null || userTimezoneProp.isEmpty();
if (timezonePropertyEmpty) {
System.err.println("You must set the user.timezone property to the same time zone as the database time zone.");
System.exit(-1);
}
只有您必须在执行任何使用默认时区的操作之前执行此操作。一旦执行了这样的操作,JVM 将查询操作系统的默认时区并相应地设置系统 属性(如果成功)。
根据文档 System.getProperty()
应该 return null
对于尚未设置的系统 属性。在此示例中,我的 Java return 编辑了一个空字符串。所以我考虑了这两种可能性。它可能对 user.timezone
来说有些特别。我没有找到任何提及它的文档。我仍然不保证该方法是防弹的。