Years, Months, Days from date in past: YY/MM/DD

Hello fiends. I want to make a gift to my wife on 14th February and I have troubles with my project.
Oh, forgot to tell you that I'm begginer and I'm trying to calculate how many years, months and days we are together and show it on 7seg displays.

I cuted sodes from different projects and now I can show on LCD difference this difference, but I forgot about leap years. Can anyone help me to upgrate my code?

I test in proteus, and I ordered PCB yesterday. I very want to finish within 2 months. :sob:

#include <Wire.h>    //Libraries to communicate with RTC
#include "RTClib.h"

RTC_DS1307 rtc;      //create rtc object

int segs[] = {0, 1, 2, 3, 4, 5, 6, 7};//abcdefg. segments
int digits[] = {12, 13, 10, 11, 8, 9};        //number of digits
String num[]  = {"00000011", //0
                 "10011111", //1
                 "00100101", //2
                 "00001101", //3
                 "10011001", //4
                 "01001001", //5
                 "01000001", //6
                 "00011111", //7
                 "00000001", //8
                 "00001001"  //9
                };

DateTime dtBegin (2010, 6, 27, 0, 0, 0); //!!!! adjust time here!!!!!

TimeSpan Timepassed;



int Dayspassed, Yearpassed, Monthpassed, DaysTotal;

void setup()
{
  rtc.begin();//begin rtc communication
  for (int i = 0; i < 8; i++)
  {
    pinMode(segs[i], OUTPUT);//set segment pins output
  }
  for (int i = 0; i < 6; i++)
  {
    pinMode(digits[i], OUTPUT);//set digts as outputs

  }

}


void loop()
{


  DateTime nowTime = rtc.now();
  Timepassed = nowTime - dtBegin;
  DaysTotal = Timepassed.days();
  Yearpassed = DaysTotal / 365;
  Monthpassed = (DaysTotal - Yearpassed * 365) / 31;
  Dayspassed = DaysTotal - Monthpassed *  31 - Yearpassed * 365;
  printTime(Dayspassed, Monthpassed, Yearpassed);

}



void printNum(int number)//function to print number
{
  for (int i = 0; i < 8; i++)
  {
    //if (state == true && state1 == true) //if date is displayed show decimal after day
    //    {
    //      num[number].setCharAt(7, '1');
    //    }
    //    //if (state != true || state1 != true) //if not then no decimal
    //    {
    //      num[number].setCharAt(7, '0');
    //    }

    if (num[number].charAt(i) == '1')//set segment high
    {
      digitalWrite(segs[i], HIGH);
    }
    else
    {
      digitalWrite(segs[i], LOW);//set low
    }
  }
}
void printTime(int day, int month, int year)
{
  int d[] = {floor(day / 10), day - 10 * floor(day / 10), floor(month / 10), month - 10 * floor(month / 10), floor(year / 10), year - 10 * floor(year / 10)};

  for (int i = 0; i < 6; i++)
  {
    if (i != 0)
    {
      digitalWrite(digits[i - 1], LOW);
    }
    if (i == 0)
    {
      digitalWrite(digits[5], LOW);
    }
    if (i == 1)
    {
      //  state = true;
    }
    else
    {
      // state = false;
    }

    digitalWrite(digits[i], HIGH);
    printNum(d[i]);
    delay(5);
  }
}

I found this topic on same library, may be it can help me?

#include "RTClib.h"
RTC_DS3231 rtc; // Using DS3231 Real Time Clock 
DateTime now = rtc.now(); // Current Date and Time
DateTime dob = DateTime(1984,8,16,0,0,0); // Date of Birth (1984.08.16 00:00:00)
 
int t0 = dob.year() * 12 + dob.month() - 1;
int t = now.year() * 12 + now.month() - 1;
int dm = t - t0;
int Y;
int M;
int D;
 
//Calculate age in Y/M/D
if(now.day() >= dob.day()){
  Y = floor(dm/12);
  M = dm % 12;
  D = now.day() - dob.day();
}
else {
  dm--;
  t--;
  Y = floor(dm/12);
  M = dm % 12;
  DateTime tmp = DateTime(floor(t/12),(t%12)+1,dob.day(),0,0,0);
  D = (now.unixtime() - tmp.unixtime())/60/60/24;
}

14th_February.ino (2.46 KB)

I presume if you are planning to present this gift in Feb 2020 that you won't need to count very far back. You could work out with a spreadsheet how many days there will have been at 14 Feb and start with that number. Then, assuming you want the thing to keep counting in future years it just needs to increment by 1 every day and you can make it adjust for a leap year in 2020 and every 4 years after that. There would be no need to figure out leap years in times past.

...R

Maybe this will help.

/*************************************************************************
* Title: Date Difference Calculator
* File: gDay.c
* Author: James Eli
* Date: 10/19/2017
*
* Determine difference between two days, measured in days.
*
* Notes:
*  (1) Algorithm found here: https://alcor.concordia.ca/~gpkatch/gdate-algorithm.html
*  (2) Compiled with MS Visual Studio 2017 Community (v141), using C
*      language options.
*************************************************************************
* Change Log:
*   10/19/2017: Initial release. JME
*************************************************************************/
#include <stdbool.h>

// Definitions.
#define MIN_YEAR 1582 // Start of gregorian calendar. 
#define MAX_YEAR 2500 // Maximum end date (arbitrary).

// Leap year validator.
// Logic: if year is divisible by 4, then its a leap year. But,
// if that year is divisible by 100, then its not a leap year. However, 
// if the year is also divisible by 400, then its a leap year.
static inline bool isLeapYear(const unsigned int year) 
{
	return ((!(year % 4U) && (year % 100U)) || !(year % 400U));
}

// Determine last day of month.
unsigned int lastDayOfMonth(const int y, const unsigned int m) 
{
	static const unsigned int eom[13] = { 0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U };
	return m != 2U || !isLeapYear(y) ? eom[m] : 29U;
}

// For algorithm, zero day is March 1, year 0. Note: this year 0 is NOT Gregorian 
// year 0, it is a reference date only. However, calculations involving dates 
// after the establishment of the Gregorian calendar will be correct. Therefore, 
// start = dayCount(1582, 10, 1); WARNING: Dates before Oct, 1582 are inaccurate!
long gDay(const int year, const unsigned int month, const unsigned int day) 
{
	long y, m;

	m = (month + 9U) % 12U; // Mar = 0, Feb = 11
	y = year - m / 10U;     // If Jan or Feb, year--
	return 365U * y + y / 4U - y / 100U + y / 400U + (m * 306U + 5U) / 10U + (day - 1U);
}

Pavels:
... but I forgot about leap years. Can anyone help me to upgrate my code?

If you have to be precise according to Gregorian calendar, do not use any complex calculations usually involve fractions as 365.2425 per Julian year...

Actually this have nothing to do with leap years - one year is one year!

Only do simple subtraction and addition:

  • Subtract starting from first date until end of that year in months and days
  • Then subtract last and first year
  • Add remaining months and days.
  • If days >= 29 it is actually arbitrary and up to you to decide how many days will be one month. Actually, you may consider only first and last year of the dates are leap or not for adjustment.

Rest is trivial. :wink: