Formatted Output

Former Member
Former Member
hi there,

i have a problem with the formatted output for a given time on my whatchface:

view.setText(Lang.format("$1$:$2$:$3$", [hh.format("%.2d"), mm.format("%.2d"), ss.format("%.2d")]));

for example hh=12; mm=2; ss=5;

it works fine on the emulator (12:02:05 is correctly shown on screen), but it doesn't work "in real" at my fenix3 device (12:2:5 ist shown there!).

any idea what's wrong here?

thanks in advance.

stefan
  • What of you use a format of "%02d" instead of "%.2%"?
  • Former Member
    Former Member over 9 years ago
    The printf implementation that runs on our devices does not properly format the .X specifier for integers. The 0X specifier should have the same expected result, and will work properly.
  • The printf implementation that runs on our devices does not properly format the .X specifier for integers.


    I don't believe your implementations on the devices are buggy; I'm pretty sure it is the simulator. The C99 specification (N1336 7.19.6.1 p4) has this to say...

    Each conversion specification is introduced by the character %. After the %, the following appear in sequence:
    — Zero or more flags (in any order) that modify the meaning of the conversion specification.
    — An optional minimum field width. If the converted value has fewer characters than the field width, it is padded with spaces (by default) on the left (or right, if the left adjustment flag, described later, has been given) to the field width. The field width takes the form of an asterisk * (described later) or a nonnegative decimal integer. (244)
    — An optional precision that gives the minimum number of digits to appear for the d, i, o, u, x, and X conversions, the number of digits to appear after the decimal-point character for a, A, e, E, f, and F conversions, the maximum number of significant digits for the g and G conversions, or the maximum number of bytes to be written for s conversions. The precision takes the form of a period (.) followed either by an asterisk * (described later) or by an optional decimal integer; if only the period is specified, the precision is taken as zero. If a precision appears with any other conversion specifier, the behavior is undefined.
    — An optional length modifier that specifies the size of the argument.
    — A conversion specifier character that specifies the type of conversion to be applied

    244) Note that 0 is taken as a flag, not as the beginning of a field width.


    7.19.6.1 p6 defines the expected behavior for the 0 flag.

    For d, i, o, u, x, X, a, A, e, E, f, F, g, and G conversions, leading zeros (following any indication of sign or base) are used to pad to the field width rather than performing space padding, except when converting an infinity or NaN. If the 0 and - flags both appear, the 0 flag is ignored. For d, i, o, u, x, and X conversions, if a precision is specified, the 0 flag is ignored. For other conversions, the behavior is undefined.


    As I read it, the format specification %0.2d is read as flag=0, precision=2, specifier=d. In this case, the 0 flag and a precision are specified; the 0 flag is to be ignored. If you want to use a d, i, o, u, x, or X conversion and want it to be padded with 0 on the left, you must specify the field width. i.e., flag=0, width=2, specifier=d or %02d.
  • Former Member
    Former Member over 9 years ago
    The format "%02d" works fine (at fenix3 and emulator).
    Thanks for your help!
  • Former Member
    Former Member over 9 years ago
    The API docs quote http://www.cplusplus.com/reference/cstdio/printf/ as a reference for format, which is not the C99 spec and clearly states that when using .precision with an integer, zero padding is used.

    Please can you update the API docs either to reference other documentation that you do follow, or to explicitly document the true behaviour of the format methods?

    Or, if you do intend to follow the documentation you link to, please update the device firmware to behave correctly.

    My experience is actually that the Fenix 3 (and the simulator as any device) does behave as I would expect - "%.2d" renders 07 when supplied with 7, but the Vivoactive does not behave that way - "%.2d" renders 7 (not even space padding). I'm not sure about other devices. Consistency would be really helpful!
  • Yeah... time to update the documentation please. The forums are not searchable for this.
  • I didn't think our documents referenced cplusplus.com anymore, but I see it in the API docs. I'll get that revised.
  • hi,

    zero padding is not working for me in the emulator for 230, fenix3, vivoactive, vivoactive hr.

    ret = h.toString("%02d")+":"+m.toString("%02d")+suffix;

    and it shows
    8:30PM

    whilst i would expect 08:30PM.

    am i missing something?
    after reading this post, i have tried "%.2d", even though it looks strange. it does not work either.
    any idea?

    thank you in advance
  • Are you on windows or a mac, and what SDK?
    I did this on Windows and 2.2.2 and got 08:30PM in all cases with the simulator:
    var h=8;
    var m=30;
    var suffix="PM";
    var ret=h.format("%02d")+":"+m.format("%02d")+suffix;
    Sys.println(ret);


    Oh, wait, you're using toString(). I didn't think that took a format, and per the doc, it doesn't. I'm surprised an error isn't thrown.
    What it looks like is you're actually doing:

    ret=h.toString()+":"+m.toString()+suffix;

    in fact I just tried:
    ret=h.toString("bogus")+":"+m.toString("bogus")+suffix;

    and the output is 8:30PM
  • I cannot reproduce the issue...

    using Toybox.Application as App;
    using Toybox.System as Sys;
    using Toybox.Lang as Lang;
    using Toybox.WatchUi as Ui;
    using Toybox.Test as Test;

    function do_test_format_number(logger, n, fmt, s)
    {
    var r = n.format(fmt);

    logger.debug(Lang.format("$1$.format(\"$2$\") => $3$", [ n, fmt, r ]));
    Test.assertEqual(r, s);
    }

    (:test) function test_format_number(logger)
    {
    do_test_format_number(logger, 0, "%02d", "00");
    do_test_format_number(logger, 1, "%02d", "01");
    do_test_format_number(logger, 2, "%02d", "02");
    do_test_format_number(logger, 3, "%02d", "03");
    do_test_format_number(logger, 4, "%02d", "04");
    do_test_format_number(logger, 5, "%02d", "05");
    do_test_format_number(logger, 6, "%02d", "06");
    do_test_format_number(logger, 7, "%02d", "07");
    do_test_format_number(logger, 8, "%02d", "08");
    do_test_format_number(logger, 9, "%02d", "09");
    do_test_format_number(logger, 10, "%02d", "10");
    do_test_format_number(logger, 11, "%02d", "11");
    do_test_format_number(logger, 99, "%02d", "99");
    do_test_format_number(logger, 100, "%02d", "100");
    do_test_format_number(logger, 999, "%02d", "999");

    return true;
    }

    class TestApp extends App.AppBase
    {
    function initialize() {
    AppBase.initialize();
    }

    function getInitialView() {
    return null;
    }
    }


    Here is the output when running with the simulated fr230.

    C:\Users\Travis\workspace\Test>monkeyc.bat -v
    Connect IQ compiler version 2.2.2

    C:\Users\Travis\workspace\Test>monkeyc.bat -x release -w -t -y C:\Development\3rdparty\connectiq\developer.key -o bin\TestApp.prg -m manifest.xml -n 2.1.1 -z resources\resources.xml -d fr230 source\TestApp.mc
    WARNING: The launcher icon (30x30) is smaller than the specified launcher icon size of the device 'fr230' (40x40). Padding will be added to the image to center it.
    WARNING: No supported languages are defined. It's a good idea to indicate which languages you are supporting.

    C:\Users\Travis\workspace\Test>monkeydo.bat bin\TestApp.prg fr230 /t
    Found Transport: tcp
    Connecting...
    Connecting to device...
    Device Version 0.1.0
    Device id 1 name "A garmin device"
    Shell Version 0.1.0
    Copying file.... 2% complete
    Copying file.... 4% complete
    Copying file.... 7% complete
    Copying file.... 9% complete
    Copying file.... 12% complete
    Copying file.... 14% complete
    Copying file.... 17% complete
    Copying file.... 19% complete
    Copying file.... 21% complete
    Copying file.... 24% complete
    Copying file.... 26% complete
    Copying file.... 29% complete
    Copying file.... 31% complete
    Copying file.... 34% complete
    Copying file.... 36% complete
    Copying file.... 39% complete
    Copying file.... 41% complete
    Copying file.... 43% complete
    Copying file.... 46% complete
    Copying file.... 48% complete
    Copying file.... 51% complete
    Copying file.... 53% complete
    Copying file.... 56% complete
    Copying file.... 58% complete
    Copying file.... 61% complete
    Copying file.... 63% complete
    Copying file.... 65% complete
    Copying file.... 68% complete
    Copying file.... 70% complete
    Copying file.... 73% complete
    Copying file.... 75% complete
    Copying file.... 78% complete
    Copying file.... 80% complete
    Copying file.... 83% complete
    Copying file.... 85% complete
    Copying file.... 87% complete
    Copying file.... 90% complete
    Copying file.... 92% complete
    Copying file.... 95% complete
    Copying file.... 97% complete
    Copying file.... 100% complete
    File pushed successfully
    Connection Finished
    Closing shell and port
    Found Transport: tcp
    Connecting...
    Connecting to device...
    Device Version 0.1.0
    Device id 1 name "A garmin device"
    Shell Version 0.1.0
    ------------------------------------------------------------------------------
    Executing test test_format_number...
    DEBUG (11:11): 0.format("%02d") => 00
    DEBUG (11:11): 1.format("%02d") => 01
    DEBUG (11:11): 2.format("%02d") => 02
    DEBUG (11:11): 3.format("%02d") => 03
    DEBUG (11:11): 4.format("%02d") => 04
    DEBUG (11:11): 5.format("%02d") => 05
    DEBUG (11:11): 6.format("%02d") => 06
    DEBUG (11:11): 7.format("%02d") => 07
    DEBUG (11:11): 8.format("%02d") => 08
    DEBUG (11:11): 9.format("%02d") => 09
    DEBUG (11:11): 10.format("%02d") => 10
    DEBUG (11:11): 11.format("%02d") => 11
    DEBUG (11:11): 99.format("%02d") => 99
    DEBUG (11:11): 100.format("%02d") => 100
    DEBUG (11:11): 999.format("%02d") => 999
    PASS

    ==============================================================================
    RESULTS
    Test: Status:
    test_format_number PASS
    Ran 1 test

    PASSED
    Connection Finished
    Closing shell and port

    C:\Users\Travis\workspace\Test>


    I get exactly the same output for the fenix3, vivoactive, and vivoactive_hr simulated device profiles.

    What version of the ConnectIQ SDK are you using?