Hier ist ein Ruby-Skript, das ich geschrieben habe, um die Zeitzonenkonfiguration auf Ubuntu zu ändern. Ich führe es mit jruby aus (ein Ruby-Interpreter, der in einer JVM läuft).
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
Es ändert die Konfigurationsdatei ordnungsgemäß. Die Ausgabe für das Skript ist jedoch nicht wie erwartet.
Angenommen, der Standardwert für die Zeitzone ist America/Toronto
.
Wenn ich den Befehl jruby change_timezone.rb Asia/Chongqing
ausführe , die Ausgabe ist:
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!!!)
Fahren Sie mit dem Befehl jruby change_timezone.rb Europe/Amsterdam
fort , komme ich auf Folgendes:
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!!!)
Weiter geht es mit jruby change_timezone.rb Europe/Amsterdam
wieder erhalte ich Folgendes:
Europe/Amsterdam
Current Time:Thu Jul 07 21:21:27 +0200 2011
Europe/Amsterdam
Updated Time:Thu Jul 07 21:21:27 +0200 2011
Kann jemand herausfinden, warum es nicht wie erwartet funktioniert hat?
Akzeptierte Antwort:
Dies ist ein Problem bei der Bestimmung der Zeitzone durch Java unter Unix-Systemen.
Die POSIX-Spezifikation gibt nicht an, wie die Zeitzone bestimmt wird, wenn der TZ
Umgebungsvariable ist nicht gesetzt. Ich kann dazu nichts in der Linux Standard Base finden.
Die Basissystembibliothek (GNU libc) verwendet /etc/localtime
um die Zeitzone zu bestimmen. Unter nicht eingebettetem Linux also /etc/localtime
Hier werden die Zeitzoneninformationen gespeichert, und idealerweise würde die Geschichte hier enden.
(Umsehen:FreeBSD, NetBSD und OpenBSD verwenden /etc/localtime
. Solaris und einige andere verwenden /etc/TIMEZONE
. Der Rosetta Stone für Unix zeigt, was andere Unix verwenden. Dietlibc (wird in einigen eingebetteten Linux-Systemen verwendet) verwendet /etc/localtime
, während uClibc /etc/TZ
verwendet (sofern nicht gepatcht).)
Leider macht Java die Dinge anders. Debian und Ubuntu haben eine Datei namens /etc/timezone
die den Namen der Zeitzone enthält. Diese zusätzliche Datei ist für das Verpackungssystem gedacht, damit es sich einen geografischen Namen wie Europe/Amsterdam
merkt statt nur die Beschreibung der Zeitzone (Offsets über die Zeit und Anzeigenamen CET
, CEST
und CEDT
). Dies ist sowohl menschenfreundlicher als auch robust, falls das geografische Gebietsschema seine Zeitzonenregeln aktualisiert. Sun (jetzt Oracle) Java bevorzugt /etc/timezone
(oder /etc/sysconfig/clock
auf Red Hat-basierten Distributionen) siehe Fehler Nr. 6456628 in /etc/localtime
, und OpenJDK und gcj folgen diesem Beispiel.
Die Lösung ist einfach:Aktualisieren Sie immer /etc/timezone
und /etc/localtime
zusammen. Unter Debian oder Ubuntu ist die offizielle Methode zum Ändern der Zeitzone dpkg-reconfigure tzdata
. Um die Zeitzone nur für eine Anwendung zu ändern, setzen Sie den TZ
Umgebungsvariable (diese ist über alle Unix-Systeme portierbar).