DS1302 clock calendar and WEEK NUMBER

Hi I building this project but I need the (week number ) to display on screen
..(RTC DS1302 on 16x2 LCD display I2C), this is clock, day, month,
and want to add the WEEK NUMBER and need the code for
WEEK NUMBER please help any suggestion I look around cant find any info.
please help, thanks

Can't you calculate that from the date?

1 Like

Also, week number seems like a not standard concept.

You will have to decide what week number even means.

Then use standard calendar algorithms to develop a day number into the year, plus an offset maybe (guessing) to get to the first Monday and divide by 7.

Algorithms for day of week and so forth are so old, maybe they were are old they never made it onto the internets.

But it would be worth a google.

  Zeller’s congruence

maybe.

a7

1 Like

What code are you using? In order for us to add to what you have, we need to know what you already have.

Please post your code inside code tags. Click on the </> symbol to get them.

1 Like

Do not think I've ever seen week number in any of the libraries, its likely you will need to calculate it yourself. Which week numbering system do you want to use, they differ on which day is the start of the week, and when week #1 begins in the year.

1 Like

this is the code I try to use Thanks to http://www.bajdi.com

 // http://www.bajdi.com
// Arduino digital clock
// Date and time shown on I2C LCD display
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib

#include <Wire.h>
#include "RTClib.h"
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);

RTC_DS1307 RTC;

void setup () {
    Wire.begin();
    RTC.begin();
    lcd.init(); // initialize the lcd
    lcd.backlight();
  }

void loop () {
    DateTime now = RTC.now();
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(now.year(), DEC);
    lcd.print('/');
    lcd.print(now.month(), DEC);
    lcd.print('/');
    lcd.print(now.day(), DEC);
    lcd.setCursor(0, 1);
    lcd.print(now.hour(), DEC);
    lcd.print(':');
    lcd.print(now.minute(), DEC);
    lcd.print(':');
    lcd.print(now.second(), DEC);
    delay(1000);
}

Hi thanks for your help
not on the libraries but I seen an Arduino with week number on display
but they do not show code
thanks

It's well established in ISO8601: week1 contains the year's first Thursday.

It may be written down, but that doesn't mean every organisation uses it or that it is the week number @javaox wants.

I have worked in organisations which use at least 2 different week numbering systems at the same time. The two systems are defined differently and the current week number in one system was always ahead of the other, but not always by the same difference. Both systems included week 53 in some years, but not generally in the same years. It was common to hear something like

"What were sales in week 47?"

"Which week 47?"

1 Like

The difficult part is determining when week #1 begins, after that calculating the week number within the year would be easy using the unix timestamp.

1 Like

Which is exactly why the ISO and their standards exist.

1 Like

By the way, OP, unless you have a compelling reason for using the 1302, like maybe you bought a container load, you will find life easier if you go for the newer I2C 1307 and even newer and better 3231.

1 Like

This function might be useful:

int ymdToWeekNumber (int y, int m, int d) {
  // reject out-of-range input
  if ((y < 1965)||(y > 2099)) return 0;
  if ((m < 1)||(m > 12)) return 0;
  if ((d < 1)||(d > 31)) return 0;
  // compute correction for year
  //     If Jan. 1 falls on: Mo Tu We Th Fr Sa Su
  // then the correction is:  0 +1 +2 +3 -3 -2 -1
  int corr = ((((y - 1965) * 5) / 4) % 7) - 3;
  // compute day of the year (in range 1-366)
  int doy = d;
  if (m > 1) doy += 31;
  if (m > 2) doy += (((y%4)==0) ? 29 : 28);
  if (m > 3) doy += 31;
  if (m > 4) doy += 30;
  if (m > 5) doy += 31;
  if (m > 6) doy += 30;
  if (m > 7) doy += 31;
  if (m > 8) doy += 31;
  if (m > 9) doy += 30;
  if (m > 10) doy += 31;
  if (m > 11) doy += 30;
  // compute corrected day number
  int cdn = corr + doy;
  // check for boundary conditions
  // if our calculation would give us "week 53",
  // we need to find out whether week 53 really exists,
  // or whether it is week 1 of the following year
  if (cdn > 364) {
    // check for year beginning on Thurs.
    if (corr==3) return 53;
    // check for leap year beginning on Wed.
    if (((y%4)==0) && (corr==2)) return 53;
    // otherwise, there is no week 53
    return 1;
  }
  // if our calculation would give us "week 0",
  // then go to the previous year
  // and find out whether we are in week 52 or week 53
  if (cdn < 1) {
    // first, compute correction for the previous year
    corr = ((((y - 1966) * 5) / 4) % 7) - 3;
    // then, compute day of year with respect to that same previous year
    doy = d + (((y%4)==1)?366:365);
    // finally, re-compute the corrected day number
    cdn = corr + doy;
  }
  // compute number of weeks, rounding up to nearest whole week
  return ((cdn + 6) / 7);
}

