[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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:

AltStyle によって変換されたページ (->オリジナル) /