Create dates

Hello, i am new here and i want to know how i can create a date format (dd/mm/yy hh:mm:ss), without any external hardware, just programming the dates in the serial monitor.

I saw this (Arduino Playground - HomePage) but i dont know how i can use this...
Thanks

Change start times as needed, change : to / in the serial prints at the end.

unsigned long currentMicros;
unsigned long previousMicros;
unsigned long elapsedTime;
// Initial time to start, 10:00:00 with 90 years, 240 days. (around start of May),
// adjust as needed.
// Get this working, then more display code if needed
byte hundredths;
byte tenths;
byte secondsOnes = 0;
byte oldsecondsOnes;
byte secondsTens = 0;
byte minutesOnes = 0;
byte minutesTens = 0;
byte hoursOnes= 0;
byte hoursTens = 1;
int days = 240; //
byte years = 90;

void setup(){
Serial.begin(115200); // make serial monitor match
Serial.println (Setup Done");
}
void loop(){
currentMicros = micros();
// how long's it been?
elapsedTime = currentMicros - previousMicros;
if ( elapsedTime >=10000UL){  // 0.01 second passed? Update the timers
previousMicros  = previousMicros + 10000UL;
hundredths = hundredths+1;
if (hundredths == 10){
    hundredths = 0;
    tenths = tenths +1;
    if (tenths == 10){
        tenths = 0;
        secondsOnes = secondsOnes + 1;
        if (secondsOnes == 10){
            secondsOnes = 0;
            secondsTens = secondsTens +1;
            if (secondsTens == 6){ 
                secondsTens = 0;
                minutesOnes =  minutesOnes + 1;
                if (minutesOnes == 10){
                    minutesOnes = 0;
                    minutesTens = minutesTens +1;
                    if (minutesTens == 6){
                        minutesTens = 0;
                        hoursOnes = hoursOns + 1;
                          if (hoursOnes == 10){
                              hoursOnes = 0;
                              hoursTens = hoursTens +1;
                                if ( (hoursTens == 2) && (hoursOnes == 4){
                                      hoursOnes = 0;
                                      hoursTens = 0;
                                      if (days>1){
                                          days = days-1;
                                           }
                                      else {
                                         days = 365;
                                         years = years - 1;
                                         }
                                    
                                      } // 24 hr rollover check
                                   } //hoursTens rollover check
                              } // hoursOnes rollover check
                        } // minutesTens rollover check
                     } // minutesOnes rollover check
                 } // secondsTens rollover check
              } // secondsOnes rollover check
          } // tenths rollover check
       } // hundredths rollover check
} // hundredths passing check

if (oldSecondsOnes != secondsOnes){  // show the elapsed time
oldSecondsOnes = secondsOnes;
Serial.print (years);
Serial.print(":");
Serial.print(days);
Serial.print(":");
Serial.print(hoursTens);
Serial.print(hoursOnes);
Serial.print(":");
Serial.print(minutesTens);
Serial.print(minutesOnes);
Serial.print(":");
Serial.print(secondsTens);
Serial.println(secondsOnes);

} // end one second check

} // end loop

i got the error message: missing terminating" character.

Thanks

Actually it is missing a starting " character. Add it, it should not be hard to find the right location. :wink:

If you want to deal with dates, you might want a function to calculate the number of days in a month, like the one I posted here: using arduino at the end of each month - #12 by odometer - Programming Questions - Arduino Forum

You could also do this.

I had made a calendar class for my TFT_Extras library (TFT_Clocks to be exact). And all I did here was just copy that code then modify it to have AM or PM.

You also might be able to find a smaller code elsewhere online or within the forum.

unsigned long oldTime = millis();

int days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const char *months[] = { "ERR", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };

char Date[30]; // string buffer
unsigned int Cy; // years
byte Cm; // months
byte Cd; // days
unsigned long clock = 0; // variable to keep track of time in seconds

#define PM false
#define AM true

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  SetDate(1,1,2015); // January 1, 2015
  SetTime(11, 59, 50, AM); // ...
}

