【问题标题】:How to change OS timezone in java?如何在java中更改操作系统时区?
【发布时间】:2020-01-07 23:57:04
【问题描述】:

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

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

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

【问题讨论】:

  • 永久更改操作系统时区需要提升权限(特别是在 Linux 上,对/etc/localtime 的写入权限)。除非您的程序以 root 权限执行,否则您无法仅从 Java 中执行此操作。
  • 程序有这个权限。
  • 如果您正在运行具有提升权限的 Java 程序,那可能是个坏主意。你审核了吗?如果这是产品代码,您是否考虑过您的客户可能(应该)想要审核它?
  • 是的,如果您确定这是个好主意,您需要依靠Runtime.getRuntime().exec("os commands") 或其他方式来操作操作系统。
  • @OleV.V.:不,你没有(至少对于 Linux 来说不是)。看我的回答。

标签: java timezone jodatime


【解决方案1】:

假设您有 root 权限,这将更改 Linux 中的操作系统时区:

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);

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

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

编辑:做一个符号链接可能会更好,但任何一个都应该工作。

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

【讨论】:

    【解决方案2】:

    JVM 维护自己的默认时区,未连接到主机操作系统时区设置。

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

    我需要从 java 更改操作系统时区。

    无法使用捆绑的 Java 类。我所知道的任何 Java 实现都不会为 Java 应用程序提供这种能力。

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

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

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

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

    【讨论】:

    • OP 可能想要更改其他应用程序的操作系统时区,不一定是 java 应用程序。这是我对 的理解,但看起来,他们只是改变了 jvm 时区而不是实际的操作系统(= 我希望其他所有程序都能获得新的时区),所以我认为这个问题与JVM,也许我错了
    • @BackSlash 我建议将其作为对问题作者的澄清请求发布。我同意这个问题不清楚。
    • 是的 - 我想更改操作系统时区(偏离路线会影响该服务器上运行的其他应用程序),而不仅仅是 java。实际上,我的应用程序有一个专用的虚拟机。目前我不关心对其他应用程序的影响。
    • 时区是特定于用户的,而不是特定于应用程序的。不同的应用实例可能有不同的时区。
    【解决方案3】:

    这是可能的答案:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-16
      • 1970-01-01
      • 1970-01-01
      • 2015-10-14
      • 2017-09-07
      • 1970-01-01
      • 1970-01-01
      • 2014-10-09
      相关资源
      最近更新 更多