I know that that function is long and maybe ugly, but it's what I came up with.
Test here: P873cQ - Online C++ Compiler & Debugging Tool - Ideone.com

2 Likes

Nice. For what range of year numbers does this work?

My only observation is that you doing lotsa the same calculations that might be needed elsewhere… so I would have the week number thing using the functions or structure that already have figured out all the other data, or has been suggested use the epoch unix timestamp and cede trust to a widely used and presumably less likely to fail piece of software.

But it is fun to play with the problem. Probably something no two people new to the problem woukd code up in the same way.

a7

1 Like
  // reject out-of-range input
  if ((y < 1965)||(y > 2099)) return 0;

although (after posting I realized) there is a bug for the first few days of 1965, so the answer to your question should really be 1966 to 2099.

1 Like

Thanks I will tray this code

    lcd.print(now.year(), DEC);

What does this show you for the year number? Is it 2022, or just 22?

1 Like

I extended the range of my function. Now it handles dates from 1901 to 2099. I chose this range because, within this range, a leap year occurs exactly once every four years. (Outside this range, that simple leap year rule doesn't work. Google "Gregorian calendar" for more info.)

int ymdToWeekNumber (int y, int m, int d) {
  // reject out-of-range input
  if ((y < 1901)||(y > 2099)) return 0;
  if ((m < 1)||(m > 12)) return 0;
  if ((d < 1)||(d > 31)) return 0;
  // compute correction for year
  //     If Jan. 1 falls on: Mo Tu We Th Fr Sa Su
  // then the correction is:  0 +1 +2 +3 -3 -2 -1
  int corr = ((((y - 1881) * 5) / 4) % 7) - 3;
  // compute day of the year (in range 1-366)
  int doy = d;
  if (m > 1) doy += 31;
  if (m > 2) doy += (((y%4)==0) ? 29 : 28);
  if (m > 3) doy += 31;
  if (m > 4) doy += 30;
  if (m > 5) doy += 31;
  if (m > 6) doy += 30;
  if (m > 7) doy += 31;
  if (m > 8) doy += 31;
  if (m > 9) doy += 30;
  if (m > 10) doy += 31;
  if (m > 11) doy += 30;
  // compute corrected day number
  int cdn = corr + doy;
  // check for boundary conditions
  // if our calculation would give us "week 53",
  // we need to find out whether week 53 really exists,
  // or whether it is week 1 of the following year
  if (cdn > 364) {
    // check for year beginning on Thurs.
    if (corr==3) return 53;
    // check for leap year beginning on Wed.
    if (((y%4)==0) && (corr==2)) return 53;
    // otherwise, there is no week 53
    return 1;
  }
  // if our calculation would give us "week 0",
  // then go to the previous year
  // and find out whether we are in week 52 or week 53
  if (cdn < 1) {
    // first, compute correction for the previous year
    corr =  ((((y - 1882) * 5) / 4) % 7) - 3;
    // then, compute day of year with respect to that same previous year
    doy = d + (((y%4)==1)?366:365);
    // finally, re-compute the corrected day number
    cdn = corr + doy;
  }
  // compute number of weeks, rounding up to nearest whole week
  return ((cdn + 6) / 7);
}

Test here: dt1yNa - Online C++ Compiler & Debugging Tool - Ideone.com

1 Like

Haha, I'll take your word for it. Nice work.

That 400 year thing is always a complication, yeah. Calendar code can be a mess.

I approve of using online compilers to develop and perfect algorithms but it would be wise to use standard names for the specific integer sizes so you don't get surprised moving from the 32 bit ints you might find one place to the 16 bit ints on a different system. No energy to look hard and be sure you wouldn't be caught up by that in this case.

Also the long if thing doing the month correction might be shorter and look better with an array of 12 correction factors and a hack for leap year, no problem because the algorithm is basically one long miserable hack already (as they all seem to be…), or two arrays of 12 correction factors, one for leap and the other for not leap &c.

But who cares? Those are subtleties and once working the whole thing can be ignored. One would hope.

I note that weeks are numbered from 01. I wondered since many times things are numbered from 0 in C/C++.

The matter gives me a heads ache, and any time I do this stuff it makes me appreciate the sheer brilliance of a 360 day system with 5 or 6 days of unaccounted hard partying inserted to maintain synchrony with the Earth's orbit around the Sun. Well back then I guess the Sun might still have been moving around the Earth.

Of course these days that just wouldn't do, time being money and all.

a7

1 Like

I am trying to keep my numbers small enough to fit in a (signed) 16-bit int. According to my figuring, they do fit into a 16-bit int, but you are welcome to check, in case I made a mistake.

It would look better on the screen, maybe, but an array would use up the Arduino's precious RAM.
I wonder if a big switch statement, with the months in backward order and no breaks between them, would be more elegant. I'm not about to try, though, at least not right now.

Here is a version which is maybe easier to read, and which has full Gregorian leap year handling:

int ymdToWeekNumber (int y, int m, int d) {
  // reject out-of-range input
  if ((y < 1583)||(y > 25000)) return 0;
  if ((m < 1)||(m > 12)) return 0;
  if ((d < 1)||(d > 31)) return 0;
  // compute correction for year
  //     If Jan. 1 falls on: Mo Tu We Th Fr Sa Su
  // then the correction is:  0 +1 +2 +3 -3 -2 -1
  int corr = ((y + 2 + (y-1)/4 - (y-1)/100 + (y-1)/400) % 7) - 3;
  // compute day of the year (in range 1-366)
  int doy = d;
  if (m > 1) doy += 31;
  if (m > 2) doy += (((y%100) ? (y%4) : (y%400)) ? 28 : 29);
  if (m > 3) doy += 31;
  if (m > 4) doy += 30;
  if (m > 5) doy += 31;
  if (m > 6) doy += 30;
  if (m > 7) doy += 31;
  if (m > 8) doy += 31;
  if (m > 9) doy += 30;
  if (m > 10) doy += 31;
  if (m > 11) doy += 30;
  // compute corrected day number
  int cdn = corr + doy;
  // compute number of weeks, rounding up to nearest whole week
  // this gives us our week number
  int wknum = ((cdn + 6) / 7);
  // check for boundary conditions:
  // if our calculation would give us "week 0",
  // then it is really the final week of the previous year
  // and we need to find out whether that is week 52 or week 53
  if (wknum < 1) {
    // first, compute correction for the previous year
    corr = ((y + 1 + (y-2)/4 - (y-2)/100 + (y-2)/400) % 7) - 3;
    // then, compute day of year with respect to that same previous year
    doy = d + ((((y-1)%100) ? ((y-1)%4) : ((y-1)%400)) ? 365 : 366);
    // finally, re-compute the corrected day number and the week number
    cdn = corr + doy;
    wknum = ((cdn + 6) / 7);
    return wknum;
  }
  // if our calculation would give us "week 53",
  // we need to find out whether week 53 really exists,
  // or whether it is week 1 of the following year
  if (wknum > 52) {
    // check for year beginning on Thurs.
    if (corr==3) return 53;
    // check for leap year beginning on Wed.
    if (((y%4)==0) && (corr==2)) return 53;
    // otherwise, there is no week 53
    return 1;
  }
  return wknum;
}

Test page here: tY4iOy - Online C++ Compiler & Debugging Tool - Ideone.com

1 Like