Re: time zone and UTC issue
"J. B" <bakshi12@gmail.com> writes:
> My box is configured to the local time zone from beginning, both
> hwclock and system time. But linux always favor hwclock to
> UTC. What is the advantage of doing that ?
Although time, timezones and clock setting are quite a simple topic it
seems to be major source of confusion for many people and many systems
are mis-configured, as can seen in this thread and as can be often
seen in E-mail time stamps.
I jumped into this thread somewhat late and wanted to write a couple
of sentences, but now this has become a little bit longer than
intended.
First, to reduce confusion, it is helpful to use good terminology and
to know what the meaning of used terms is.
1. Local time and UTC.
I strongly dislike the term "local time". There is no such thing
as a local time or different local times in different locations (on
earth). There is only one global time. What differs locally is
only the /represantation/ of the time. Nevertheless, I also
sometimes use "local time" to mean "local time representation".
Also, UTC is only /one/ possible representation for times. It is
special in that is "universal", i.e. it is used independent of
location and doesn't have weird things like daylight saving times.
Both, UTC and local time representation, express time as year,
month, day, hour, minute, second, and (hopefully) timezone
indicator.
2. System clock and system time.
The system clock is a software clock driven by the Linux kernel and
it defines the system time. The system clock uses yet another time
representation. Although seemingly everybody states that Linux and
Unix systems run their system clock in UTC, this is IMO not quite
correct. The system time, time stamps in Unix file systems, and
time stamps exchanged between the Linux kernel and user space
programs are representated as a POSIX time_t (or struct timeval or
struct timespec). This representation is only an integer number
counting the seconds since the POSIX epoch (ignoring leap seconds).
The timeval and timespec representation additionally give the
microseconds and nanoseconds, respectively. The POSIX epoch is a
fixed point in time, usually given in UTC time representation and
it is January 1, 1970 0:00:00 UTC. The representation as a simple
integer has several advantages:
* It's very simple to advance the clock by one second. No need to
carry to the next unit after 60 seconds, 60 minutes, 24 hours,
and so on.
* It's very simple to calculate the difference between two times.
* It's independent of local time representation and daylight saving
rules. It doesn't jump forth and back.
When people say "The Linux kernel system time is always in UTC",
what the really mean is that the kernel keeps a time representation
that doesn't depend on any local timezone definitions, doesn't jump
for daylight saving times and is based on a certain point in time
(the epoch) which is usually expressed in UTC (although you could
equally well define the epoch as "December 31, 1969 19:00:00
Eastern Standard Time" because that is the /same/ time as
1970-01-01 0:00:00 UTC).
You can get the current kernel system time with the gettimeofday(2)
or clock_gettime(2) system calls, or print it like this
$ date +%s
1354558752
$ perl -e 'print time,"\n"'
1354558754
I think it's important to understand that you don't set the system
clock to one time or another, you don't set it to "local time" nor
to UTC. You set it to "the current time" (or have it synchronized
to "the current time" using NTP), since there is only one global
time. The representation used by the system clock is POSIX struct
timespec and nothing else.
3. Hardware clock (aka. CMOS clock, BIOS clock or real time clock (RTC)).
This is a clock that ticks independently from any operating system
and even keeps running when the computer is turned off. This clock
represents its time as year-month-day-weekday-hour-minute-second so
it can be set to any local time representation or to UTC.
Unfortunately, it doesn't have information which representation it
is set to nor if it currently is set to daylight saving time or
not. Without this information, you have to guess the meaning of
the time you read from the hardware clock. Therefore, it's best
best to use UTC for this clock since that never has be adjusted for
daylight saving time. Otherwise, in multi-boot system each OS may
adjust thue RTC by one hour resulting in wrong RTC time.
This clock is normally not used in your Linux system, except when
booting the system. Early in the boot process the time is read
from the hardware clock, its time representation is
interpreted/guess (hopefully correct), the POSIX time_t calculated
and the system time set from this. After that, you can read and
set the hardware clock using hwclock(8), but it's not used for
other purposes.
Having the kernel system time represented as a POSIX time_t doesn't
mean the user has to deal with such time representations or with UTC
time representation. There are library routines that, given a local
timezone description, can convert from your selected local time
representation to POSIX time_t and vice versa (localtime(3) and
mktime(3)). In fact, there's not only one such local timezone
description, but there are many and each user[1] can choose which one
to use. The default timezone is specified in /etc/localtime but you
can specify any other timezone using the TZ environment variable (my
default timezone is Europe/Berlin):
$ date
Mon Dec 3 19:19:20 CET 2012
$ TZ=UTC date
Mon Dec 3 18:19:23 UTC 2012
$ TZ=America/Los_Angeles date
Mon Dec 3 10:19:28 PST 2012
$ TZ=America/Detroit date
Mon Dec 3 13:19:32 EST 2012
$ TZ=Asia/Tokyo date
Tue Dec 4 03:19:36 JST 2012
You can also print the date for any time other than the current time
using date's -d option:
$ # The POSIX epoch, expressed in Europe/Berlin timezone
$ date -d@0
Thu Jan 1 01:00:00 CET 1970
$ # One hour later
$ date -d@3600
Thu Jan 1 02:00:00 CET 1970
$ # The epoch expressed in UTC and Los Angeles time
$ TZ=UTC date -d@0
Thu Jan 1 00:00:00 UTC 1970
$ TZ=America/Los_Angeles date -d@0
Wed Dec 31 16:00:00 PST 1969
Using GNU date you can also easily convert any time representation
into a POSIX time_t, i.e. the kernels time representation for that
time:
$ date -d"1967-01-31 17:27" +%s
-92043180
$ TZ=UTC date -d"1967-01-31 16:27" +%s
-92043180
$ # The time that many people celebrated as the begin of a new millenium
$ TZ=America/New_York date -d"2000-01-01 0:00:00" +%s
946702800
Almost all other tools that deal with times, also respect the default
timezone and the TZ environment variable:
$ cd /tmp
$ date; touch foo
Mon Dec 3 19:21:09 CET 2012
$ ls -l --time-style=full-iso foo
-rw-r--r-- 1 urs urs 0 2012-12-03 19:21:09.973761852 +0100 foo
$ TZ=UTC ls -l --time-style=full-iso foo
-rw-r--r-- 1 urs urs 0 2012-12-03 18:21:09.973761852 +0000 foo
$ TZ=America/New_York ls -l --time-style=full-iso foo
-rw-r--r-- 1 urs urs 0 2012-12-03 13:21:09.973761852 -0500 foo
$ TZ=Australia/Sydney find foo -printf "%TF %TT %Tz %p\n"
2012-12-04 05:21:09.9737618520 +1100 foo
$ tar cf bar.tar foo
$ tar tvf bar.tar
-rw-r--r-- urs/urs 0 2012-12-03 19:21 foo
$ TZ=Asia/Shanghai tar tvf bar.tar
-rw-r--r-- urs/urs 0 2012-12-04 02:21 foo
$ # Look at the time displayed in the emacs mode line
$ TZ=Asia/Tokyo emacs --eval "(display-time)"
$ TZ=UTC xclock
And of course, you don't need to specify the timezone to use in every
command, but simply set the TZ environment variable for all subsequent
commands (e.g. in your ~/.profile):
$ export TZ=Europe/Berlin
Or set the default timezone for the system using dpkg or zic -l so
that you don't need to set the TZ environment variable.
[1] To be more precise: The environment variable is not set for each
user, you can even give a different value to each process. That
means you can have several terminal windows and/or X11 clocks
and/or whatever-you-like show different times:
$ TZ=Asia/Tokyo xterm &
$ TZ=Asia/Tokyo xclock -title Tokyo &
$ TZ=Europe/Berlin xterm &
$ TZ=Europe/Berlin xclock -title Berlin &
$ TZ=US/Pacific xclock -title "San Francisco" &
Hint: Have a look at /usr/share/zoneinfo to get an idea which timezone
descriptions are available. To see what a timezone description
contains run from your command-line shell
$ zdump -v America/New_York
German readers might want to read
http://www.ibr.cs.tu-bs.de/users/thuerman/time
where I give some more background info on time. It's > 10 years old,
some links are out-of-date and it's still not complete :-)
urs
Reply to: