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 convertingfort::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:
py_fort_myrmidon.Time.__init__()
# equivalent but less precise than m.Time.Now() fm.Time(time.time())
py_fort_myrmidon.Time.ToTimestamp()
#equivalent to time.time() fm.Time.Now().ToTimestamp()
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
:
py_fort_myrmidon.Time.__init__()
# equivalent to m.Time.Now() m.Time(datetime.utcnow()) # use a naïve object m.Time(datetime.now(timezone.UTC).astimezone(tz=None)) # transform it to a naïve object
py_fort_myrmidon.Time.ToDateTime()
# equivalent to datetime.utcnow() m.Time.Now().ToDateTime()
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:
py_fort_myrmidon.Time.ToDateTime()
, will return values that differs from one can read from thepy_fort_myrmidon.Time.__str__()
if not careful to take into account the local timezone.before passing any
datetime.datetime
object topy_fort_myrmidon.Time.__init__()
, one must ensure they are converted to localtime first. One could usedatetime.datetime.astimezone()
withtz=None
to do 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 thePOSIXct
object to convert it to afmTime
.# equivalent to fmTimeParse("2019-11-02T23:03:04Z") fmTimeCreate(as.POSIXct("2019/11/02 23:03:04",tz="UTC"))
fmTime$asPOSIXct()
will returns afmTime
as aPOSIXct
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