Depuração do programa Java para alterar o arquivo de configuração do fuso horário no Ubuntu

1

Aqui está um script ruby que escrevi para alterar a configuração do fuso horário no Ubuntu. Eu corro com jruby (um interpretador Ruby rodando em uma 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

Altera o arquivo de configuração corretamente. No entanto, a saída do script não é a esperada.

Suponha que o valor padrão do fuso horário seja America/Toronto . Quando eu executo o comando jruby change_timezone.rb Asia/Chongqing , a saída é:

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 com o comando jruby change_timezone.rb Europe/Amsterdam , acabo com o seguinte:

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!!!)

Indo mais longe com jruby change_timezone.rb Europe/Amsterdam , recebo o seguinte:

Europe/Amsterdam
Current Time:Thu Jul 07 21:21:27 +0200 2011
Europe/Amsterdam
Updated Time:Thu Jul 07 21:21:27 +0200 2011

Alguém pode descobrir por que não funcionou como esperado?

    
por Terry Li 07.07.2011 / 21:25

1 resposta

6

Este é um problema em como o Java determina o fuso horário em sistemas unix.

A especificação POSIX não especifica como determinar o fuso horário quando o ambiente TZ variável não está definida. Não consigo encontrar nada na Base do Linux sobre isso. A biblioteca do sistema básico (GNU libc) usa /etc/localtime para determinar o fuso horário. Portanto, no Linux não integrado, /etc/localtime é onde as informações de fuso horário são armazenadas e, idealmente, a história terminaria aqui.

(Olhando em volta: FreeBSD, NetBSD e OpenBSD usam /etc/localtime . O Solaris e alguns outros usam /etc/TIMEZONE . O Rosetta Stone for Unix mostra o que outros unices usam. Dietlibc (usado em alguns sistemas Linux embarcados) usa /etc/localtime , enquanto uClibc usa /etc/TZ (a menos que corrigido ).)

Infelizmente, o Java faz as coisas de maneira diferente. O Debian e o Ubuntu têm um arquivo chamado /etc/timezone , que contém o nome do fuso horário. Esse arquivo extra destina-se ao sistema de empacotamento, para que ele se lembre de um nome geográfico como Europe/Amsterdam em vez de apenas a descrição do fuso horário (compensações ao longo do tempo e nomes de exibição CET , CEST e CEDT ). Isso é mais amigável para os humanos e robusto caso o local geográfico atualize suas regras de fuso horário. Sun (agora Oracle) Java prefere /etc/timezone (ou /etc/sysconfig/clock em distribuições baseadas no Red Hat) veja o bug # 6456628 para /etc/localtime , e OpenJDK e gcj sigam o exemplo. p>

Veja também: Como encontro o fuso horário do sistema atual? ; O Java Time Zone está confuso .

A solução é simples: sempre atualize /etc/timezone e /etc/localtime juntos. No Debian ou Ubuntu, o método oficial para mudar o fuso horário é dpkg-reconfigure tzdata . Para alterar o fuso horário apenas para um aplicativo, defina a variável de ambiente TZ (isso é portátil em todos os sistemas unix).

    
por 08.07.2011 / 23:13