# Converting milliseconds to time

I am trying to convert millis to HRS:MINS:SECS as in 01:12:34.

I was lead to the DateTime Library which requires the Wiring Library.

These are very old Libraries and my searches have been fruitless for a substitute.

Can anyone give me a direction to go so I can use a newer Library or any other suggestions.

Thanks

I am trying to convert millis to HRS:MINS:SECS as in 01:12:34.

Convert to seconds: millis() divided by 1000
Convert to hours: seconds / 3600
etc

Yes I do understand that, I'm just really having a tough time making either a count up or count down clock or timer with HRS:MINS:SECS that takes roll over into account.

Thanks

So, just keep track of seconds, and derive everything from that - no need to worry about rollover.
Have a look at the blink without delay example in the IDE for clues.

technogeekca:
I am trying to convert millis to HRS:MINS:SECS as in 01:12:34.

I was lead to the DateTime Library which requires the Wiring Library.

These are very old Libraries and my searches have been fruitless for a substitute.

Can anyone give me a direction to go so I can use a newer Library or any other suggestions.

You don't need any library to do simple date and time calculations.

Here is a small example sketch to show millis() since last reset in hh:mm:ss format.
Upload code and open serial monitor at 9600 Baud and watch!

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

}

void loop() {
unsigned long runMillis= millis();
unsigned long allSeconds=millis()/1000;
int runHours= allSeconds/3600;
int secsRemaining=allSeconds%3600;
int runMinutes=secsRemaining/60;
int runSeconds=secsRemaining%60;

char buf[21];
sprintf(buf,"Runtime%02d:%02d:%02d",runHours,runMinutes,runSeconds);
Serial.println(buf);
delay(1000);
``````

Why are you wanting to take rollovers into account?

Is your application running more than 50 days uninterrupted?

In case yes: DO NOT USE MILLIS, COUNT SECONDS instead!

You can break down millis() into a seconds counter which is NOT affected by rollovers after about 50 days.
Please feel free to ak in case you don't know how to do it.

And be warned: Internal time counting using the on-board oscillator/or ceramic resonator as a clocking source may be wrong up to 0.8%.

So counting 1000 seconds with internal timing might be something between 992 and 1008 seconds, actually!

Is that OK for you? Or do you need more accurate timing?

In case you need accurate timing, use an RTC module for clocking, preferably a high-precision clock module like DS3231.

``````if(millis() >= next_millis) {
next_millis += 1000;
time++;

seconds = time;

sec = seconds % SECONDS_PER_MINUTE;		seconds /= SECONDS_PER_MINUTE;
min = seconds % MINUTES_PER_HOUR;		seconds /= MINUTES_PER_HOUR;
hrs = seconds % HOURS_PER_DAY			seconds /= HOURS_PER_DAY;
// etc
}
``````

Man you guys are really helpful.

I'm still trying to rap my head around displaying this on the AdaFruit LCD Shield.

I do know how to use the Shield I'm just trying to decipher all your code because I'm such a newbie.

Thanks all of you.

jurs:

``````void setup() {
``````

Serial.begin(9600);

}

void loop() {
unsigned long runMillis= millis();
unsigned long allSeconds=millis()/1000;
int runHours= allSeconds/3600;
int secsRemaining=allSeconds%3600;
int runMinutes=secsRemaining/60;
int runSeconds=secsRemaining%60;

char buf[21];
sprintf(buf,"Runtime%02d:%02d:%02d",runHours,runMinutes,runSeconds);
Serial.println(buf);
delay(1000);

Ok I have this one working except for two kind of Chinese look symbols at the end.
I'm not sure how to fix that but I'm already working on removing the Delay command.

Thanks

jurs:

``````char buf[21];
``````

sprintf(buf,"Runtime%02d:%02d:%02d",runHours,runMinutes,runSeconds);

Okay I figured out where the extra characters were coming from and now it's time to make it run without the Delay Function.

I really do not understand how these two lines work at all though.

Thanks

technogeekca:

jurs:

``````char buf[21];
``````

sprintf(buf,"Runtime%02d:%02d:%02d",runHours,runMinutes,runSeconds);

I really do not understand how these two lines work at all though.

http://www.cplusplus.com/reference/cstdio/sprintf/
I know that that information is in a form that is hard for a beginner to understand, so I will make my own explanation of the two lines you are asking about.

``````char buf[21];
``````

This creates a character array. Character arrays can be used to store text, such as, for example, the text you want to show on your display. Note that "text" can include numerals and punctuation, not just letters of the alphabet.
This particular character array is named `buf` and can store up to 20 characters. (I know that the number in brackets is 21, not 20, but for all practical purposes, the limit here is 20 characters. For character arrays, the limit is always one less than the number in the brackets.)

``````sprintf(buf,"Runtime%02d:%02d:%02d",runHours,runMinutes,runSeconds);
``````

This fills `buf` with text in a very specific manner. What it does here is this:
Step 1: The word `Runtime` is transcribed verbatim.
Step 2: The characters `%02d` (before the first colon) are taken as an instruction to convert a number (`int` variable or smaller) into text. In this case, the number is whatever is in the variable `runHours`. (How does it know we want `runHours` and not some other variable? Read the whole line of code and you will see.)
Step 3: The `:` (colon) character is transcribed verbatim.
Step 4: The characters `%02d` (between the two colons) are taken as an instruction to convert a number into text. This time, the number is whatever is in `runMinutes`.
Steps 5 and 6: I think you can figure these out on your own. (Hint: they are very similar to Steps 3 and 4.)
Step 7: A "null terminator" is inserted at the end of our text. (A "null terminator" is a kind of stop sign that means we've reached the end of our text, so stop reading.)

Note: `%02d` means "Use at least two digits. If only one digit, then put a zero at the left to make it two digits." If you don't want the zero, then use `%d` instead of `%02d`. If you want more zeros (like on a car odometer), then use `%03d` or `%04d` or whatever.

jurs:
In case yes: DO NOT USE MILLIS, COUNT SECONDS instead!

You can break down millis() into a seconds counter which is NOT affected by rollovers after about 50 days.
Please feel free to ak in case you don't know how to do it.

My timer only needs to pause an initial set off external devices for a maximum of 24 Hours and then after that each event requires 30 Minute Intervals. I will also need to try to figure out how to use your example to count down and remove the Delay Function but I would like to do this on my own for now. By no means do I need any kind of accuracy for what I'm doing so the internal clock in the Arduino is perfectly fine.

Yes if you could help me with what's quoted above that would be great.

I'm a hardware guy and I'm drastically laking in any programming knowledge ar all. I would like to ask anyone if you can suggest any resources that may help me out. Books, Websites, what languages I should learn for the Arduino at this point and then I can expand to other devices later.

I can't thank any of you enough, this has been an absolutely wonderful place to start from.

Look at at post #5, you need not delay. If the millis are equal or greater than kept value do an action. Increment millis about 1000 for next successful comparison. Increment time about 1 second. From this moment you are working with the time in seconds. No delay is needed.

```#include "wiring.c";
...
...
...
volatile void millis_reset()
{
uint8_t oldSREG = SREG; //
cli(); // disable interrupts while we read timer0_millis or we might get an
// inconsistent value (e.g. in the middle of a write to timer0_millis)
timer0_millis = 0; // Set to new millis value...
SREG = oldSREG; //
}
```

technogeekca:
I am trying to convert millis to HRS:MINS:SECS as in 01:12:34.

I was lead to the DateTime Library which requires the Wiring Library.