Gregorian.moment returns time with one hour skew (daylight saving?)

Hello,

I want to get Time.moment value for today's midnight. I wrote following function:

function getTodayMidnightMoment()
 {
 
   var nowMoment = new Time.Moment(Time.today().value());
   var nowGregorianInfo = Gregorian.info(NowMoment, Time.FORMAT_MEDIUM);
 
   var todayMidnight = {
    :year   => NowGregorianInfo.year,
    :month  => NowGregorianInfo.month,
    :day    => NowGregorianInfo.day,
    :hour   => 0,  
    :minute => 0,
    :second => 0
    };
  
   var midnightMoment = Gregorian.moment(todayMidnight);

   return midnightMoment;

 }

So it basically checks current date, and tries to get Gregorian.moment for this date, with hour, minute, and second set to 0.

It works, but it returns moment one hour later - 01:00:00 of current day. I'm not sure what causes this, maybe it's related to daylight saving being enabled?  If this is the case, is it somehow possible to programmatically check if watch has daylight saving enabled? Or is there any other method to get actual moment.value for midnight of current time zone?

Thanks,

Wojtek

  • When I've used Gregorian.moment, I've found I needed to subtract System.getClockTime().timeZoneOffset. So something like:

    var timeZoneOffsetDuration = Gregorian.duration({:seconds => System.getClockTime().timeZoneOffset});
    var tempYear = {:year => dateInfoMedium.year, :month => 1, :day => 1, :hour => 12, :minute => 0, :second => 0};
    var startOfYearNoon = Gregorian.moment(tempYear).subtract(timeZoneOffsetDuration);
    

    But I think that converts to UTC, so maybe you could subtract System.getClockTime().dst ?

  • It's been a while since I looked at this, but if I recall, this is a sim vs device difference. On a real device you'll see the correct info, but not in this sim.  On a real device the DST offset is always zero and the time is correct, but in the sim it's not and the time needs to be adjusted.  

  • I'm fairly certain that you can get this with just this:

    function getTodayMidnightMoment()
    {
       return Time.today();
    }

    I made the following code into an app:

    using Toybox.Application;
    using Toybox.WatchUi;
    using Toybox.Time;
    using Toybox.Time.Gregorian;
    
    class TodayView extends WatchUi.View {
    
        hidden var _mLines;
    
        function initialize() {
            View.initialize();
        }
    
        function addTimestamp(moment) {
            var s = moment.value();
            _mLines.add(s.toString());
        }
    
        function addGregorianInfo(info, zone) {
            _mLines.add(Lang.format("$1$/$2$/$3$ @ $4$:$5$$6$ $7$", [
                info.month,
                info.day,
                info.year,
                ((info.hour + 11) % 12) + 1,
                info.min.format("%02u"),
                info.hour < 12 ? "am" : "pm",
                zone
            ]));
        }
    
        function addMoment(moment) {
            addTimestamp(moment);
            addGregorianInfo(Gregorian.utcInfo(moment, Time.FORMAT_SHORT), "utc");
            addGregorianInfo(Gregorian.info(moment, Time.FORMAT_SHORT), "local");
        }
    
        function onLayout(dc) {
            _mLines = [];
            addMoment(Time.today());
        }
    
        function onUpdate(dc) {
            dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_BLACK);
            dc.clear();
    
            var justification = Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER;
    
            var cx = dc.getWidth() / 2;
            var cy = dc.getHeight() / 2;
    
            var font = Graphics.FONT_XTINY;
            var fy = dc.getFontHeight(font);
    
            cy -= (_mLines.size() * fy) / 2;
    
            for (var i = 0; i < _mLines.size(); ++i) {
                dc.drawText(cx, cy, font, _mLines[i], justification);
                cy += fy;
            }
        }
    }
    
    class TodayApp extends Application.AppBase {
    
        function initialize() {
            AppBase.initialize();
        }
    
        function getInitialView() {
            return [ new TodayView() ];
        }
    }

    Both the simulator and the device (a vivoactive4) displayed 

    1576051200
    12/11/2019 @ 8:00am utc
    12/11/2019 @ 12:00am local

    It seems to me that it is doing the right thing. I plugged the timestamp into https://unixtimestamp.com and verified see the same UTC time, and I'm in Pacific Standard Time (UTC-8), so everything checks out on both.

  • Hello, thank you for all the suggestions. Travis solution seems to work well, so i'll try to use that. Regarding Gregorian.moment sim/device difference - i have checked this, and on Fenix 6x, this behaves identically on sim, as well as on real device - Gregorian.moment returns time for 01:00:00 instead of 00:00:00 (i'm in the CET timezone, with daylight saving enabled).

    Thanks!