Aquí hay un script de Ruby que escribí para cambiar la configuración de la zona horaria en Ubuntu. Lo ejecuto con jruby (un intérprete de Ruby que se ejecuta en 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 el archivo de configuración correctamente. Sin embargo, el resultado del script no es el esperado.
Suponga que el valor predeterminado para la zona horaria es America/Toronto
.
Cuando ejecuto el comando jruby change_timezone.rb Asia/Chongqing
, la salida es:
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 el comando jruby change_timezone.rb Europe/Amsterdam
, termino con lo siguiente:
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!!!)
Yendo más allá con jruby change_timezone.rb Europe/Amsterdam
de nuevo, obtengo lo siguiente:
Europe/Amsterdam
Current Time:Thu Jul 07 21:21:27 +0200 2011
Europe/Amsterdam
Updated Time:Thu Jul 07 21:21:27 +0200 2011
¿Alguien puede averiguar por qué no funcionó como se esperaba?
Respuesta aceptada:
Este es un problema de cómo Java determina la zona horaria en los sistemas Unix.
La especificación POSIX no especifica cómo determinar la zona horaria cuando el TZ
la variable de entorno no está configurada. No puedo encontrar nada en la base estándar de Linux sobre esto.
La biblioteca del sistema base (GNU libc) usa /etc/localtime
para determinar la zona horaria. Entonces, en Linux no integrado, /etc/localtime
es donde se almacena la información de la zona horaria, e idealmente la historia terminaría aquí.
(Mirando alrededor:FreeBSD, NetBSD y OpenBSD usan /etc/localtime
. Solaris y algunos otros usan /etc/TIMEZONE
. Rosetta Stone para Unix muestra lo que usan otros unices. Dietlibc (usado en algunos sistemas Linux incorporados) usa /etc/localtime
, mientras que uClibc usa /etc/TZ
(a menos que esté parcheado).)
Desafortunadamente, Java hace las cosas de manera diferente. Debian y Ubuntu tienen un archivo llamado /etc/timezone
que contiene el nombre de la zona horaria. Este archivo adicional está destinado al sistema de empaquetado, para que recuerde un nombre geográfico como Europe/Amsterdam
en lugar de solo la descripción de la zona horaria (compensaciones en el tiempo y nombres para mostrar CET
, CEST
y CEDT
). Esto es más amigable para los humanos y sólido en caso de que la ubicación geográfica actualice sus reglas de zona horaria. Sun (ahora Oracle) Java prefiere /etc/timezone
(o /etc/sysconfig/clock
en distribuciones basadas en Red Hat) consulte el error n.º 6456628 en /etc/localtime
y OpenJDK y gcj hacen lo mismo.
La solución es simple:actualice siempre /etc/timezone
y /etc/localtime
juntos. En Debian o Ubuntu, el método oficial para cambiar la zona horaria es dpkg-reconfigure tzdata
. Para cambiar la zona horaria solo para una aplicación, configure el TZ
variable de entorno (esto es portátil en todos los sistemas Unix).