Complete
over 5 years ago

Documentation updated and waiting for future release.

Runtime error with Moment.subtract() when subtracting a Duration


Hi
The following Simple Data Field code snippet fails on my Vivoactive HR. It works in the simulator.

using Toybox.WatchUi;
using Toybox.Time;
using Toybox.Time.Gregorian;

    function compute(info) {
		var aDuration = Gregorian.duration({:minutes => 10});
		var aMoment = Time.now();
		var anEarlierMoment = aMoment.subtract(aDuration);
        return 0.0;
    }


The error log (CIQ_LOG.TXT) says:
ERROR: System Error
DETAILS: Expected a Moment object
STORE_ID: 00000000000000000000000000000000
CALLSTACK:
@PC = 0x300013fe
F:\Eclipse2\workspace\ATest\source\ATestView.mc (compute:14)

where compute:14 is the line containing "var anEarlierMoment..."
The Connect IQ SDK documentation for Module: Toybox::Time says
Moment.subtract() can be used to subtract a Duration from a Moment to give "An earlier Moment"
and specifically in the Instance Methods Summary for Class: Toybox::Time::Moment it says
subtract(subtrahend) ⇒ Toybox::Time::Duration, Toybox::Time::Moment
Subtract a Duration or Moment from a Moment.

so I expected it to work.

Former Member
Former Member
  • We can add some documentation to clarify the situation, but it doesn't look like can easily fix it. The documentation generation script maps symbols to minimum SDK versions, so a given symbol can only have one version associated with it.

  • Former Member
    Former Member over 5 years ago in reply to Travis.ConnectIQ

    Thanks for your reply.

    In fact subtracting values is the workaround I've been using. I just wanted to flag up the issue.

    It's a shame the documentation is wrong (it says Subtract a Duration or Moment from a Moment  - Since: 1.0.0)

    It's also a shame the simulator and real device behave differently - I only saw the problem because it fails on the watch I happen to have.

  • If I remember correctly, the behavior of this function was documented this way for some time, but due to an oversight the implementation was left out originally. A fix was added later, but the documentation was not amended to indicate that subtracting a Duration will only work on devices with ConnectIQ X.Y.Z support (where X.Y.Z is the version number we made the fix).

    If you need to support devices that don't have this support, the workaround is to add a Duration with a negative value:

    using Toybox.Time;
    using Toybox.Time.Gregorian;
    
    var today = new Time.today();
    var yesterday = today.add(new Time.Duration(-Gregorian.SECONDS_PER_DAY));

    Another option is to subtract the values and create a new Moment:

    using Toybox.Time;
    using Toybox.Time.Gregorian;
    
    var today = Time.today();
    var yesterday = new Time.Moment(today.value() - Gregorian.SECONDS_PER_DAY);
    

    For your code:

    function compute(info) {
    	var aDuration = Gregorian.duration({:minutes => 10});
    	
    	// invert the duration
    	aDuration = aDuration.multiply(-1);
    
    	var aMoment = Time.now();
    	
    	// then add it
    	var anEarlierMoment = aMoment.add(aDuration.value());
        return 0.0;
    }