Ecco uno script Ruby che ho scritto per modificare la configurazione del fuso orario su Ubuntu. Lo eseguo con jruby (un interprete Ruby in esecuzione in una JVM).
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
Cambia il file di configurazione correttamente. Tuttavia, l'output per lo script non è quello previsto.
Si supponga che il valore predefinito per il fuso orario sia America/Toronto
.
Quando eseguo il comando jruby change_timezone.rb Asia/Chongqing
, l'output è:
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!!!)
Continuando con il comando jruby change_timezone.rb Europe/Amsterdam
, finisco con quanto segue:
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!!!)
Andare oltre con jruby change_timezone.rb Europe/Amsterdam
di nuovo, ottengo quanto segue:
Europe/Amsterdam
Current Time:Thu Jul 07 21:21:27 +0200 2011
Europe/Amsterdam
Updated Time:Thu Jul 07 21:21:27 +0200 2011
Qualcuno può capire perché non ha funzionato come previsto?
Risposta accettata:
Questo è un problema nel modo in cui Java determina il fuso orario nei sistemi unix.
La specifica POSIX non specifica come determinare il fuso orario quando il TZ
la variabile di ambiente non è impostata. Non riesco a trovare nulla in Linux Standard Base a riguardo.
La libreria di sistema di base (GNU libc) usa /etc/localtime
per determinare il fuso orario. Quindi su Linux non incorporato, /etc/localtime
è dove vengono archiviate le informazioni sul fuso orario e idealmente la storia finirebbe qui.
(Guardando in giro:FreeBSD, NetBSD e OpenBSD usano /etc/localtime
. Solaris e pochi altri usano /etc/TIMEZONE
. La Rosetta Stone per Unix mostra cosa usano gli altri Unix. Dietlibc (usato in alcuni sistemi Linux embedded) usa /etc/localtime
, mentre uClibc usa /etc/TZ
(a meno che non siano corretti).)
Sfortunatamente, Java fa le cose in modo diverso. Debian e Ubuntu hanno un file chiamato /etc/timezone
che contiene il nome del fuso orario. Questo file aggiuntivo è destinato al sistema di confezionamento, in modo che ricordi un nome geografico come Europe/Amsterdam
piuttosto che solo la descrizione del fuso orario (offset nel tempo e nomi visualizzati CET
, CEST
e CEDT
). Questo è sia più amichevole per gli esseri umani che robusto nel caso in cui la località geografica aggiorni le regole del fuso orario. Sun (ora Oracle) Java preferisce /etc/timezone
(o /etc/sysconfig/clock
su distribuzioni basate su Red Hat) vedere il bug #6456628 su /etc/localtime
, e OpenJDK e gcj seguono l'esempio.
La soluzione è semplice:aggiorna sempre /etc/timezone
e /etc/localtime
insieme. Su Debian o Ubuntu, il metodo ufficiale per cambiare il fuso orario è dpkg-reconfigure tzdata
. Per modificare il fuso orario di una sola applicazione, impostare il TZ
variabile d'ambiente (portabile su tutti i sistemi Unix).