如何在 java 中更改 OS 时区?

How to change OS timezone in java?

我的 java 应用程序在 Ubuntu 上 运行,我有一个用例,我需要从 java 更改 OS 时区。我试图通过使用 Joda 和 Java.util.Timezone 来实现这一点。但看起来,他们只是改变了 jvm 时区而不是实际的 OS.

所以,在 server/machine 重新启动时,我正在使用旧时区。有什么方法可以从 java 实现,或者我需要依赖 Runtime.getRuntime().exec("os commands")?

注意:在这种情况下,时区将是特定于用户的(用户将定义自己的时区)。不同的实例可能有不同的时区。

这是可能的答案:

Calendar gmtTime = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
System.out.println(gmtTime.getTime());

JVM 保持其自己的默认时区,未连接到主机 OS 时区设置。

大多数 Java 实现在启动时默认为主机 OS 的当前默认时区。或者,您可以将参数传递给 JVM 启动程序以指定另一个时区。最后,调用 TimeZone.setDefault 会立即更改该 JVM 中所有应用 运行 的所有线程中所有代码的当前默认时区。

I need to change OS timezone from java.

无法使用捆绑的 Java 类。据我所知,Java 的实现不会为 Java 应用程序提供这种功能。

您可以从 Java 中调用一些本机应用程序或实用程序,这可能会改变主机 OS 时区设置。但是您必须找到这样的实用程序,并设置从 Java 到本机代码的桥接调用。或者您可以 execute a shell script 更改 OS 设置。

就 Java 代码中的日期时间处理而言,您不应依赖主机 OS 或 JVM 的默认时区。我建议始终将可选的 ZoneId (or ZoneOffset) 传递给各种日期时间方法。省略该参数会导致隐式依赖 JVM 当前的默认时区。最好指定您的 desired/expected 时区。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;

顺便说一句,请注意 Joda-Time 项目现在处于维护模式。它的创建者 Stephen Colebourne 继续在 JSR 310 定义的 java.time 类 中创建其继任者,现在与 Java 8 及更高版本捆绑在一起.

假设您有 root 权限,这将更改 Linux 中的 OS 时区:

import java.io.File;
import java.nio.file.Files;
import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;    

// ...

String zone = "Asia/Tokyo";
File source = new File("/usr/share/zoneinfo/" + zone);
File dest = new File("/etc/localtime");
Files.copy(source.toPath(), dest.toPath(), REPLACE_EXISTING, COPY_ATTRIBUTES);

请注意,更改 OS 默认时区不会影响当前进程。另请注意,这 不是 可移植的。

编辑:我同意 Stephen C 关于 运行 提升权限下的自定义代码的警告。

编辑:创建一个符号链接可能会更好,但两者都应该有效。

编辑:要永久更改 单个用户的 时区,请将 export TZ='Asia/Tokyo' 写入启动脚本,例如 .bashrc。您不需要提升权限。