void loop()
{
  static byte s, m, h, ampm;

  if (millis() - oldTime >= 1000) // update every second
  {
    oldTime += 1000;
    s = clock % 60; // extract seconds from clock variable
    m = (clock / 60) % 60; // extract minutes
    h = clock / 3600; // extract hours
    if (h == 0) // check for flip
      h = 12;
      
    if (h > 12) // military time converter
      h -= 12;
    
    // possibly overkill with sprintf()
    sprintf(Date, "%s/%02d/%d %02d:%02d:%02d %s", months[Cm], Cd, Cy, h, m, s, (clock > 43199 ? "PM" : "AM"));
    Serial.println(Date); // show the date + time
    clock++; // increment clock
  }

  if (clock >= 86400) // Next day?
  {
    Calendar( &Cy, &Cm, &Cd); // day increments every time this function is called
    clock = 0; // reset time
  }
}

void Calendar( unsigned int *Y, byte *M, byte *D)
{
  if (*D < (days_in_month[*M] + Leapyear(*M, *Y)) )
    *D += 1;
  else
  {
    *D = 1;

    if (*M < 12)
      *M += 1;
    else
    {
      *M = 1;
      *Y += 1;
    }
  }
} //End of Calendar Funct

byte Leapyear(byte month, unsigned long year) // gotten from online 
{
  if (month == 2) // February?
    return ( ( (((year) % 4) == 0) && (((year) % 100) != 0) ) || (((year) % 400) == 0) );

  return 0;
}

void SetTime(unsigned long hours, unsigned long minutes, unsigned long seconds, bool am_pm)
{
  // This handles invalid time overflow ie 1(H), 0(M), 120(S) -> 1h, 2m, 0s
  unsigned int S = (seconds / 60), M = (minutes / 60), H;

  if (hours == 0)
    H = 12;

  if (hours > 12)
    H = hours - 12;

  if (S)
    minutes += S;

  if (M)
    hours += M;

  clock = (hours * 3600) + (minutes * 60) + (seconds % 60);

  if ((hours > 12) || am_pm == false) // if AM = true, PM = false
    clock += 43200;
}

void SetDate(byte m, byte d, int y)
{
  Cm = m;
  Cd = d;
  Cy = y; 
}

HazardsMind:
I had made a calendar class for my TFT_Extras library (TFT_Clocks to be exact). And all I did here was just copy that code then modify it to have AM or PM.

Why bother with AM and PM?

  if (millis() - oldTime >= 1000) // update every second

