Voici un script ruby que j'ai écrit pour changer la configuration du fuseau horaire sur Ubuntu. Je le lance avec jruby (un interpréteur Ruby s'exécutant dans une 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
Il modifie correctement le fichier de configuration. Cependant, la sortie du script n'est pas celle attendue.
Supposons que la valeur par défaut du fuseau horaire est America/Toronto
.
Lorsque je lance la commande jruby change_timezone.rb Asia/Chongqing
, la sortie est :
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!!!)
Poursuivre avec la commande jruby change_timezone.rb Europe/Amsterdam
, je me retrouve avec ce qui suit :
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!!!)
Aller plus loin avec jruby change_timezone.rb Europe/Amsterdam
encore une fois, j'obtiens ce qui suit :
Europe/Amsterdam
Current Time:Thu Jul 07 21:21:27 +0200 2011
Europe/Amsterdam
Updated Time:Thu Jul 07 21:21:27 +0200 2011
Quelqu'un peut-il comprendre pourquoi cela n'a pas fonctionné comme prévu ?
Réponse acceptée :
Il s'agit d'un problème dans la façon dont Java détermine le fuseau horaire sous les systèmes Unix.
La spécification POSIX ne précise pas comment déterminer le fuseau horaire lorsque le TZ
la variable d'environnement n'est pas définie. Je ne trouve rien dans la base standard Linux à ce sujet.
La bibliothèque système de base (GNU libc) utilise /etc/localtime
pour déterminer le fuseau horaire. Donc sur Linux non embarqué, /etc/localtime
est l'endroit où les informations de fuseau horaire sont stockées, et idéalement l'histoire se terminerait ici.
(En regardant autour de vous :FreeBSD, NetBSD et OpenBSD utilisent /etc/localtime
. Solaris et quelques autres utilisent /etc/TIMEZONE
. La pierre de Rosette pour Unix montre ce que les autres unix utilisent. Dietlibc (utilisé dans certains systèmes Linux embarqués) utilise /etc/localtime
, tandis que uClibc utilise /etc/TZ
(sauf si patché).)
Malheureusement, Java fait les choses différemment. Debian et Ubuntu ont un fichier appelé /etc/timezone
qui contient le nom du fuseau horaire. Ce fichier supplémentaire est destiné au système d'emballage, afin qu'il mémorise un nom géographique comme Europe/Amsterdam
plutôt que la simple description du fuseau horaire (décalages dans le temps et noms d'affichage CET
, CEST
et CEDT
). Ceci est à la fois plus convivial pour les humains et robuste au cas où les paramètres régionaux mettraient à jour leurs règles de fuseau horaire. Sun (maintenant Oracle) Java préfère /etc/timezone
(ou /etc/sysconfig/clock
sur les distributions basées sur Red Hat) voir le bogue #6456628 dans /etc/localtime
, et OpenJDK et gcj emboîtent le pas.
La solution est simple :mettez toujours à jour /etc/timezone
et /etc/localtime
ensemble. Sur Debian ou Ubuntu, la méthode officielle pour changer le fuseau horaire est dpkg-reconfigure tzdata
. Pour modifier le fuseau horaire d'une seule application, définissez le TZ
variable d'environnement (portable sur tous les systèmes Unix).