Difference between revisions of "Linux datetime"
(7 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
[[Category:Engineering]] | [[Category:Engineering]] | ||
+ | [[Category:Time]] | ||
This article covers date and time issues on Linux including epoch time, timezones, hardware and system clock sync, ntpdate, and [http://en.wikipedia.org/wiki/Network_Time_Protocol NTP]. | This article covers date and time issues on Linux including epoch time, timezones, hardware and system clock sync, ntpdate, and [http://en.wikipedia.org/wiki/Network_Time_Protocol NTP]. | ||
Line 38: | Line 39: | ||
$ echo $EPOCH | awk '{print strftime("%F %T %z",$1)}' | $ echo $EPOCH | awk '{print strftime("%F %T %z",$1)}' | ||
2010-02-12 19:57:17 -0800 | 2010-02-12 19:57:17 -0800 | ||
+ | </pre> | ||
+ | |||
+ | You can use a Python one-liner to handle epoch times. | ||
+ | <pre> | ||
+ | $ python -c "import time; print time.time()" | ||
+ | 1396490714.62 | ||
+ | $ python -c "import time, sys; print time.strftime('%Y-%m-%dT%H:%M:%S',time.localtime(float(sys.argv[1])))" 1396494023 | ||
+ | 2014-04-02T20:00:23 | ||
</pre> | </pre> | ||
Line 47: | Line 56: | ||
$ date +"%F %T %z" -r $EPOCH | $ date +"%F %T %z" -r $EPOCH | ||
2010-02-12 19:57:17 -0800 | 2010-02-12 19:57:17 -0800 | ||
+ | </pre> | ||
+ | |||
+ | This has been tested on Mac OS X and Linux. It may not work on very old versions of OS X. | ||
+ | <pre> | ||
+ | # Pass an epoch time and this will return the date in human readable format. | ||
+ | # This works on Linux and OS X. | ||
+ | epoch_to_rfc_3339 () | ||
+ | { | ||
+ | EPOCH=$(echo $@ | sed -n "s/.*\([0-9]\{10\}\).*/\1/p"); | ||
+ | if ! date "+%FT%T:::%z" -d "1970-01-01 UTC ${EPOCH} seconds" 2>/dev/null; then | ||
+ | date -r ${EPOCH} "+%FT%T:::%z" | ||
+ | fi | ||
+ | } | ||
</pre> | </pre> | ||
Line 79: | Line 101: | ||
# date -d "-14 days -4 hours -27 minutes" | # date -d "-14 days -4 hours -27 minutes" | ||
Fri May 14 09:11:19 PDT 2010 | Fri May 14 09:11:19 PDT 2010 | ||
+ | </pre> | ||
+ | |||
+ | === Bash function to return formatted date in days past for both GNU Linux and MacOS OSX === | ||
+ | |||
+ | Pass the number of days in the past for which you want the date. If you pass nothing it will assume 0 days. | ||
+ | <pre> | ||
+ | date_days_past () { days_past=${1:-0}; if ! date -v-${days_past}d +%Y%m%d 2>/dev/null; then date --date="-${days_past} day" +%Y%m%d; fi } | ||
</pre> | </pre> | ||
Line 117: | Line 146: | ||
;Pacific time:http://www.time.gov/timezone.cgi?Pacific/d/-8 | ;Pacific time:http://www.time.gov/timezone.cgi?Pacific/d/-8 | ||
+ | |||
+ | == ntp.org == | ||
+ | |||
+ | pool.ntp.org | ||
+ | |||
+ | Query: | ||
+ | <pre> | ||
+ | ntpdate -q -b pool.ntp.org | ||
+ | </pre> | ||
+ | |||
+ | Query and set local System Clock: | ||
+ | <pre> | ||
+ | ntpdate -b pool.ntp.org | ||
+ | </pre> | ||
+ | |||
+ | == hwclock == | ||
+ | |||
+ | Something was corrupting the registers in an I2C RTC clock chip I was using. I was getting this error after the chip registers were corrupt: | ||
+ | <pre> | ||
+ | # hwclock | ||
+ | The Hardware Clock registers contain values that are either invalid (e.g. 50th day of month) or beyond the range we can handle (e.g. Year 2095). | ||
+ | </pre> | ||
+ | |||
+ | I ran `strace` with '''-e raw=ioctl''' option because I needed the ioctl constant for '''RTC_RD_TIME''', 0x40247009. | ||
+ | |||
+ | <pre> | ||
+ | # strace hwclock | ||
+ | ... | ||
+ | open("/dev/rtc", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory) | ||
+ | open("/dev/rtc0", O_RDONLY|O_LARGEFILE) = 3 | ||
+ | stat64(0x1000850c, 0xbfb87c60) = -1 ENOENT (No such file or directory) | ||
+ | ioctl(3, RTC_UIE_ON, 0) = -1 ENOTTY (Inappropriate ioctl for device) | ||
+ | ioctl(3, RTC_RD_TIME, {tm_sec=7, tm_min=41, tm_hour=27, tm_mday=29, tm_mon=10, tm_year=265, ...}) = 0 | ||
+ | ioctl(3, RTC_RD_TIME, {tm_sec=7, tm_min=41, tm_hour=27, tm_mday=29, tm_mon=10, tm_year=265, ...}) = 0 | ||
+ | ... | ||
+ | ioctl(3, RTC_RD_TIME, {tm_sec=7, tm_min=41, tm_hour=27, tm_mday=29, tm_mon=10, tm_year=265, ...}) = 0 | ||
+ | ioctl(3, RTC_RD_TIME, {tm_sec=8, tm_min=41, tm_hour=27, tm_mday=29, tm_mon=10, tm_year=265, ...}) = 0 | ||
+ | ioctl(3, RTC_RD_TIME, {tm_sec=8, tm_min=41, tm_hour=27, tm_mday=29, tm_mon=10, tm_year=265, ...}) = 0 | ||
+ | open("/etc/localtime", O_RDONLY) = 4 | ||
+ | fstat64(0x4, 0xbfb87980) = 0 | ||
+ | ... | ||
+ | # strace -e raw=ioctl hwclock | ||
+ | ... | ||
+ | open("/dev/rtc", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory) | ||
+ | open("/dev/rtc0", O_RDONLY|O_LARGEFILE) = 3 | ||
+ | stat64(0x1000850c, 0xbfe5cc60) = -1 ENOENT (No such file or directory) | ||
+ | ioctl(0x3, 0x20007003, 0) = -1 (errno 25) | ||
+ | ioctl(0x3, 0x40247009, 0xbfe5c988) = 0 | ||
+ | ioctl(0x3, 0x40247009, 0xbfe5c9b4) = 0 | ||
+ | ... | ||
+ | ioctl(0x3, 0x40247009, 0xbfe5c9b4) = 0 | ||
+ | ioctl(0x3, 0x40247009, 0xbfe5cb10) = 0 | ||
+ | ioctl(0x3, 0x40247009, 0xbfe5cb10) = 0 | ||
+ | open("/etc/localtime", O_RDONLY) = 4 | ||
+ | fstat64(0x4, 0xbfe5c980) = 0 | ||
+ | ... | ||
+ | </pre> | ||
+ | |||
+ | <pre> | ||
+ | # cat /etc/adjtime | ||
+ | -1.865802 1277906845 0.000000 | ||
+ | 1277906845 | ||
+ | UTC | ||
+ | </pre> | ||
== Time Sync radio broadcasts == | == Time Sync radio broadcasts == | ||
− | |||
Most consumer "atomic" clocks use WWVB for radio sync. Time signals can also be received through GPS receivers which pickup the time signals broadcast by GPS satellites. Each GPS satellite carries its own atomic clock. | Most consumer "atomic" clocks use WWVB for radio sync. Time signals can also be received through GPS receivers which pickup the time signals broadcast by GPS satellites. Each GPS satellite carries its own atomic clock. |
Revision as of 14:37, 16 May 2016
This article covers date and time issues on Linux including epoch time, timezones, hardware and system clock sync, ntpdate, and NTP.
Contents
Epoch time
UNIX Epoch Time is the number of seconds since 00:00:00 1970-01-01 UTC. This is useful for datetime stamps or generating unique names.
The epoch time can be retrieved using the `date` command:
$ date "+%s" 1266033437
Unfortunately, it is not trivial to convert epoch times to a human-readable format in a portable way. The following will work on most Linux systems and is probably the most portable:
$ EPOCH=`date "+%s"` $ echo $EPOCH 1266033437 $ date +"%F %T %z" -d "1970-01-01 UTC + $EPOCH seconds" 2010-02-12 19:57:17 -0800
The `date` command in versions of GNU coreutils since 5.3.0 support the @ feature:
$ EPOCH=`date "+%s"` $ echo $EPOCH 1266033437 $ date +"%F %T %z" -d @$EPOCH 2010-02-12 19:57:17 -0800
If you have GNU Awk installed then you can use the following command (Ubuntu/Debian systems do not have the 'gawk' package installed by default):
$ EPOCH=`date "+%s"` $ echo $EPOCH 1266033437 $ echo $EPOCH | awk '{print strftime("%F %T %z",$1)}' 2010-02-12 19:57:17 -0800
You can use a Python one-liner to handle epoch times.
$ python -c "import time; print time.time()" 1396490714.62 $ python -c "import time, sys; print time.strftime('%Y-%m-%dT%H:%M:%S',time.localtime(float(sys.argv[1])))" 1396494023 2014-04-02T20:00:23
Supposedly, the following will work on BSD systems; unfortunately, not Mac OS X. And it is not portable with the GNU `date` command.
$ EPOCH=`date "+%s"` $ echo $EPOCH 1266033437 $ date +"%F %T %z" -r $EPOCH 2010-02-12 19:57:17 -0800
This has been tested on Mac OS X and Linux. It may not work on very old versions of OS X.
# Pass an epoch time and this will return the date in human readable format. # This works on Linux and OS X. epoch_to_rfc_3339 () { EPOCH=$(echo $@ | sed -n "s/.*\([0-9]\{10\}\).*/\1/p"); if ! date "+%FT%T:::%z" -d "1970-01-01 UTC ${EPOCH} seconds" 2>/dev/null; then date -r ${EPOCH} "+%FT%T:::%z" fi }
date calculations with the Linux `date` command
The 'seconds' keyword may be written as 'seconds', 'second', 'secs', and 'sec'.
The `date` command can format a not just the current date, but any given date with the '-d' option. You can also express calendrical calculations from a given date or from the now time.
# date; date -d "- 1 week" Fri May 28 13:43:36 PDT 2010 Fri May 21 13:43:36 PDT 2010
On Linux, the file '/proc/uptime' will give you the number of seconds the system has been running. From there you can use `date` to figure out what date the system booted. Of course, you can get the boot time using `who -b` or `last -x`, but that doesn't teach us anything.
date +"%F %T %z" -d "now UTC - $(cat /proc/uptime | cut -f 1 -d ' ' ) seconds" 2010-05-14 09:31:05 -0700
Current time minus a number of seconds
If you run `cat /proc/uptime`
# uptime 13:35:57 up 14 days, 4:27, 4 users, load average: 0.00, 0.01, 0.04
So, what date was 14 days, 4 hours, and 27 minutes ago?
# date -d "-14 days -4 hours -27 minutes" Fri May 14 09:11:19 PDT 2010
Bash function to return formatted date in days past for both GNU Linux and MacOS OSX
Pass the number of days in the past for which you want the date. If you pass nothing it will assume 0 days.
date_days_past () { days_past=${1:-0}; if ! date -v-${days_past}d +%Y%m%d 2>/dev/null; then date --date="-${days_past} day" +%Y%m%d; fi }
Set timezone and clock on Linux
1. su to root
2. Find your timezone file under /usr/share/zoneinfo. For example:
/usr/share/zoneinfo/US/Pacific
3. OPTIONAL: backup the current timezone configuration:
cp /etc/localtime /etc/localtime.old
4. Create a symbolic link from the appropiate timezone to /etc/localtime.
ln -sf /usr/share/zoneinfo/US/Pacific /etc/localtime
or
ln -sf /usr/share/zoneinfo/America/Los_Angeles /etc/localtime
5. Use rdate or ntpdate to set the system time (ntpdate is better):
/usr/sbin/ntpdate time.nist.gov
or
/usr/bin/rdate time.nist.gov
6. Set the hardware clock to the system time:
/sbin/hwclock --systohc
Correct for clock drift
For where its not possible to run ntpd you may use adjtimex to correct for systematic drift.
aptitude install adjtimex
NIST
time.nist.gov
- Pacific time
- http://www.time.gov/timezone.cgi?Pacific/d/-8
ntp.org
pool.ntp.org
Query:
ntpdate -q -b pool.ntp.org
Query and set local System Clock:
ntpdate -b pool.ntp.org
hwclock
Something was corrupting the registers in an I2C RTC clock chip I was using. I was getting this error after the chip registers were corrupt:
# hwclock The Hardware Clock registers contain values that are either invalid (e.g. 50th day of month) or beyond the range we can handle (e.g. Year 2095).
I ran `strace` with -e raw=ioctl option because I needed the ioctl constant for RTC_RD_TIME, 0x40247009.
# strace hwclock ... open("/dev/rtc", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory) open("/dev/rtc0", O_RDONLY|O_LARGEFILE) = 3 stat64(0x1000850c, 0xbfb87c60) = -1 ENOENT (No such file or directory) ioctl(3, RTC_UIE_ON, 0) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(3, RTC_RD_TIME, {tm_sec=7, tm_min=41, tm_hour=27, tm_mday=29, tm_mon=10, tm_year=265, ...}) = 0 ioctl(3, RTC_RD_TIME, {tm_sec=7, tm_min=41, tm_hour=27, tm_mday=29, tm_mon=10, tm_year=265, ...}) = 0 ... ioctl(3, RTC_RD_TIME, {tm_sec=7, tm_min=41, tm_hour=27, tm_mday=29, tm_mon=10, tm_year=265, ...}) = 0 ioctl(3, RTC_RD_TIME, {tm_sec=8, tm_min=41, tm_hour=27, tm_mday=29, tm_mon=10, tm_year=265, ...}) = 0 ioctl(3, RTC_RD_TIME, {tm_sec=8, tm_min=41, tm_hour=27, tm_mday=29, tm_mon=10, tm_year=265, ...}) = 0 open("/etc/localtime", O_RDONLY) = 4 fstat64(0x4, 0xbfb87980) = 0 ... # strace -e raw=ioctl hwclock ... open("/dev/rtc", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory) open("/dev/rtc0", O_RDONLY|O_LARGEFILE) = 3 stat64(0x1000850c, 0xbfe5cc60) = -1 ENOENT (No such file or directory) ioctl(0x3, 0x20007003, 0) = -1 (errno 25) ioctl(0x3, 0x40247009, 0xbfe5c988) = 0 ioctl(0x3, 0x40247009, 0xbfe5c9b4) = 0 ... ioctl(0x3, 0x40247009, 0xbfe5c9b4) = 0 ioctl(0x3, 0x40247009, 0xbfe5cb10) = 0 ioctl(0x3, 0x40247009, 0xbfe5cb10) = 0 open("/etc/localtime", O_RDONLY) = 4 fstat64(0x4, 0xbfe5c980) = 0 ...
# cat /etc/adjtime -1.865802 1277906845 0.000000 1277906845 UTC
Time Sync radio broadcasts
Most consumer "atomic" clocks use WWVB for radio sync. Time signals can also be received through GPS receivers which pickup the time signals broadcast by GPS satellites. Each GPS satellite carries its own atomic clock.
WWVB radio broadcasts of UTC time.
- WWVB, Fort Collins, CO
- 60 kHz (binary carrier signal)
- WWV, Fort Collins, CO
- 2500, 5000, 10000 and 15000 kHz (broadcasts voice)
- WWVH, Kauai, HI
- 2500, 5000, 10000 and 15000 kHz (broadcasts voice)
- CHU, Ottawa, Ontario, Canada
- 3330, 7335 and 14670 kHz (broadcasts voice)
UTC
UTC(GMT) | EDT | EST / CDT | CST / MDT | MST / PDT | PST |
0000 | 8 PM | 7 PM | 6 PM | 5 PM | 4 PM |
0100 | 9 PM | 8 PM | 7 PM | 6 PM | 5 PM |
0200 | 10 PM | 9 PM | 8 PM | 7 PM | 6 PM |
0300 | 11 PM | 10 PM | 9 PM | 8 PM | 7 PM |
0400 | MIDNIGHT | 11 PM | 10 PM | 9 PM | 8 PM |
0500 | 1 AM | MIDNIGHT | 11 PM | 10 PM | 9 PM |
0600 | 2 AM | 1 AM | MIDNIGHT | 11 PM | 10 PM |
0700 | 3 AM | 2 AM | 1 AM | MIDNIGHT | 11 PM |
0800 | 4 AM | 3 AM | 2 AM | 1 AM | MIDNIGHT |
0900 | 5 AM | 4 AM | 3 AM | 2 AM | 1 AM |
1000 | 6 AM | 5 AM | 4 AM | 3 AM | 2 AM |
1100 | 7 AM | 6 AM | 5 AM | 4 AM | 3 AM |
1200 | 8 AM | 7 AM | 6 AM | 5 AM | 4 AM |
1300 | 9 AM | 8 AM | 7 AM | 6 AM | 5 AM |
1400 | 10 AM | 9 AM | 8 AM | 7 AM | 6 AM |
1500 | 11 AM | 10 AM | 9 AM | 8 AM | 7 AM |
1600 | NOON | 11 AM | 10 AM | 9 AM | 8 AM |
1700 | 1 PM | NOON | 11 AM | 10 AM | 9 AM |
1800 | 2 PM | 1 PM | NOON | 11 AM | 10 AM |
1900 | 3 PM | 2 PM | 1 PM | NOON | 11 AM |
2000 | 4 PM | 3 PM | 2 PM | 1 PM | NOON |
2100 | 5 PM | 4 PM | 3 PM | 2 PM | 1 PM |
2200 | 6 PM | 5 PM | 4 PM | 3 PM | 2 PM |
2300 | 7 PM | 6 PM | 5 PM | 4 PM | 3 PM |