Epoch to readable date Problem

Former Member
Former Member
Hi. i'm creating an app that get a json data from Internet, in the file exist a time data in milliseconds (epoch time or unix), my principal problem is when i tray to convert to a readable time i get incorrect time.

Time from json:
"time":1446483157632

var epoch=value2["time"].toLong("%d");

var now=new Time.Moment(epoch);
var info = Calendar.info(now, Time.FORMAT_SHORT);

var dateStr = Lang.format("$1$/$2$/$3$", [info.day,info.month, info.year]);
var timeStr = Lang.format("$1$:$2$:$3$",[info.hour.format("%2d"), info.min.format("%02d"), info.sec.format("%02d")]);
Sys.println("---time: "+ dateStr+" "+timeStr);


Result Simulator
---time: 2/12/2076 11:49:36

Should be
Mon, 02 Nov 2015 16:52:37

please someone can help me.

thanks
  • Former Member
    Former Member over 9 years ago
    Data

    I'm getting the data from usgs site http://earthquake.usgs.gov/fdsnws/event/1/query?limit=5&format=geojson. i thing the watch read the data diferent. i debug the epoch time in the watch and show a different compared with the simulator, i dont now why happend this :/. im using a fenix 3 firmware 5 with the 1.21v SDK


    var url ="earthquake.usgs.gov/.../query
    Comm.makeJsonRequest(url,{"format"=>"geojson","latitude"=>posnInfo.position.toDegrees()[0],
    "longitude"=>posnInfo.position.toDegrees()[1],"maxradiuskm"=>320,"limit"=>5,"orderby"=>"time"},
    {:method=>Comm.HTTP_REQUEST_METHOD_GET, :headers=>{}},
    method(:onReceive));

    function onReceive(responseCode, data)
    {
    currentVal=0;
    if( responseCode == 200 )
    {
    var value=data["features"];
    sizeList=value.size();
    if( sizeList>0 )
    {
    eqList=new [value.size()];

    for (var i = 0; i < sizeList; i++)
    {
    var item=new EarthQuakeItem();
    var value2=value["properties"];

    var StringTime=value2["time"].toString();
    var timeZoneOff=Sys.getClockTime().timeZoneOffset;

    var res=(StringTime.toFloat()-timeZoneOff)/1000;
    var now=new Time.Moment(res);

    var info = Calendar.info(now, Time.FORMAT_SHORT);

    var dateStr = Lang.format("$1$/$2$/$3$",[info.day,info.month, info.year]);
    var timeStr = Lang.format("$1$:$2$",[info.hour, info.min]);

    item.date=dateStr;
    item.time=timeStr;
    eqList=item;
    }
    }
    }
    }
    [/CODE]
  • var res=(epoch-timeZoneOff)/1000.0;



    This code is wrong. The value epoch is in milliseconds, and timeZoneOff is specified in seconds. You need to write...

    var res = (epoch / 1000) - timeZoneOff;


    Also, converting from a float to a string, then back to a float as you are doing is unnecessary.

    Travis
  • The problem is that I can't determine if the problem is in {{Gregorian.info()}} or not. You're only showing the final result on the fenix3, and I can see that it is wrong. Unfortunately, your code is also wrong. I don't have a fenix3 to test on, and I don't have the time to spend trying to re-create your test case from the ground up.

    Perhaps we should go at this from another direction. What does the following test case produce on your fenix3 and in the simulator?? Does it produce the output that I suggest in the comments?

    Note: This code may require some slight tweaking, I'm writing it without access to a development environment.

    using Toybox.Graphics as Gfx;
    using Toybox.WatchUi as Ui;
    using Toybox.Lang as Lang;
    using Toybox.Time as Time;
    using Toybox.Application as App;

    class TestView extends Ui.View
    {
    function initialize() {
    View.initialize();
    }

    function onUpdate(dc) {
    dc.setColor(Gfx.COLOR_BLACK, Gfx.COLOR_BLACK);
    dc.clear();

    dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_TRANSPARENT);

    var milliseconds = 1447851065344.000000;
    var seconds = (milliseconds / 1000).toNumber();

    // you only need to do this if the input data is specified in UTC time and you want to display it in local
    // time. the documentation just says the `epoch', but it doesn't specify if in local time or not. normally
    // it would be in universal time, so i'm going to assume that it is. if you just want to display universal
    // time, then comment this out;
    // seconds -= Sys.getClockTime().timeZoneOffset;

    var info = Calendar.info(new Time.Moment(seconds), Time.FORMAT_SHORT);

    var iso8601 = Lang.format("$1$-$2$-$3$T$4$:$5$:$6$Z", [
    info.year.format("%04d"),
    info.month.format("%02d"),
    info.day.format("%02d"),
    info.hour.format("%02d"),
    info.min.format("%02d"),
    info.sec.format("%02d")
    ]);

    var fx = dc.getFontHeight(Gfx.FONT_SMALL);

    var cx = dc.getWidth() / 2;
    var cy = dc.getHeight() / 2 - fx;

    dc.drawText(cx, cy, Gfx.FONT_SMALL, milliseconds.toString(), Gfx.TEXT_JUSTIFY_CENTER | Gfx.TEXT_JUSTIFY_VCENTER);
    cy += fx;

    dc.drawText(cx, cy, Gfx.FONT_SMALL, seconds.toString(), Gfx.TEXT_JUSTIFY_CENTER | Gfx.TEXT_JUSTIFY_VCENTER);
    cy += fx;

    dc.drawText(cx, cy, Gfx.FONT_SMALL, iso8601, Gfx.TEXT_JUSTIFY_CENTER | Gfx.TEXT_JUSTIFY_VCENTER);

    // should print...
    // 1447851065344.000000
    // 1447851065
    // 2015-11-18T12:51:05Z
    }
    }

    class TestApp extends App.AppBase {

    function initialize() {
    AppBase.initialize();
    }

    function getInitialView() {
    return [ new TestView() ];
    }
    }
  • Basic logic of how I deal with epoch in json data:

    epoch=data["current_observation"]["observation_epoch"];
    if(epoch.length()>0 ) {
    epoch=epoch.toNumber();


    var nowTS=new Time.Moment(0);
    var offset = new Toybox.Time.Duration(epoch);
    nowTS = nowTS.add( offset );

    var timeStamp = Calendar.info(nowTS, Time.FORMAT_MEDIUM);
    ...


    I create a "0" moment, then add the epoch as a "duration", and the result is a moment for the epoch... You can probably do TZ adjustment with the moment, but never tried it... (I think the moment may already be in your local TZ)
  • Former Member
    Former Member over 9 years ago
    don work

    The problem is that I can't determine if the problem is in {{Gregorian.info()}} or not. You're only showing the final result on the fenix3, and I can see that it is wrong. Unfortunately, your code is also wrong. I don't have a fenix3 to test on, and I don't have the time to spend trying to re-create your test case from the ground up.

    Perhaps we should go at this from another direction. What does the following test case produce on your fenix3 and in the simulator?? Does it produce the output that I suggest in the comments?

    Note: This code may require some slight tweaking, I'm writing it without access to a development environment.

    using Toybox.Graphics as Gfx;
    using Toybox.WatchUi as Ui;
    using Toybox.Lang as Lang;
    using Toybox.Time as Time;
    using Toybox.Application as App;

    class TestView extends Ui.View
    {
    function initialize() {
    View.initialize();
    }

    function onUpdate(dc) {
    dc.setColor(Gfx.COLOR_BLACK, Gfx.COLOR_BLACK);
    dc.clear();

    dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_TRANSPARENT);

    var milliseconds = 1447851065344.000000;
    var seconds = (milliseconds / 1000).toNumber();

    // you only need to do this if the input data is specified in UTC time and you want to display it in local
    // time. the documentation just says the `epoch', but it doesn't specify if in local time or not. normally
    // it would be in universal time, so i'm going to assume that it is. if you just want to display universal
    // time, then comment this out;
    // seconds -= Sys.getClockTime().timeZoneOffset;

    var info = Calendar.info(new Time.Moment(seconds), Time.FORMAT_SHORT);

    var iso8601 = Lang.format("$1$-$2$-$3$T$4$:$5$:$6$Z", [
    info.year.format("%04d"),
    info.month.format("%02d"),
    info.day.format("%02d"),
    info.hour.format("%02d"),
    info.min.format("%02d"),
    info.sec.format("%02d")
    ]);

    var fx = dc.getFontHeight(Gfx.FONT_SMALL);

    var cx = dc.getWidth() / 2;
    var cy = dc.getHeight() / 2 - fx;

    dc.drawText(cx, cy, Gfx.FONT_SMALL, milliseconds.toString(), Gfx.TEXT_JUSTIFY_CENTER | Gfx.TEXT_JUSTIFY_VCENTER);
    cy += fx;

    dc.drawText(cx, cy, Gfx.FONT_SMALL, seconds.toString(), Gfx.TEXT_JUSTIFY_CENTER | Gfx.TEXT_JUSTIFY_VCENTER);
    cy += fx;

    dc.drawText(cx, cy, Gfx.FONT_SMALL, iso8601, Gfx.TEXT_JUSTIFY_CENTER | Gfx.TEXT_JUSTIFY_VCENTER);

    // should print...
    // 1447851065344.000000
    // 1447851065
    // 2015-11-18T12:51:05Z
    }
    }

    class TestApp extends App.AppBase {

    function initialize() {
    AppBase.initialize();
    }

    function getInitialView() {
    return [ new TestView() ];
    }
    }




    The problem is not the format, when a run your code on the simulator i get a very close result, in the simulator and in the watch, but when i get the time from internet and i try to show it the watch show me a wrong date, i think that the problem is in the watch, they get a different date from the internet.






    using Toybox.Graphics as Gfx;
    using Toybox.WatchUi as Ui;
    using Toybox.Lang as Lang;
    using Toybox.Time as Time;
    using Toybox.Application as App;
    using Toybox.Time.Gregorian as Calendar;
    using Toybox.System as Sys;
    using Toybox.Communications as Comm;

    class TestView extends Ui.View
    {

    var url="earthquake.usgs.gov/.../query";
    var eqList=null;
    function initialize() {
    View.initialize();

    Comm.makeJsonRequest(url,{"format"=>"geojson","limit"=>1,"orderby"=>"time"},
    {:method=>Comm.HTTP_REQUEST_METHOD_GET, :headers=>{}},
    method(:onReceive));
    }

    function onUpdate(dc) {
    if(eqList!=null)
    {
    dc.setColor(Gfx.COLOR_BLACK, Gfx.COLOR_BLACK);
    dc.clear();

    dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_TRANSPARENT);

    var milliseconds = eqList.toFloat();
    var seconds = (milliseconds / 1000).toNumber();

    // you only need to do this if the input data is specified in UTC time and you want to display it in local
    // time. the documentation just says the `epoch', but it doesn't specify if in local time or not. normally
    // it would be in universal time, so i'm going to assume that it is. if you just want to display universal
    // time, then comment this out;
    //seconds -= Sys.getClockTime().timeZoneOffset;

    var info = Calendar.info(new Time.Moment(seconds), Time.FORMAT_SHORT);

    var iso8601 = Lang.format("$1$-$2$-$3$T$4$:$5$:$6$Z", [
    info.year.format("%04d"),
    info.month.format("%02d"),
    info.day.format("%02d"),
    info.hour.format("%02d"),
    info.min.format("%02d"),
    info.sec.format("%02d")
    ]);

    var fx = dc.getFontHeight(Gfx.FONT_SMALL);

    var cx = dc.getWidth() / 2;
    var cy = dc.getHeight() / 2 - fx;

    dc.drawText(cx, cy, Gfx.FONT_SMALL, milliseconds.toString(), Gfx.TEXT_JUSTIFY_CENTER | Gfx.TEXT_JUSTIFY_VCENTER);
    cy += fx;

    dc.drawText(cx, cy, Gfx.FONT_SMALL, seconds.toString(), Gfx.TEXT_JUSTIFY_CENTER | Gfx.TEXT_JUSTIFY_VCENTER);
    cy += fx;

    dc.drawText(cx, cy, Gfx.FONT_SMALL, iso8601, Gfx.TEXT_JUSTIFY_CENTER | Gfx.TEXT_JUSTIFY_VCENTER);
    }
    // should print...
    // 1447851065344.000000
    // 1447851065
    // 2015-11-18T12:51:05Z
    }


    function onReceive(responseCode, data)
    {
    Sys.println(data);
    if( responseCode == 200 )
    {
    var value=data["features"];
    var sizeList=value.size();
    if( sizeList>0 )
    {
    for (var i = 0; i < sizeList; i++)
    {
    var value2=value["properties"];

    eqList=value2["time"].toString();
    Ui.requestUpdate();
    }
    }
    }
    }
    }

    class TestApp extends App.AppBase {

    function initialize() {
    AppBase.initialize();
    }

    function getInitialView() {
    return [ new TestView() ];
    }
    }[/CODE]
  • Given that, it looks like the code that handles the json data on the fenix3 is truncating the result before it ever gets to your application code. i.e., this is a device firmware bug and it might exist on other devices. I'll report it to Garmin.
  • Former Member
    Former Member over 9 years ago
    Thanks

    Yes it's a bug :( I'm just hope the Garmin team fix this bug to launch my app. Thanks you very much TRAVIS for all your help :)
  • One small note. To avoid loss of precision when doing arithmetic, the millisecond offset value that is retrieved needs to be promoted to a double. In your test case...

    // var milliseconds = eqList.toFloat();
    var milliseconds = eqList.toDouble();
    var seconds = (milliseconds / 1000).toNumber();


    This accounts for the small error you mention when testing on the simulator. The other issue is a ConnectIQ bug and isn't limited to the fenix3. I have been able to reproduce it on a fr920xt and fr630. I'm guessing it is also a problem on the vivoactive, but I'm too lazy to test it.

    Travis
  • Former Member
    Former Member over 9 years ago
    Nice to know it

    I got note about that, thanks again for all you help. i think to upload my app with the date and hour disable, until garmin fix this.