NEED HELP: working with dates in monkeyc, different behaviour

As my first app for ConnectIQ I created calendar widget: https://apps.garmin.com/ru-RU/apps/6deb3671-47db-4cbe-8066-4305ddfcf38b
It works fine on my watch, but users claimes that dates are shifted. So, may someone help me ti figure out what I doing wrong?

Here is a parts of code:
using Toybox.Time as Tm;
using Toybox.Time.Gregorian as Tmg;

// get current datetime, store current month
var curtime = Tm.today();
var grinfo_s = Tmg.info(curtime, Tmg.FORMAT_SHORT);
var cur_month = grinfo_s.month;
// by default display_month = current month
var display_month = cur_month;
...
function onUpdate(dc) {
...
// get displayed month start, next month start (to calculate days_in_month)
var m_start = Tmg.moment({:day=>1,:month=>display_month});
var m_end = Tmg.moment({:day=>1,:month=>display_month + 1});
// print dispayed month name
var grinfo = Tmg.info(m_start, Tmg.FORMAT_LONG);
dc.drawText(..., grinfo.month, ...);
...
}
...
// handling menu
function onMenuItem(item) {
...
// "January" - 1, etc...
if ( item == :item_1 ) {
display_month = 1;
...


feedbacks are:
When i choose January, it's displaying December. It is also showing today as the Thursday the 29th, when it should be Saturday the 30th.

When selecting February is showing January but has only 29 days.


The very strange thing is that on my watch there are no such problems, monthes displayed exactly the same as in real calendar. Same for some users according to positive feedbacks, can't guess the dependencies.
And for now I don't know what to do...
  • It works fine on my watch, but users claimes that dates are shifted. So, may someone help me ti figure out what I doing wrong?


    I found only one problem:
    Tm.today(); returns GMT time/date, how can I get time/date for current TZ?
  • Tm.now();

    Tm.today() is UTC (I think it may be a bug) but now() works fine.
  • Actually, according to our API documentation:
    • Use now() to get a Moment for the current moment in time.
    • Use today() to get a Moment for the beginning of today based on your current GPS location.


    For example, if I use this code (shamelessly ripped off from Koulik):

    using Toybox.WatchUi as Ui;
    using Toybox.System as Sys;
    using Toybox.Lang as Lang;
    using Toybox.Time.Gregorian as Calendar;

    class TimeTestView extends Ui.WatchFace {

    function onUpdate(dc) {
    var now = Calendar.info(Time.now(), Time.FORMAT_LONG);
    var today = Calendar.info(Time.today(), Time.FORMAT_LONG);

    Sys.println(Lang.format("$1$.$2$.$3$ $4$:$5$",
    [now.day, now.month, now.year, now.hour.format("%02d"), now.min.format("%02d")]
    ));

    Sys.println(Lang.format("$1$.$2$.$3$ $4$:$5$",
    [today.day, today.month, today.year, today.hour.format("%02d"), today.min.format("%02d")]
    ));
    }
    }


    I see something like this (it's currently 14:56 CST, my local time):

    4.Feb.2016 14:56
    4.Feb.2016 00:00

    Time.now() is providing the current local time, while Time.today() is generating a moment at the beginning of today.
  • Brandon,

    That is how it is supposed to behave, but there was a bug that was supposed to have been fixed in December. The bug was that Time.today() was returning a value that represented midnight UTC, and not local time. This could cause the month-day to be incorrect. If you are using Time.today() in your code, it might be broken for users of devices that have firmware that does not have this fix.

    If you just need the day/month/year as you do for a calendar, I'd do as Jim suggested and use Time.now() and then just ignore the hours/minutes/seconds fields.

    Travis
  • Brandon - In the simulator it works, but just tried your code on a 230 (latest FW) and here's what I see:

    4.Feb.2016 14:54

    3.Feb.2016 17:00



    it's 2:54pm here and I'm at GMT -7
  • Sorry if I confused things. :)

    The docs describe how it's supposed to work, and I demonstrated that with the sim.

    The issue with Time.today() that Jim and Travis have pointed out was addressed in the 1.2.2 SDK release. In Jim's example of the FR230, the current firmware (v3.30) doesn't yet include the 1.2.2 changes that have the fix. It has been included in our internal development builds, so it should be fixed in the next firmware release.

    So, it's working correctly in the sim, but may not yet work correctly on devices (but it will).
  • it seems that I found the cause of this error, but still dunno how to fix it.
    I have to display some month, so I have month number as input, for example 5 (May).
    now I want to see the very beginning of this month and day of week for that day:

    var m_start = Tmg.moment({:day=>1,:month=>display_month});
    var first_dow = Tmg.info(m_start, Tmg.FORMAT_SHORT).day_of_week;

    which in my timezone (UTC+2) gives me:
    1.May.2016 02:00
    1
    // sunday
    this works fine for UTC>0, but in negative TZ, everything will be shifted to previous day

    So, the question is how to get strict moment for current timezone and how to get day of week for this moment?
  • This should work...

    // now represents the current broken down local time
    var now = Calendar.info(Time.now(), Calendar.FORMAT_SHORT);

    // just to verify
    Sys.println(Lang.format("$1$-$2$-$3$T$4$:$5$:$6$", [
    now.year.format("%4d"),
    now.month.format("%02d"),
    now.day.format("%02d"),
    now.hour.format("%02d"),
    now.min.format("%02d"),
    now.sec.format("%02d")
    ]));

    // this is the time for midnight on the first day of the current month
    // but it is specified in offset from the epoch in UTC time. if you pass
    // this to Calendar.info(), the time will be off by an amount proportional
    // to your zone offset.
    var first_day_of_month = Calendar.moment({
    :year => now.year,
    :month => now.month,
    :day => 1,
    :hour => 0,
    :minute => 0,
    :second => 0
    });

    // apply the local time zone offset so that when Calendar.info() offsets
    // by our local time zone offset, we get back to our actual local time.
    var zoff = Sys.getClockTime().timeZoneOffset;
    first_day_of_month = first_day_of_month.add(new Time.Duration(-zoff));

    // this is the information for the first day of the month in our current local
    // time zone.
    var info = Calendar.info(first_day_of_month, Calendar.FORMAT_SHORT);

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


    I ran this with my system clock set to Cairo (UTC+2), and I got the following...

    2016-02-12T02:01:15
    2016-02-01T00:00:00


    I set my system clock back to US/Pacific (UTC-8), and I got this...

    2016-02-11T16:10:15
    2016-02-01T00:00:00
  • TRAVIS.VITEK, thanks a lot, it works now!