The day of the week starts on Monday and not on Sunday.

Hi, 

how do I change the value in the code so that the day of the week starts on Monday and not on Sunday? Thank you for your help.


var dayOfWeekNumber = Time.Gregorian.info(Time.now(), Time.FORMAT_SHORT).day_of_week -1;      //week starts on Sunday, not Monday?

  • System.getDeviceSettings().firstDayOfWeek

  • It looks like you've modified the code in this post (https://forums.garmin.com/developer/connect-iq/f/discussion/272964/current-day-of-the-week-in-an-ellipse/1311736#1311736). I see that you've made some changes, but I'm going to look at the original code.

    The original code is supposed to print the days of the week (in the device's language) starting with Monday, and highlight the current day. e.g.

    Mon
    Tue
    Wed
    Thu
    Fri
    Sat
    Sun

    On the sim in my computer, it prints the Sun as the first day. This is due to a bug in the original code relating to time zones (*) -- to fix this, wherever you see "Time.Gregorian.info", replace it with "Time.Gregorian.utcInfo", in drawDay(): change "Time.Gregorian.info", replace it with "Time.Gregorian.utcInfo"

    (You'll find that if your system timezone is west of UTC -- e.g. UTC-5 / Eastern Time -- the the first day of the week displayed will be Sunday. Any other timezone -- such as UTC, UTC+1, etc -- will work as expected. This is because the original code uses January 3, 2000 00:00 UTC as a reference date for Monday, but it grabs the day of week in *local time* for that reference date, when it should be getting the day of the week in *UTC time*. In other words, in UTC time, January 3, 2000 00:00 UTC is always a Monday. In local time, January 3, 2000 00:00 UTC is a Monday or a Sunday depending on your local time zone.

    I changed my PC's time zone to UTC+0, restarted eclipse, re-ran the app, and the original code displayed Monday first.)

    Even after this fix, the code also has a bug where if it's currently Sunday, the highlight rectangle is placed in the empty space above Monday, instead of around Sunday.

    To fix this problem, you need to add a couple of lines of code after "var dayOfWeekNumber = ...  //week starts on Sunday, not Monday"

            var dayOfWeekNumber = Time.Gregorian.utcInfo(date, Time.FORMAT_SHORT).day_of_week - 1; //week starts on Sunday, not Monday
            if (dayOfWeekNumber == 0) { // <=== new code
                   dayOfWeekNumber = 7; // <=== new code
               } // <=== new code

    Here's the full drawDay() and highlightDay() functions with the fixes described above. I've also included the original onUpdate(), for reference, as well as other relevant code (with an added comment for Gregorian.moment()).

    (In the code below, the var names localDate and utcDate are little misleading as the format of the input is the same in both cases (each date is a Time.Moment which represents the numbers of seconds since January 1, 1970 at 00:00:00 UTC), but the actual difference is the format of the output: in the case of utcDate, we want to show the day of the week in UTC time, since the input was initialized based on UTC time, and in the case of localDate, we want to show the day of the week in local time, since that's what's relevant to the user.)

        // ...
        
        var fontSize = Graphics.FONT_XTINY;
        var paddingWidth=6; //padding around the text
        var paddingHeight=2; //padding around the text
        var daysX = 0.5; //middle of the screen
        var ySpacing = 0.1; //how much of the screen to leave vertically. The larger the number the greater the spacing
        
        // Note that the args to Gregorian moment are assumed to be in UTC time
        // See: https://developer.garmin.com/connect-iq/api-docs/Toybox/Time/Gregorian.html#moment-instance_function
        // Therefore, KNOWN_MONDAY is January 3, 2000 00:00 UTC
        // and any code which extracts the day of week based on KNOWN_MONDAY
        // should use Gregorian.utcInfo(), not Gregorian.info()
        var KNOWN_MONDAY = Gregorian.moment( {:year=> 2000, :month=> 1, :day=> 3});
        var DAY_LENGTH = 3600 * 24;
    
        // ...
    
        function onUpdate(dc as Dc) as Void {
            
            //clear the screen
            dc.setColor(Graphics.COLOR_RED, Graphics.COLOR_BLACK);
            dc.clear();
            dc.setPenWidth(2);
                    
            //draw all the days of the week down the screen
            drawDay(dc, 1, KNOWN_MONDAY);
            drawDay(dc, 2, KNOWN_MONDAY.add(new Time.Duration(1 * DAY_LENGTH)));
            drawDay(dc, 3, KNOWN_MONDAY.add(new Time.Duration(2 * DAY_LENGTH)));
            drawDay(dc, 4, KNOWN_MONDAY.add(new Time.Duration(3 * DAY_LENGTH)));
            drawDay(dc, 5, KNOWN_MONDAY.add(new Time.Duration(4 * DAY_LENGTH)));
            drawDay(dc, 6, KNOWN_MONDAY.add(new Time.Duration(5 * DAY_LENGTH)));
            drawDay(dc, 7, KNOWN_MONDAY.add(new Time.Duration(6 * DAY_LENGTH)));
           
            //draw the ellipse around that day
            highlightDay(dc, Time.now());
        }
        
        function drawDay(dc, position, utcDate){
            // We use utcInfo() because utcDate was initialized using a
            // date specified in UTC time (KNOWN_MONDAY)
            var name = Time.Gregorian.utcInfo(utcDate, Time.FORMAT_MEDIUM).day_of_week;
            dc.drawText(daysX * dc.getWidth(), position * ySpacing * dc.getHeight(), fontSize, name, Graphics.TEXT_JUSTIFY_CENTER|Graphics.TEXT_JUSTIFY_VCENTER);
        }
        
        function highlightDay(dc, localDate){
            // We use info() because we want to display the date in the user's
            // local time zone
            var dayOfWeekNumber = Time.Gregorian.info(localDate, Time.FORMAT_SHORT).day_of_week - 1; //week starts on Sunday, not Monday
            if (dayOfWeekNumber == 0) {
           		dayOfWeekNumber = 7;
           	}
            var dayOfWeekName = Time.Gregorian.info(localDate, Time.FORMAT_MEDIUM).day_of_week;
                 
            //calculate the width of the ellipse for the length and height of the name eg. "SUN"
            var width = dc.getTextWidthInPixels(dayOfWeekName, fontSize) + paddingWidth;
            var height = dc.getFontHeight(fontSize)+paddingHeight;
            
            //position the elipse in the middle of the screen
            var xPosition = dc.getWidth()/2 - width/2;
            //and the right number of days down
            var yPosition = dayOfWeekNumber * ySpacing * dc.getHeight() - height/2;
                    
            //draw it
            dc.drawRoundedRectangle(xPosition, yPosition, width, height, 3); 
        }

  • Great, thank you very much, now everything works nicely in the simulator.
  • No problem!

    I think my own code has a bug tho. highlightDay() should still be using Time.Gregorian.info. I'll edit my code above.

  • So I should be there - Time.Gregorian.info?
  • Yeah, I've changed highlightDay to use Time.Gregorian.info as before, and changed date to localDate for clarity.

        function highlightDay(dc, localDate){
            var dayOfWeekNumber = Time.Gregorian.info(localDate, Time.FORMAT_SHORT).day_of_week - 1; //week starts on Sunday, not Monday
            if (dayOfWeekNumber == 0) {
                dayOfWeekNumber = 7;
            }
            var dayOfWeekName = Time.Gregorian.info(localDate, Time.FORMAT_MEDIUM).day_of_week;

  • Thank you,
    
    now I'm adjusting the spaces between the day of the week and I need to make a position so that I can adjust the days on the screen (x, y).
  • Thanks for stepping in and correcting the bugs. I simply couldn't find the time to look at it.  Glad it's fixed now.