[SOLVED] How to check if a String contains a specific number

So I found a simple "oled calendar" code on github and I want to add a simple square to highlight the current date of the month but I don't know how to do it. I was thinking of maybe testing the Strings "week1", "week2", etc... if it contains the current date then it will supposedly output a true or false then from there plot it with x,y coordinate system. So my question is how to check or test if a String contains a specific number? Here's the simplified code from the github:

  int startDay = 0;
  String week1 ="";
  String week2 ="";
  String week3 ="";
  String week4 ="";
  String week5 ="";
  int newWeekStart = 0;
  int monthLength = 0;


void setup(){

 }

void loop(){
  if (now.month() == 1 || now.month() == 3 || now.month() == 5 || now.month() == 7 || now.month() == 8 || now.month() == 10 || now.month() == 12){
    monthLength = 31;
  }
  else {monthLength = 30;}
  if(now.month() == 2){monthLength = 28;}
  startDay = startDayOfWeek(now.year(),now.month(),1);

  switch (startDay){
    case 0:
      // Sunday
      week1 = " 1  2  3  4  5  6  7";
      break;
    case 1:
      // Monday
      week1 = "    1  2  3  4  5  6";
      break;      
     case 2:
      // Tuesday
      week1 = "       1  2  3  4  5";
      break;           
     case 3:
      // Wednesday
      week1 = "          1  2  3  4";
      break;  
     case 4:
      // Thursday
      week1 = "             1  2  3";
      break; 
     case 5:
      // Friday
      if(monthLength == 28 || monthLength == 30){week1 = "                1  2";}      
      if(monthLength == 31){week1 = "31              1  2";}      
      break; 
     case 6:
      // Saturday
      if(monthLength == 28){week1 = "                   1";}
      if(monthLength == 30){week1 = "30                 1";}      
      if(monthLength == 31){week1 = "30 31              1";}       
      
      break;           
  } // end first week
  newWeekStart = (7-startDay)+1;
  const char* newWeek1 = (const char*) week1.c_str();  

  Serial.print(newWeek1);

 }
  
   String s("1/18/2022");
   // Find occurrence of "18" in the date
   if (s.indexOf("18") != -1)
   {
      //found it!!!
   }

I think you want to look for "/18/", otherwise the 20th and 22nd of the month will be a problem and days less than 13 will be a problem on certain months.

  String lookFor = "/" + String(day) + "/";
  if (s.indexOf(lookFor) != -1)
  {
      //found it!!!
   }
1 Like

haven't tested all the suggestions yet, but the String has contents like this:
week1: " 1 2 3 4 5 6"
week2: "7 8 9 10 11 12 13"

and I want to test these week1 and week2 and so on....

so I'm thinking maybe it won't affect the final output that much, but then again I haven't tested the code yet

Not sure what you mean. I agree that it should be "/18/" since OP specifically wants the day of the month and not, e.g., to detect "2018" but I don't see how the 20th or 22nd would be a problem.

The value from startDayOfWeek is enough to give you the offset into the calendar for calculating the x-y coordinate for any day of the month.

