Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Here is a ruby script I wrote to change the timezone configuration on Ubuntu. I run it with jruby (a Ruby interpreter running in a 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

It does change the configuration file properly. However, the output for the script is not as expected.

Assume the default value for the timezone is America/Toronto. When I run the command jruby change_timezone.rb Asia/Chongqing, the output is:

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

Continuing with the command jruby change_timezone.rb Europe/Amsterdam, I end up with the following:

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

Going further with jruby change_timezone.rb Europe/Amsterdam again, I get the following:

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

Can someone figure out why it didn't work as expected?

share|improve this question
    
Just a note: why are you using relative paths? –  pbm Jul 7 '11 at 20:02
    
@pbm Good point. Absolute paths can make code more portable. Thanks a lot! –  Terry Li Jul 7 '11 at 20:21
    
@Gilles As you can see from the output, the time did change while I didn't touch /etc/localtime. What confuses me here is that the time change wouldn't show upon the first run(it showed on the following run!!). –  Terry Li Jul 7 '11 at 20:27
    
@TerryLee The process reads the timezone the first time it needs it, and doesn't check for changes afterwards. What surprises me is that you're seeing a change without modifying /etc/localtime. Do you see the same effect with plain ruby? Please post the output of ls -l /etc/localtime and strace -efile jruby change_timezone.rb Asia/Chongqing. –  Gilles Jul 7 '11 at 20:57
    
@Gilles It seems that /etc/localtime won't change between runs. Plus, with plain Ruby I'm not able to see the change. I figure that Time.now results in different objects(java Time vs ruby Time) with jruby vs plain ruby. –  Terry Li Jul 8 '11 at 13:40

1 Answer 1

up vote 0 down vote accepted

This is an issue in how Java determines the time zone under unix systems.

The POSIX specification does not specify how to determine the timezone when the TZ environment variable is not set. I can't find anything in the Linux Standard Base about this. The base system library (GNU libc) uses /etc/localtime to determine the timezone. So on non-embedded Linux, /etc/localtime is where the timezone information is stored, and ideally the story would end here.

(Looking around: FreeBSD, NetBSD and OpenBSD use /etc/localtime. Solaris and a few others use /etc/TIMEZONE. The Rosetta Stone for Unix shows what other unices use. Dietlibc (used in some embedded Linux systems) uses /etc/localtime, while uClibc uses /etc/TZ (unless patched).)

Unfortunately, Java does things differently. Debian and Ubuntu have a file called /etc/timezone which contains the name of the timezone. This extra file is intended for the packaging system, so that it remembers a geographical name like Europe/Amsterdam rather than just the description of the timezone (offsets over time, and display names CET, CEST and CEDT). This is both friendlier to humans and robust in case the geographical locale updates its time zone rules. Sun (now Oracle) Java prefers /etc/timezone (or /etc/sysconfig/clock on Red Hat-based distributions) see bug #6456628 to /etc/localtime, and OpenJDK and gcj follow suit.

See also: How do I find the current system timezone?; Java Time Zone is messed up.

The solution is simple: always update /etc/timezone and /etc/localtime together. On Debian or Ubuntu, the official method to change the timezone is dpkg-reconfigure tzdata. To change the timezone only for one application, set the TZ environment variable (this is portable across all unix systems).

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.