Date calculation on Nextion HMI for a date picker or calendar applet
– part I

Image by freepik

While the work on the Nextion MEGA IO project goes on in the background, making our hyper efficient custom protocol fit for a future CAN bus use, a question or better a feature request for a calendar popped up in the Nextion forums.

My dear colleague Patrick gave an exhaustive answer, explaining why this can’t and won’t be a feature implemented into the Nextion HMI firmware, because of too many different calendars in the world, and too complex computations. I thought that it could be interesting to think about a “calendar light” version, though, with some limitations like only the Gregorian version, and also with a restricted range from January 1900 to December 2099. I started investigating and researching how this could be achieved.

How it can’t be done (on Nextion)

I started my research by browsing the available date and time libraries for C, C++, Java, Python, etc. And I found that Patrick was right. The computations in these libraries, although perfectly precise, bring every date/time object down to a Unix timestamp, a 32bit integer carrying the elapsed seconds since 1970-01-01. While this is a great approach to sort dates and to compute precisely the interval between two dates, it’s definitively oversized for our small Nextion HMIs.

Especially since we need neither hours, nor minutes, nor seconds for our monthly calendar view or date picker, there had to be another, simpler way. What we need for a given month and year, is just the weekday of the first day and the number of days in that specific month.

How it can be done on Nextion

I remembered that from time to time, a “genius” would appear in a quiz show in TV and tell you by heart the weekday for a given, arbitrary date. Thus, I decided to find out how to become such a genius. Perhaps not myself, but our Nextion HMIs. Doing more research, I found a (relatively) simple method to achieve what we need:

The number of the weekday is simply (YearCode + MonthCode + CenturyCode + DateNumber – LeapYearCode) mod 7

That sounds rather easy, but what are all these codes? Let’s look at them, one by one :

The Year Code

Since the century is handled by a separate code, we need only the last 2 digits of the year. For example for June 14, 1964, we keep only the 64. Then we apply another simple formula:

YearCode = (yy +(yy div 4)) mod 7

The div operator here stands for an integer division like the Nextion firmware does it always, discarding an eventual remainder. For example 25 div 4 = 6 because the remaining 1 will be discarded. For our example, 64 div 4 is 16. Which we add back to the 64 which makes 80. 80 mod 7 is 3.

The Month Code

There is no formula, it’s a lookup table :

  • January = 0
  • February = 3
  • March = 3
  • April = 6
  • May = 1
  • June = 4
  • July = 6
  • August = 2
  • September = 5
  • October = 0
  • November = 3
  • December = 5

Our genius will have to know it by heart. Our Nextion can use the often mentioned (in my blog projects) pseudo array to retrieve the Month code. For our example date (June) we’ll find a Month code of 4.

The Century Code

Easy to remember and easily implemented in code: for dates in 19xx, it’s 0, and for 20xx, it’s 6. Thus, we retain a century code of 0 for our example date.

The Leap Year Code

I think that it’s common knowledge that a year is a leap year when it can be divided by 4, unless it can also be divided by 100, but it is again a leap year if it can be divided by 400. In leap years, but only for the first two months, the leap year code is -1. In all other cases, it’s 0

The proof of work

For our example date, the formula is now (3 + 4 + 0 + 14 + 0) mod 7. You notice that although 1964 is definitively a leap year, the leap year code is 0. It’s because June is neither the first nor the second month of the year, and thus, the leap year correction does not apply. Finally, we find 21 mod 7 = 0. And using another simple lookup table

  • 0 = Sunday
  • 1 = Monday
  • 2 = Tuesday
  • 3 = Wednesday
  • 4 = Thursday
  • 5 = Friday
  • 6 = Saturday

… we understand that the author of these lines was born on a Sunday.

Implementing this on the Nextion HMI

… should now be pretty straightforward. And we’ll see this in detail in the next part of this blog. We’ll make a little more use of the modulo operator, so that we won’t have to calculate the weekday for every day of a month, but only for the first since all the following days will be consecutive.

Last, but not least

You have any questions, comments, critics, or suggestions? Just send me an email to thierry (at) itead (dot) cc! 🙂

And, by the way, if you like and you find useful what I write, and you are about to order Nextion stuff with Itead, please do so by clicking THIS REFERRAL LINK! To you, it won’t forcibly make a change for your order but on some products, you may even get a 10% discount using the coupon code THIERRYFRSONOFF. In ever case, it will pay me perhaps the one or the other beer or coffee. And that will motivate me to write still more interesting blogs 😉

Thank you for reading and happy Nextioning!