This is an excellent example of an XY problem. (What is an XY problem? See: https://xyproblem.info/ )

You don't need to test any strings. You just need to know where in the grid a specific date will be located.
To begin, suppose that today is the 1st day of the month. Then today's date will, naturally, appear in the row for week1, in the position (0 to 6) given by startDay.
OK, so we've just solved our problem for the 1st day of the month. What if it is the 2nd day of the month? We just start with startDay, and move forward 1 position. If this moves us off the end of the row, then we have to start again at the beginning of the next row.
For the 3rd day of the month, we have to move forward one more position, so we will be 2 positions past startDay. And so forth, for the remaining days of the month. In general, on day N, we will be N-1 positions past 'startDay'. In code, that would look something like this:

int rowNumber = 1; // rows are numbered 1 to 5
int colNumber = startDay; // columns are numbered 0 to 6
colNumber += (now.day() - 1); // advance the column by the appropriate number of days
while (colNumber > 6) { // check if we are past the end of the row
  colNumber -= 7; // move backwards 7 columns
  rowNumber++; // advance to the next row
}
if (rowNumber > 5) {
  rowNumber = 1;
}

Is there a "20" in "1/18/2022"? Yes, all this century.
Is there a "22" in "1/18/2022"? Yes, all this year.
Is there an "8" in "1/18/2022"? Yes, on the 8th, 18th, and 28th and all of August.

1 Like

from what I can interpret that "startDayOfWeek" or "startDay" only contains the first day of the month, what if it's currently the 20th? then the program doesn't have a reference of what's the current week. Am I right? I'm planning to use "week1", "week2", ........ as a reference for y-coordinate

startDayOfWeek gives you a number from 0 through 6 that is the day of the week for the first day of the month.

( startDayOfWeek + ( day of month - 1) ) % 7 will give you the day of the week for any day in the month.

( startDayOfWeek + ( day of month - 1 ) / 7 done as integer math will give you which line of the calendar the day is on.

1 Like

You're missing a ).

If it is currently the 20th day of the month, then the program will count forward 19 positions from startDay. Please look again at my code. Do you know what this line does? Do you know what now.day() means?

colNumber += (now.day() - 1); // advance the column by the appropriate number of days

I'm so sorry about that, I'm so fixated on my idea of doing it when there's easy or more simple way of doing it. Thank you, that code is working. Can you please explain again how your code works?

To understand how my code works, let's look a little ahead, to the beginning of February 2022.
Here is the calendar for February 2022.

Column# 0  1  2  3  4  5  6
       Su Mo Tu We Th Fr Sa
Row 1         1  2  3  4  5
Row 2   6  7  8  9 10 11 12
Row 3  13 14 15 16 17 18 19
Row 4  20 21 22 23 24 25 26
Row 5  27 28

First, let us look at February 1, 2022. Look at the calendar, and find February 1 on the calendar.
Now look at this line of code (from the original program).

startDay = startDayOfWeek(now.year(),now.month(),1); // Sunday's value is 0

That line calculates the day of the week for the first day of the month, and sets startDay to the result (a number from 0 to 6).
For February 2022, the first day is a Tuesday, so startDay will be 2.

Now, look at these two lines I wrote:

int rowNumber = 1; // rows are numbered 1 to 5
int colNumber = startDay; // columns are numbered 0 to 6

You see, for the first day of the month, that is all we need. We are done.

"But," you ask, "what about the rest of the month?"
All right, let's get started on the rest of the month.

What about February 2 ?
Look at the calendar, and find February 2 in the calendar.
Now, look again at those two lines of code:

int rowNumber = 1; // rows are numbered 1 to 5
int colNumber = startDay; // columns are numbered 0 to 6

For February 2, the correct rowNumber is still 1, so that's fine. But, what about the colNumber?
From looking at our calendar, we see that the colNumber value we need for February 2 is 3. But, our code doesn't set colNumber to 3. It sets it to 2. (Remember, for the entire month of February 2022, startDay is 2.) How do we fix this?

if (now.day() == 2) {
  // this fixes the column number for the 2nd day of the month
  colNumber = colNumber + 1;
}

That takes care of February 2.

Now, what about February 3 ?
Look again at the calendar grid, and find February 3.
Then, look again at my code:

int rowNumber = 1; // rows are numbered 1 to 5
int colNumber = startDay; // columns are numbered 0 to 6

OK, so rowNumber is 1, which is fine.
But, colNumber is not fine. It gets set to 2. But, from looking at our calendar grid, we see that we need it to be 4. How do we fix this?

if (now.day() == 3) {
  // this fixes the column number for the 3rd day of the month
  colNumber = colNumber + 2;
}

That takes care of February 3.

Now, what about February 4 ?
For February 4, the fix is:

if (now.day() == 4) {
  // this fixes the column number for the 4th day of the month
  colNumber = colNumber + 3;
}

Do you understand why this fix works for February 4 ?

To recap, we have:

if (now.day() == 2) {
  // this fixes the column number for the 2nd day of the month
  colNumber = colNumber + 1;
}
if (now.day() == 3) {
  // this fixes the column number for the 3rd day of the month
  colNumber = colNumber + 2;
}
if (now.day() == 4) {
  // this fixes the column number for the 4th day of the month
  colNumber = colNumber + 3;
}

Looking at this, we see a pattern.
The code for each day looks like this:

if (now.day() == [[number]] ) {
  // this fixes the column number for the [[number]] day of the month
  colNumber = colNumber + [[one less than the number]];
}

So, we can get rid of all of those ifs, and write this instead:

colNumber = colNumber + (now.day() - 1); // fix column number for day of month

or even just this:

colNumber += (now.day() - 1); // fix column number for day of month

and have a solution that will work for any day of the month, like so:

int rowNumber = 1; // rows are numbered 1 to 5
int colNumber = startDay; // columns are numbered 0 to 6
colNumber += (now.day() - 1); // fix column number for day of month

As it turns out, our solution doesn't work for every day of the month. The reason is, of course, that we run out of columns. We have a fix for that, too:

if (colNumber == 7) {
  // first position past the end of the row
  // so we go to the beginning of the next row
  colNumber = 0;
  rowNumber++;
}

if (colNumber == 8) {
  // second position past the end of the row
  // so we go to the second position (column 1) of the next row
  colNumber = 1;
  rowNumber++;
}

if (colNumber == 9) {
  // third position past the end of the row
  // so we go to the third position (column 2) of the next row
  colNumber = 2;
  rowNumber++;
}

Or, we can just type:

while (colNumber > 6) { // check if we are past the end of the row
  colNumber -= 7; // move backwards 7 columns
  rowNumber++; // advance to the next row
}

We have to be careful of moving off the end of the grid (possible in some months with 30 or 31 days). So, we take care of that like this:

if (rowNumber > 5) {
  rowNumber = 1;
}

And we're done!

1 Like

You ask:

what if it's currently the 20th? then the program doesn't have a reference of what's the current week. Am I right?

The program calculates which week is the current week.

Here is a calendar.

Calendar for January 2022

Column# 0  1  2  3  4  5  6
       Su Mo Tu We Th Fr Sa
Row 1  30 31              1
Row 2   2  3  4  5  6  7  8
Row 3   9 10 11 12 13 14 15
Row 4  16 17 18 19 20 21 22
Row 5  23 24 25 26 27 28 29

Let's calculate the position of January 20 in that calendar.

int rowNumber = 1; // rows are numbered 1 to 5
int colNumber = startDay; // columns are numbered 0 to 6

Here, rowNumber is of course 1.
colNumber is 6 (because startDay is 6, because Jan. 1 is a Saturday).

colNumber += (now.day() - 1); // advance the column by the appropriate number of days

For January 20, now.day() is 20.
Therefore, (now.day() - 1) is 19, and thus colNumber gets increased by 19.
colNumber, which previously was 6, thus becomes 25 (because 6+19=25).

while (colNumber > 6) { // check if we are past the end of the row
  colNumber -= 7; // move backwards 7 columns
  rowNumber++; // advance to the next row
}

colNumber is greater than 6 (it is 25), so it gets reduced by 7 (to 18), and rowNumber gets increased by 1 (to 2).
Then we do that again, because it's a while loop, and colNumber is still greater than 6.

colNumber gets reduced by 7 (to 11), and rowNumber gets increased by 1 (to 3).
Then we do that again, because it's a while loop, and colNumber is still greater than 6.

colNumber gets reduced by 7 (to 4), and rowNumber gets increased by 1 (to 4).
Now colNumber is no longer greater than 6, so we have escaped the while loop.

The result: January 20 is in row 4, column 4.

1 Like

Thanks for the answers guys, it really helped me a lot! All these suggestions worked with what I was trying to do!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.