{
    oldTime = millis();

Better would be:

  if (millis() - oldTime >= 1000) // update every second
  {
    oldTime += 1000;

That way, even if something in the loop takes a few milliseconds (or even a few hundred milliseconds) to execute, it will not throw off your timekeeping.

Other than that, your code looks OK to me.

Fixed: oldTime += 1000;

Why bother with AM and PM?

Because at which 12th hour does the date change?

HazardsMind:
Because at which 12th hour does the date change?

It doesn't.

A day has 24 hours, which are numbered sequentially from 0 to 23.
The date changes at the moment when hour 23 ends and hour 0 (of the following day) begins.

-_- On a non-military clock.

On a standard clock you have 12 noon and 12 midnight, when does the date change?

HazardsMind:
-_- On a non-military clock.

On a standard clock you have 12 noon and 12 midnight, when does the date change?

Mᴜʀʀɪᴄᴀ!

lukx31:
Hello, i am new here and i want to know how i can create a date format (dd/mm/yy hh:mm:ss), without any external hardware, just programming the dates in the serial monitor.

Are you sure?

Modern Arduino boards just use a "16 MHz ceramic resonator" to keep their frequency, which is accurate up to 5000 ppm only.

So if you'd create a clock just from the Arduino clock frequency, the inaccuracy may be 5000 seconds within 1 Million seconds, which would be an inaccuracy of 432 seconds per day.

Would 432 seconds per day of inaccuracy be acceptable for your application?

I haven't seen that kind of drift running my code with a crystal equipped Duemilanove or an oscillator equipped Uno.
I tracked it against the official US time clock at http://www.time.gov/

CrossRoads:
I haven't seen that kind of drift running my code with a crystal equipped Duemilanove or an oscillator equipped Uno.

That's correct.

Old Arduino boards like Duemilanove (year 2009) had crystal oscillators which are much more accurate than ceramic resonators as used with newer boards such as the "R3" designs.

With a board that creates the 16 MHz Atmega clock from a "crystal oscillator" you can expect an accuracy of perhaps 80 ppm, that is 80 seconds in 1 million seconds, or about 7 seconds per day.

Crystal oscillators are MUCH MORE ACCURATE than the ceramic resonators used in newer R3 board designs.

As user ' lukx31' is new here, I suppose he is using a newer board in R3 design and not an old Duemilanove board from 2009. So his Arduino board will most likely have the inaccurate clocking with a ceramic resonator and not an accurate clocking with a crystal oscillator.

Sorry, I meant to say resonator equipped Uno.

CrossRoads:
Sorry, I meant to say resonator equipped Uno.

Actual results may vary.

5000 ppm for ceramic resonators and 80 ppm for crystal oscillators are somewhat "worst case" inaccuracy.

So if you think it might make sense what the thread starter requested, here is some code for a clock without using any additional clock hardware and setting by using the serial monitor:

struct sTime // structure for holding a date and a time
{
  int  iYear;
  byte bMonth;
  byte bDay;
  byte bHour;
  byte bMinute;
  byte bSecond;
};

sTime dateTime; // variable to hold a full date/time struct

byte daysInMonth(int year, byte month)
{
  if (month == 4 || month == 6 || month == 9 || month == 11)  
    return 30;  
  else if (month == 2)  
  {
    bool isLeapYear = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);  
    if (isLeapYear) return 29;
    else return 28;
  }  
  else return 31;
}

void updateTime()
{
  static unsigned long lastUpdate;
  if (millis()-lastUpdate>=1000)
  {
    lastUpdate+=1000;
    dateTime.bSecond++;
    if (dateTime.bSecond>=60) {dateTime.bSecond=0; dateTime.bMinute++;}
    if (dateTime.bMinute>=60) {dateTime.bMinute=0; dateTime.bHour++;}
    if (dateTime.bHour>=24) {dateTime.bHour=0; dateTime.bDay++;}
    if (dateTime.bDay>daysInMonth(dateTime.iYear, dateTime.bMonth)) {dateTime.bDay=1; dateTime.bMonth++;}
    if (dateTime.bMonth>12) {dateTime.bMonth=1; dateTime.iYear++;}
  }
}

void serialTimeSetting()
{
  if (Serial.available()==0) return;
  delay(50);
  char str[64];
  memset(str,0,sizeof(str));
  int i=0;
  while (Serial.available()) 
  {
    char c=Serial.read();
    if (c>='0' && c<='9')
    {
      str[i]=c;
      i++;
    }
  }
  if (strlen(str)==8) // yyyymmmdd  8 characters ==> set date, i.e. 20150826
    sscanf(str,"%04d%02d%02d",&dateTime.iYear, &dateTime.bMonth, &dateTime.bDay);
  else if (strlen(str)==6) // HHMMSS 6 characters => set time, i.e. 21:49:00
    sscanf(str,"%02d%02d%02d",&dateTime.bHour, &dateTime.bMinute, &dateTime.bSecond);
  else if (strlen(str)==4) // HHMM 4 characters => set time, i.e. 21:49
  {
    sscanf(str,"%02d%02d", &dateTime.bHour, &dateTime.bMinute);
    dateTime.bSecond=0;
  }
}


void setup() {
  Serial.begin(9600);
}

#define INTERVAL 1000

byte lastSecondPrinted;

void loop() {
  serialTimeSetting();
  updateTime();
  if (lastSecondPrinted != dateTime.bSecond)
  {
    lastSecondPrinted = dateTime.bSecond;
    char buf[41];
    snprintf(buf,sizeof(buf),"%02d/%02d/%04d  %02d:%02d:%02d", dateTime.bDay, dateTime.bMonth, dateTime.iYear, dateTime.bHour, dateTime.bMinute, dateTime.bSecond);
    Serial.println(buf);
  }
}

The serial clock setting works like that:
Enter 8 numeric digits for entering date in format yyyymmdd, i.e. 20150826
Enter 6 numeric digits for entering time in format HHMMSS, i.e. enter 234533 for 23:45:33
Enter 4 numeric digits for entering time in format HHMM, i.e. enter 2345 for 23:45:00

Serial monitor setting is 9600 baud and line ending "Carriage Return" or "both".

Time and date will reset to zero and needs setting after power-on and after each reset of the controller.

Use at your own risk!