Ticket Created
over 3 years ago

WERETECH-8841

Problems with Time.Moment().compare(Time.moment())

Hi,

Seeing some odd behaviour with Time calculations not returning Number, as per the documentation. https://developer.garmin.com/connect-iq/api-docs/Toybox/Time/Moment.html#compare-instance_function

This then triggers an unrecoverable error if the output is used within a subsequent Time calculation:

ERROR: Unhandled Exception
DETAILS: NONE
STORE_ID: 
CALLSTACK:
UnexpectedTypeException: Expected an object of type Time.Duration
native function

It looks like the ultimate cause might be a problem with Time.Moment.add();

For example:

function momentNType(moment) {
	var n = moment.value();
	System.println(moment+" has value of "+n);
	nType(n);
}
function nType(n) {
	System.println(n+" is Number? "+(n instanceof Number)+" Long? "+(n instanceof Long));
}
function getOClock(nHoursAgo) {
	var nowTime = Time.now();
	var info = Gregorian.info(nowTime,Time.FORMAT_SHORT);
	var adjustSeconds = (nHoursAgo-1)*3600 + info.min*60 + info.sec;
	System.println("CALCULATE OCLOCK WITH "+nHoursAgo);
	nType(adjustSeconds);
	// Subtracting a Duration from a Moment was not supported until ConnectIQ 3.0.0. 
	// If backward compatibility is a concern, it may be best to add a negative Duration instead.
	return nowTime.add(new Time.Duration(-adjustSeconds));
}

// And then...
var heartTime = getOClock(heartGraphInSeconds/3600); // Time.Moment
var difference = Time.now().compare(heartTime);
System.println("Output from getOClock method");
momentNType(heartTime);
System.println("GETS");
nType(difference);

///////////////////////////
// CONSOLE OUTPUT

Output from getOClock method
Obj: 192 has value of 1599465600
1599465600 is Number? false Long? true
GETS
3928 is Number? false Long? true

G

  • Yep, now I know it’s an issue, the workaround is good. 

    The question, really, is how did I end up with a Long in the first place?

    I certainly didn’t supply one anywhere. 

  • Thanks for the bug report. This happens to be a known bug. The Time.Duration and Time.Moment types do nothing to ensure that the values used internally are of the advertised types.

    You can work around this by forcing the type of the value to be a number. In this case if you modify getOClock to do this, you should be okay.

    {
        // ...
    
        var adjustedTime = nowTime.add(new Time.Duration(-adjustSeconds));
        
        return new Time.Moment(adjustedTime.value().toNumber());
    }