Offset from evalStart in metric


I have a metric (let’s call it LatestValueTimestamp) that returns the timestamp of the most recent entry of a TVH type. I now want to define a CompoundMetric which checks if LatestValueTimestamp is missing or not.

If LatestValueTimestamp is missing, the metric should return a timestamp which represents the beginning of the evaluation period (evalStart()) otherwise, just returns the value of LatestValueTimestamp

We have tried:

missing(LatestValueTimestamp) ? evalStart() : LatestValueTimestamp
missing(LatestValueTimestamp) ? number(evalStart()) : LatestValueTimestamp
missing(LatestValueTimestamp) ? number(toMillis(evalStart())) : LatestValueTimestamp
missing(LatestValueTimestamp) ? number(string(toMillis(evalStart()))) : LatestValueTimestamp

But the expression engine doesn’t seem to like any of these - all of which throw some variety of error saying the types cannot be converted to each other. What would be a good way to do this?



For the first one, evalStart(), we get this error: Cannot operaate on Timeseries of mismatched type datetime and double

and for the rest, we get this error:

Bad type on operand stack
Exception Details:
    c3/love/expr/bytecode/Expr_549086516889628973_5738946035958120516.eval(Lc3/love/typesys/Obj;Lc3/love/timeseries/TimeInfo;)Ljava/lang/Object; @35: invokestatic
    Type 'java/lang/Number' (current frame, stack[3]) is not assignable to 'java/math/BigDecimal'
  Current Frame:
    bci: @35
    flags: { }
    locals: { 'c3/love/expr/bytecode/Expr_549086516889628973_5738946035958120516', 'c3/love/typesys/Obj', 'c3/love/timeseries/TimeInfo', 'c3/love/typesys/Arry' }
    stack: { 'c3/love/expr/bytecode/Expr_549086516889628973_5738946035958120516', 'c3/love/typesys/Arry', 'c3/love/timeseries/LazyTimeseries', 'java/lang/Number', 'c3/love/timeseries/LazyTimeseries' }
    0x0000000: 2ab8 003a 4e2d 2ab4 0030 b800 3eb8 0041
    0x0000010: b800 3eb8 0045 b800 3eb8 004b 2ab4 0030
    0x0000020: b800 3eb8 004f b800 3eb9 0055 0200 572d
    0x0000030: 3a04 2a19 042c b600 592a b600 5bb0     

[missing(SM$LatestCuSumValueTimestampWithMissing) ? number(evalStart()) : SM$LatestCuSumValueTimestampWithMissing]"



A fix for this has been added to go to v7.9.1 but here’s what you can do as a workaround:

  1. Add a metric function library function:
type MyMetricFunctionLib mixes MetricFunctionLibrary { 
  convertToDoubleTs: (ts : Timeseries) : Timeseries js server 


function convertToDoubleTs (ts) { 
  if (ts.type().isA(NormTimeseriesDateTime)) { 
     var dates =; 
     var doubles = []; 
     _.each(dates, function(d) { doubles.push(d.getMillis()); }) 
     return Timeseries.makeNorm(NormTimeseriesDoubleSpec.make({start: ts.start(), end: ts.end(), interval: ts.interval(), missing: ts.missing(), data: doubles })); 
  return ts; 
  1. right your expression as:

missing(LatestValueTimestamp) ? convertToDoubleTs(evalStart()) : LatestValueTimestamp