Understanding Time

With behavioral data, time plays a very important role. Yet, time-related data is especially hard to analyze. The main culprit is the fact that time concepts are confusing. While humans can handle time intuitively, passing these intuitions to a computer program is hard. For example, implementing a growth rate using a relative duration of “twelve months” or an absolute duration of “fifty two weeks” can influence the outcome dramatically. To the human brain these distinctions can be confusing to understand and explain. Most programming tools sport a host of functions to help convert time to numbers and back. This usually leads to fewer but more subtle errors.

In order to make it as easy as possible to work with time, Rax implements five different temporal types. Point in time, absolute duration, relative duration, time interval, and time interval modulo. Combining exact temporal types with strong type checking proved to be effective in catching temporal errors because it forces modelers to express what they mean exactly. In addition to the temporal types, Rax implements a number of temporal operators which make dealing with time-related data easier and more intuitive than SQL. For example, the temporal and (@&) operator allows to easily compute the overlap between two sets of intervals. This is very useful when computing, for example ratings of TV programs, like in the below example.

{[#:channelNr, $:programTitle, |:airTime]}: tvProgramming := {
  [1, "Product X ad on channel 1", (|)"2013-11-06T20:30/2013-11-06T20:32"],
  [2, "Product X ad on channel 2", (|)"2013-11-06T20:03/2013-11-06T20:05"],
  [2, "Scary horror movie", (|)"2013-11-06T20:05/2013-11-06T22:00"]
{[#:respondentId, #:channelNr, |:viewingPeriod]}: viewingData := {
  [1, 1, (|)"2013-11-06T19:59/2013-11-06T20:31"],
  [2, 1, (|)"2013-11-06T17:13/2013-11-06T22:07"],
  [2, 2, (|)"2013-11-06T22:07/2013-11-06T22:31"],
  [3, 2, (|)"2013-11-06T19:18/2013-11-06T22:31"],
  [4, 1, (|)"2013-11-06T19:59/2013-11-06T21:07"],
  [4, 2, (|)"2013-11-06T21:59/2013-11-06T22:31"]
&: totalNumRespondents := # ! project [.respondentId] viewingData;
`print "Num respondents: " + ($)totalNumRespondents;
{[#:channelNr, $:programTitle, |:viewingTime, #:respondentId, #:chNr]}:
  viewings := tvProgramming @& :[.channelNr#1 == .channelNr#2] viewingData;
{[#:channelNr, $:programTitle, &:rating]}: ratings :=
  project [.#2, .#3, .#1/totalNumRespondents]
  Gcount [.respondentId]:[.channelNr, .programTitle] viewings;
`print ratings;

Another example of a specialized temporal operator is temporal union: @\/ which allows to unify short events into longer ones, useful for example for converting clickstreams into website visits.