Clone wiki

psi / TimeAPI

Time API

Note: This is supported from 0.3b2 and up.

As PSI gets many times from the system and needs to be able to offer these in a convenient form for Python developers we ended up making our own type to represent time. However it contains convenience functions to convert to most types of interest.

Internally PSI uses the POSIX struct timespec to store any times. It is the most accurate time structure available in POSIX and can represent both absolute time as well relative time. This is not the most versatile time representation possible, but is perfectly adequate for the time ranges and durations a kernel will expose. Often, time information is even exposed as this structure (or the slightly older and less accurate ``struct timeval`` equivalent).

Important to note is the the timespec structure does not contain any timezone information. If used as absolute time it is measured as seconds since the epoch, since the epoch is defined as 1 January 1970 Coordinated Universal Time (UTC) this means all times are in UTC and not local time.


The TimeSpec class is used by PSI to represent any times, whether absolute time or duration. It is essentially a tuple representing the two values of the timespec structure as Python long values: (tv_sec, tv_nsec), these two values are also available as the tv_sec and tv_nsec attributes. Tuple-like access to the attributes is limited to the index 0 and 1, negative indices are not supported since len() of a TimeSpec is undefined. Just like a tuple it is an immutable object.

Depending on the application these might not be convenient, therefore the object has the following methods to retrieve the time in different formats:

  • .timestamp()
    This returns a UNIX timestamp value of the time as a Python float. Equivalent of t.tv_sec + t.tv_nsec/10.0**-9. If you wanted the integer timestamp just use the tv_sec attribute.
  • .float()
    Alias for .timestamp(), but this may be more natural when working with durations.
  • .mktime()
    Return the time as a floating point, but converted to the local timezone. The returned time is not a UNIX or POSIX timestamp.
  • .timetuple()
    Returns a time.struct_time instance in UTC.
  • .gmtime()
    Alias for .timetuple().
  • .localtime()
    Returns a time.struct_time instance in the local timezone.
  • .datetime()
    Returns a datetime.datetime instance representing the time in the local timezone. Note that the tzinfo of the datetime object will be unset.
  • .utcdatetime()
    Returns a datetime.datetime instance representing the time in UTC.
  • .timedelta()
    Returns a datetime.timedelta instance.

Note that when using Python 2.2 you don't have the datetime module available and hence the .datetime(), .utcdatetime() and .timedelta() methods will not be present.

Numeric Proctol

On top of the above mentioned methods the TimeSpec class also supports part of the numeric protocol. It is possible to use a number of standard Python objects together with TimeSpec objects when using the numeric protocol. They are each converted on the fly for the operation, the result is always a TimeSpec object however.

  • Numbers
    When integers or floats are used they represent the seconds part of a timespec, the decimal part of a float counts towards the nanoseconds.
  • Tuples
    A 2-tuple of integers is accepted too. The first integer is treated as the seconds, the second integer as the nanoseconds.

Specifically these operations are supported:

  • Comparison
    You can compare with integers, floats and 2-tuples of integers. The numbers are interpreted as explained above.
  • Addition
    You can add two TimsSpec objects together as well as add integers, floats and 2-tuples of integers.
  • Subtraction
    Subtraction, same rules as for addition.
  • Boolean Representation
    If a TimeSpec value is (0, 0) then bool() will treat is as False, otherwise it will be treated as True by bool(). Bear in mind that a TimeSpec value could be negative too which is also True just like bool(-1) is True.


It is debatable if more of the numeric protocol should be defined. Multiplication with an integer would be easily done for example. But this might create more confusion then it's worth. Supporting float() and int() just like we support bool() might be convenient too.