调试 Java 程序以在 Ubuntu 上更改时区配置文件

Ter*_* Li 1 ubuntu java timezone

这是我编写的 ruby​​ 脚本,用于更改 Ubuntu 上的时区配置。我用jruby(在 JVM 中运行的 Ruby 解释器)运行它。

require 'java'

if ARGV.length == 0
  puts "Usage: jruby change_timezone.rb America/Toronto"
  exit
end

old_zone = File.read("../../../etc/timezone")
puts old_zone
time1 = Time.now
puts "Current Time:"+time1.localtime.to_s

new_zone = ARGV[0]
open('../../../etc/timezone','w') do |f|
  f.puts new_zone.to_s
  f.close
end

new_zone = File.read("../../../etc/timezone")
puts new_zone
time2 = Time.now
puts "Updated Time:"+time2.localtime.to_s
Run Code Online (Sandbox Code Playgroud)

它确实正确更改了配置文件。但是,脚本的输出与预期不同。

假设时区的默认值为America/Toronto。当我运行命令时jruby change_timezone.rb Asia/Chongqing,输出是:

America/Toronto
Current Time:Thu Jul 07 14:43:23 -0400 2011
Asia/Chongqing
Updated Time:Thu Jul 07 14:43:23 -0400 2011 (My Note: +0800 expected!!!)
Run Code Online (Sandbox Code Playgroud)

继续使用命令jruby change_timezone.rb Europe/Amsterdam,我最终得到以下结果:

Asia/Chongqing
Current Time:Fri Jul 08 03:18:25 +0800 2011 (My Note: it actually got updated from last run!!!)
Europe/Amsterdam
Updated Time:Fri Jul 08 03:18:25 +0800 2011 (My Note: +0200 expected!!!)
Run Code Online (Sandbox Code Playgroud)

再进一步jruby change_timezone.rb Europe/Amsterdam,我得到以下信息:

Europe/Amsterdam
Current Time:Thu Jul 07 21:21:27 +0200 2011
Europe/Amsterdam
Updated Time:Thu Jul 07 21:21:27 +0200 2011
Run Code Online (Sandbox Code Playgroud)

有人能弄清楚为什么它没有按预期工作吗?

Gil*_*il' 6

这是 Java 如何确定 unix 系统下的时区的问题。

POSIX规范没有规定如何确定时区时TZ未设置环境变量。我在Linux 标准库中找不到关于此的任何内容。该基本系统库(GNU库)使用/etc/localtime来确定的时区。所以在非嵌入式 Linux 上,/etc/localtime是存储时区信息的地方,理想情况下,故事到这里就结束了。

(环顾四周:FreeBSD、NetBSD 和 OpenBSD 使用/etc/localtime。Solaris 和其他一些使用。Unix/etc/TIMEZONERosetta Stone显示了其他unices使用的内容。Dietlibc(在某些嵌入式 Linux 系统中使用)使用/etc/localtime,而uClibc使用/etc/TZ(除非已打补丁)。)

不幸的是,Java 的处理方式不同。Debian 和 Ubuntu 有一个名为的文件/etc/timezone,其中包含时区的名称。这个额外的文件是为打包系统准备的,因此它记住地理名称,Europe/Amsterdam而不仅仅是时区的描述(随时间的偏移,以及显示名称CETCESTCEDT)。这对人类更友好,而且在地理区域更新其时区规则的情况下也很强大。Sun(现在是 Oracle)Java 更喜欢/etc/timezone(或/etc/sysconfig/clock在基于 Red Hat 的发行版上)参见 bug #6456628 to /etc/localtime,OpenJDK 和gcj效仿。

另请参阅:如何找到当前系统时区?; Java 时区搞砸了

解决方案很简单:始终更新/etc/timezone/etc/localtime一起。在 Debian 或 Ubuntu 上,更改时区的官方方法是dpkg-reconfigure tzdata. 要仅为一个应用程序更改时区,请设置TZ环境变量(这在所有 unix 系统中都是可移植的)。