librelist archives

« back to archive

Unix time and the Ruby Time class

Unix time and the Ruby Time class

From:
Eric Wong
Date:
2011-09-24 @ 00:28
The Unix epoch is defined as January 1, 1970, 00:00:00 UTC (Coordinated
Universal Time[1]).  Unix systems return the time in seconds as a signed
integer relative to the Unix epoch.  Negative numbers are interpreted as
dates before the Unix epoch.

Using seconds (and fractions of a second) to represent time allows
application authors to rely on arithmetic rather than specialized
functions for calculating time intervals.

File systems expose timestamps for all files in Unix time with varying
degrees of accuracy and granularity.  The Ruby File and File::Stat
classes can support timestamps with sub-second granularity on some
systems.

Modern kernels do not know nor care about timezones.  Conversions from
UTC to the local timezone (and vice versa) are done in user space[2].
Different processes running concurrently on the same machine do not
necessarily share the same local timezone.

Ruby Time class
---------------

The Ruby Time class includes methods for reading the system time and
allows converting from an Integer (seconds since the epoch) to a Ruby
Time object.

Ruby Time objects have a timezone attached to them, but remember
this is a user space construct.

Time.now / gettimeofday(2) / clock_gettime(2)
---------------------------------------------

gettimeofday(2) is the commonly available system call for reading the
Unix time with (up to) microsecond resolution.  On some systems,
clock_gettime(2) may be used for nanosecond resolution[3].

Time.now will return the current time as a Time object taking into
account the timezone of the current process (in user space).  Ruby 1.9
may use clock_gettime(2) internally if available, but fall back to
gettimeofday(2) to retrieve the system time.

Time#tv_sec / Time#tv_usec / Time#tv_nsec
-----------------------------------------

These accessors allow access to the underlying values returned by
gettimeofday(2) or clock_gettime(2) as Integers.  For systems without
nanosecond resolution, Time#tv_nsec may just be the value of
Time#tv_usec multiplied by 1000.

Time.at - converts from Unix time to a Time object
--------------------------------------------------

If you have the number of seconds (and maybe microseconds) as integer
seconds since the Unix epoch, you can convert that into a Ruby Time
object using the Time.at class method:

	Time.at(seconds[, microseconds ])

This is is useful if you encounter a Unix timestamp anywhere but want to
have a Ruby Time object.  The local timezone is attached to the created
object.

There is no underlying syscall needed for this, this conversion can be
performed entirely in user space (although it may require memory
allocation).

Process timezone
----------------

The "TZ" environment variable controls the timezone for a given process,
and thus the timezone attached to a Ruby Time object.  If "TZ" is unset,
the timezone of the process is implementation-defined.

Time#utc
--------

If your process is not running under UTC, you may wish to convert
Time objects to UTC with this method.

Setting system time
-------------------

Ruby does not provide methods to change the system time.  Changing
system time typically requires administrator (root) privileges and few
applications (especially high-level ones) need to change the system
time.  For machines with network access, system time is commonly
synchronized via NTP and gradually adjusted via adjtime(3) and/or
non-portable syscalls.

Monotonic clocks
----------------

Some systems support a monotonic clock which is not adjustable (even by
the administrator).  A monotonic clock is useful for maintaining
consistent timing and scheduling across system time changes.

Ruby currently (as of 1.9.3) does not provide access to the monotonic
clock.  However, Ruby implementations may use the monotonic clock
internally for timing (via clock_gettime(2)) and recording time
differences.

Avoiding system calls
---------------------

You may notice the lack of gettimeofday(2) or clock_gettime(2) syscalls
if you're tracing syscalls.  This is because C libraries can work with
the kernel to optimize away the syscalls for gettimeofday(2) and
clock_gettime(2).  These implementations may trade accuracy for speed,
but may be disabled (by the administrator) if accuracy is more
important (than speed).


[1] - One should know UTC is not exactly the same as Greenwich Mean Time
      (GMT)

[2] - Timezone information is usually on (regular) files, so it may
      require syscalls to read those files.

[3] - You're not guaranteed this level of accuracy is supported
      by your kernel nor your hardware.  Consult your operating
      system and hardware documentation for more information.


License: GPLv3 (or later, at the discretion of Eric Wong)
         http://www.gnu.org/licenses/gpl-3.0.txt
-- 
Eric Wong

Re: [usp.ruby] Unix time and the Ruby Time class

From:
Sean O'Halpin
Date:
2011-09-25 @ 23:35
On Sat, Sep 24, 2011 at 1:28 AM, Eric Wong <normalperson@yhbt.net> wrote:
> Using seconds (and fractions of a second) to represent time allows
> application authors to rely on arithmetic rather than specialized
> functions for calculating time intervals.

Unfortunately, this isn't quite true - UTC is a civil time standard
based on atomic time which occasionally includes intercalary leap
seconds to keep it close to mean solar time (GMT as was, now UT1). See
http://en.wikipedia.org/wiki/Leap_second for the gory details.

They've been added every 18 months or so on average and are injected
simultaneously worldwide (unlike leap days).

There is an ongoing proposal to either abolish leap seconds or switch
to an 'absolute' time standard like TA1 (atomic clocks) or GPS.

tzdata accounts for leap seconds which is one of the reasons we need
to keep it up to date (along with timezones changing).

Regards,
Sean

Re: [usp.ruby] Unix time and the Ruby Time class

From:
Eric Wong
Date:
2011-09-26 @ 01:33
Sean O'Halpin <sean.ohalpin@gmail.com> wrote:
> On Sat, Sep 24, 2011 at 1:28 AM, Eric Wong <normalperson@yhbt.net> wrote:
> > Using seconds (and fractions of a second) to represent time allows
> > application authors to rely on arithmetic rather than specialized
> > functions for calculating time intervals.
> 
> Unfortunately, this isn't quite true - UTC is a civil time standard
> based on atomic time which occasionally includes intercalary leap
> seconds to keep it close to mean solar time (GMT as was, now UT1). See
> http://en.wikipedia.org/wiki/Leap_second for the gory details.

Good points, time is complicated.  All the more reason for OSes and
runtimes like Ruby to support monotonic clocks.

Re: [usp.ruby] Unix time and the Ruby Time class

From:
Devin Ben-Hur
Date:
2011-09-27 @ 18:07
On 9/23/11 5:28 PM, Eric Wong wrote:
> Some systems support a monotonic clock which is not adjustable (even by
> the administrator).  A monotonic clock is useful for maintaining
> consistent timing and scheduling across system time changes.
>
> Ruby currently (as of 1.9.3) does not provide access to the monotonic
> clock.

Brian Buchanan recently published a gem AbsoluteTime to provide 
monotonic time at https://github.com/bwbuchanan/absolute_time
Currently supports Darwin, FreeBSD, and Linux.