Time Representation

fort-myrmidon uses its own classes to represent fort::Time and fort::Duration. These have been developped to handle the following features, which are not available with most time object representation:

  • Microseconds precision (actually up to nanosecond).

  • Robustness to wall clock reset, that could naturally happen when the system clock is reset by ntp on windows, or when a leap second occurs. Like the go time package, it uses a mix of wall and monotonic clocks (issued by the camera/framegrabber). It support multiple monotonic clock sources ( when tracking data is acquired concurrently by multiple clock source).

  • Supports for representing -∞ and +∞ time concepts.

Due to python and R limitation, we cannot implictly convert native time object of these object from and to fort::Time and fort::Duration. Indeed:

  • python time.time() representation and R POSIXct as a double precision floating point number of second ellapsed from the system epoch, is only guaranted 10us precision for time arround the year 2020. However the framegrabber used in the FORT issues time which are precise to the microsecond. By converting fort::Time objects to these native representation, rounding error may occurs and may change the behavior of certain queries.

  • R only supports 32-bit integer, that may overflow for duration of more than 2s when expressed in nanoseconds.

Note

For the aforementioned reasons, the c++ classes fort::Time and fort::Duration are binded to python and R. It means that you would find py_fort_myrmidon.Time, py_fort_myrmidon.Duration, fmTime, fmDuration objects, which are used instead of the native time object. The following section describes the perticularity of casting native time object to and from the fort-myrmidon object.

C++

Example

fort::Time and fort::Duration provides operators for manipulating duration naturally:

#include <iostream>
#include <fort/time/Time.hpp>

auto start = fort::Time::Now();
// do some operation
ellapsed = fort::Time::Now().Sub(start);
std::cerr << "operation took: " << ellapsed << std::endl;

//always true:
start < fort::Time::Forever();
start > fort::Time::SinceEver();
start < start.Add(5 * fort::Duration::Second + 2 * fort::Duration::Millisecond);

Python

Python convertion to and from time.Time

py_fort_myrmidon.Time objects can be created from and converted to a float number of seconds from the epoch, as returned by time.time() or datetime.datetime.timestamp(), with:

Note

These conversions have a guaranted precision of only +/-10 us.

Python convertion to and from datetime.datetime

py_fort_myrmidon.Time objects can be created from and converted to datetime.datetime:

Warning

As cpython and c++17 lacks supports for timezone, these datetime.datetime objects are treated as naïve objects, i.e. object wihtout an associated timezone, and assumed to be in local time. On the contrary, fort::Time uses only UTC time. It means that:

Example

py_fort_myrmidon.Time and py_fort_myrmidon.Duration provides overloaded operator that gives a natural feeling on time manipulation.

import py_fort_myrmidon as fm

start = fm.Time.Now()
somefunction()
ellapsed = fm.Time.Now() - start # equivalent to ellapsed = fm.Time.Now().Sub(start)

later = start + 5 * fm.Duration.Second # equivalent to later = start.Add(5 * fm.Duration.Second)

# we can compare Time and Duration
later > start # equivalent to later.After(start)
later < start # equivalent to later.Before(start)
later == start # equivalent to later.Equals(start)
later >= start
later <= start

# always true
start > fm.Time.SinceEver()

R

Conversion to and from POSIXct

R represents times as POSIXct objects, i.e. a numerical number of seconds since the system epoch, marked with the POSIXct class. One can use the following function to convert to and from a fmTime object:

  • fmTimeCreate() can take a number of second since epoch, simply use the POSIXct object to convert it to a fmTime.

    # equivalent to fmTimeParse("2019-11-02T23:03:04Z")
    fmTimeCreate(as.POSIXct("2019/11/02 23:03:04",tz="UTC"))
    
  • fmTime$asPOSIXct() will returns a fmTime as a POSIXct object.

    # equivalent to:
    # d <- as.POSIXct("2019/11/02 23:03:04",tz="UTC")
    # attr(d,"tzone") <- NULL # fmTime$asPOSIXct() reports no timezone
    d <- fmTimeParse("2019-11-02T23:03:04Z")$asPOSIXct()
    

Example

Here is an example of the fmTime and fmDuration R API:

library(FortMyrmidon)

start <- fmTimeNow()
# do some work
ellapsed <- fmTimeNow()$sub(start)

later <- start$add(fmSecond(5.0))

# we can compare time objects
later > start
later < start
later == start
later <= start
later >= start

# we can access +/- ∞ values
later >= fmTimeForever() # always FALSE
later > fmTimeSinceEver() # always TRUE