# Arduino timer - convert millis() to days:hours:min

I’ve been trying to get a timer for my project that would convert millis() to days:hours:minutes:seconds. Here is what I did. It works well I think. I borrowed a little utility function to print colons and zeros from DateTime library/example.

Problems I see: I read arduino’s 1000 millis is not actually 1 second… so the long ints for day hour etc may have to be recalculated.

Another thing is the millis() rollover… how do we incorporate Faludi’s code into this? http://www.faludi.com/2007/12/18/arduino-millis-rollover-handling/
???

Let me know what you think, or if this has been done before hehe… and I just wasted 20 minutes of my life! ehh, it was fun so no biggie if that’s the case.

`````` long day = 86400000; // 86400000 milliseconds in a day
long hour = 3600000; // 3600000 milliseconds in an hour
long minute = 60000; // 60000 milliseconds in a minute
long second =  1000; // 1000 milliseconds in a second

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

void loop(){
time();
delay(1000);
}

void time(){
long timeNow = millis();

int days = timeNow / day ;                                //number of days
int hours = (timeNow % day) / hour;                       //the remainder from days division (in milliseconds) divided by hours, this gives the full hours
int minutes = ((timeNow % day) % hour) / minute ;         //and so on...
int seconds = (((timeNow % day) % hour) % minute) / second;

// digital clock display of current time
Serial.print(days,DEC);
printDigits(hours);
printDigits(minutes);
printDigits(seconds);
Serial.println();

}

void printDigits(byte digits){
// utility function for digital clock display: prints colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits,DEC);
}
``````

why do you think that 1000 millis is not actually a second?

FWIW, here is a version of your sketch implimented with the macros from DateTime.h. It uses a little less flash and RAM because it uses fewer variables.

``````// macros from DateTime.h
/* Useful Constants */
#define SECS_PER_MIN  (60UL)
#define SECS_PER_HOUR (3600UL)
#define SECS_PER_DAY  (SECS_PER_HOUR * 24L)

/* Useful Macros for getting elapsed time */
#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN)
#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN)
#define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR)
#define elapsedDays(_time_) ( _time_ / SECS_PER_DAY)

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

void loop(){
time(millis() / 1000);
delay(1000);
}

void time(long val){
int days = elapsedDays(val);
int hours = numberOfHours(val);
int minutes = numberOfMinutes(val);
int seconds = numberOfSeconds(val);

// digital clock display of current time
Serial.print(days,DEC);
printDigits(hours);
printDigits(minutes);
printDigits(seconds);
Serial.println();

}

void printDigits(byte digits){
// utility function for digital clock display: prints colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits,DEC);
}
``````
1 Like

Mem, awsome. How would you incorporate the rollover? does the rollover still take place since (I presume) we're using the clock cycles? it does rollover correct?

Yes, millis will rollover. If you want to avoid this, the easiest way is to use Datetime

``````#include <DateTime.h>

void setup(){
Serial.begin (57600);
DateTime.sync(0); // start the clock
}

void loop(){
time(DateTime.now());
delay(1000);
}

void time(long val){
int days = elapsedDays(val);
int hours = numberOfHours(val);
int minutes = numberOfMinutes(val);
int seconds = numberOfSeconds(val);

// digital clock display of current time
Serial.print(days,DEC);
printDigits(hours);
printDigits(minutes);
printDigits(seconds);
Serial.println();

}

void printDigits(byte digits){
// utility function for digital clock display: prints colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits,DEC);
}
``````

This won’t roll over until 2038

1 Like