Result is negative number but must be positive

Hi Group,

I a writing a routine to calculate the Day Of Year number from the DATE .
But running the code it produces some unexpl. output. Here's the code

#include "Arduino.h"
#include <Streaming.h>  /* http://arduiniana.org/libraries/streaming/ */

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600); // opens serial port, sets data rate to 115200 bps
  Serial.println(__DATE__);
  Serial << "0-DOY : " << DayOfYear(__DATE__) << endl;
}

void loop() {
  // put your main code here, to run repeatedly:
}

int DayOfYear(char const *date) {
  char *strMonth = "TEST";
    int month, day, year;
    int doy = 0;
    static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
    sscanf(date, "%s %d %d", strMonth, &day, &year);
Serial << "1-Complete date: " << date << endl;
Serial << "2-This month: " << strMonth << endl;
Serial << "3-This day: " << day << endl;
Serial << "4-This year: " << year << endl;

    month = (strstr(month_names, strMonth)-month_names)/3+1;
Serial << "5-Days until month: " << month << endl;
    doy += month;
    doy += day;
Serial << "6-Day Of Year " << doy << endl;
    return doy;
}

It several debug results that produces the result:

Mar 20 2021
0-DOY : 1-Complete date: Mar 20 2021
2-This month: Mar
3-This day: 20
4-This year: 2021
5-Days until month: -90
6-Day Of Year -70
-70

0-doy (return value for today's number (70),should be the same as 6-Day Of Year but its not.
Did I missed something??

Harry

following worked on laptop after defining strMonth as a variable instead of a string

#include <iostream>
#include <string.h>

int DayOfYear(char const *date) {
    char strMonth [10];
    int month, day, year;
    int doy = 0;
    static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";

    sscanf(date, "%s %d %d", strMonth, &day, &year);

    std::cout << "1-Complete date: " << date << std::endl;

    std::cout << "2-This month: " << strMonth << std::endl;
    std::cout << "3-This day: " << day << std::endl;
    std::cout << "4-This year: " << year << std::endl;
    month = (strstr(month_names, strMonth)-month_names)/3+1;
    std::cout << "5-Days until month: " << month << std::endl;
    doy += month;
    doy += day;
    std::cout << "6-Day Of Year " << doy << std::endl;
    return doy;
}

int
main ()
{
    std::cout << __DATE__ << std::endl;

    DayOfYear (__DATE__);
}

Compiles here with many errors. Is this correct Arduino code??

the code i posted i ran on my laptop using gcc

This line is not legal in C++. It declares and initializes a pointer, but does not reserve memory for storing new data. In Arduino IDE preferences, turn on "show verbose" for compilation.

  char *strMonth = "TEST";
char* strMonth = "TEST";
char strMonth[] = "TEST";

Yes, once you fix that, your pointer manipulation will return a month number

month = (strstr(month_names, strMonth)-month_names)/3+1;

Then you are going to need to use that number as an index to pick up the cumulative days in the months preceding.

This will get you a little closer. You're still missing Leap Year calculations.

int DayOfYear(char const *date)
{
  char strMonth[10];
  int month, day, year;
  int daysBeforeMonth;
  int doy = 0;
  static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
  static const int DTM[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 305, 335, 366};
  sscanf(date, "%s %d %d", strMonth, &day, &year);
  Serial.print("1-Complete date: ");
  Serial.print(date);
  Serial.print('\n');
  Serial.print("2-This month: ");
  Serial.print(strMonth);
  Serial.print('\n');
  Serial.print("3-This day: ");
  Serial.print(day);
  Serial.print('\n');
  Serial.print("4-This year: ");
  Serial.print(year);
  Serial.print('\n');


  month = (strstr(month_names, strMonth) - month_names) / 3 + 1;
  Serial.print("5A-Month number: ");
  Serial.print(month);
  Serial.print('\n');


  daysBeforeMonth = DTM[month-1];
  ////// If month is greater than 2 (Feb), add 1 if Leap Year


  Serial.print("5B-Days before month: ");
  Serial.print(daysBeforeMonth);
  Serial.print('\n');
  
  doy = daysBeforeMonth + day;
  Serial.print("6-Day Of Year ");
  Serial.print(doy);
  Serial.print('\n');
  return doy;
}

Thanx, that worked. Added some lines to check the leapyear and here is the complete code

#include <Streaming.h>  /* http://arduiniana.org/libraries/streaming/ */

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600); // opens serial port, sets data rate to 115200 bps
  Serial << "Today's date " << (__DATE__) << endl;
  Serial << "Today's doy " << DayOfYear(__DATE__) << endl;
}

int DayOfYear(char const *date) {
//  char const *date = __DATE__;
  char strMonth[]= " ";
  int month, day, year;
  int DayOfYear = 0;
  static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
  int daysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  // Check if it is a leap year, this is confusing business
  // See: https://support.microsoft.com/en-us/kb/214019
  if (year % 4  == 0) {
    if (year % 100 != 0) {
      daysInMonth[1] = 29;
    }
    else {
      if (year % 400 == 0) {
        // The arrray at [0] so February would be in [1]
        daysInMonth[1] = 29;
      }
    }
  }
  sscanf(date, "%s %d %d", strMonth, &day, &year);
  month = (strstr(month_names, strMonth) - month_names) / 3 + 1;

  for (int i = 0; i < month - 1; i++) {
    DayOfYear += daysInMonth[i];
  }
  DayOfYear += day;

  return DayOfYear;
}

void loop() {
  // put your main code here, to run repeatedly:

}

I wil make a litle change for myself as I on;y use the DOY functio, going to call the sub with no arguments eg.

int DayOfYear(char const *date) {

becomes

int DayOfYear() {
  char const *date = __DATE__;

Again thanx for all the response

Harry

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