Convert seconds to HH MM SS

I am reading a tag in my PLC which is a count down timer, in seconds.

I need to show this countdown time on a display, but I need the format to change to HH:MM:SS. How can I do this? I thought about using a expression binding and use “runScript” to run a gateway script, but I have to constantly pass the seconds to the script. the runScript expression seems like you have to pass it string text? Or can I pass a tag?

Now that v7.7 is out, I thought about adding a script on the tag directly, which would create the HH:MM:SS string each time the value changed, I would dump that into another string tag.

Alright so I came up with a solution by adding a script to the tag directly. Works, but need to put it through it’s paces. Here is the code:

   m, s = divmod(currentValue.value, 60)
	h, m = divmod(m, 60)
	hhmmss = "%d:%02d:%02d" % (h, m, s)
	system.tag.write("[.]remainHHMMSS", hhmmss) 

Little concerning as I added this to my UDT definition and all my SQLtags proceeded to time out for an extended period of time (fairly complex UDT with a large number of SQLtags). Definitely would be cautious doing this in a production environment.

datetime should be usable, for Jython 2.5+:

from datetime import datetime, timedelta sec = timedelta(seconds=int(currentValue.value)) d = datetime(1,1,1) + sec hhmmss="%02d:%02d:%02d" % (d.hour, d.minute, d.second) system.tag.write("[.]remainHHMMSS", hhmmss)

This is nicely adjustable to use days as well:

from datetime import datetime, timedelta sec = timedelta(seconds=int(currentValue.value)) d = datetime(1,1,1) + sec ddhhmmss="%02d:%02d:%02d:%02d" % (d.day-1, d.hour, d.minute, d.second) system.tag.write("[.]remainDDHHMMSS", ddhhmmss)

For anyone wanting to play with this in the Script playground:

[code]from datetime import datetime, timedelta

s=500000

sec = timedelta(seconds=int(s))
d = datetime(1,1,1) + sec
print(“DAYS:HOURS:MIN:SEC”)
print("%02d:%02d:%02d:%02d" % (d.day-1, d.hour, d.minute, d.second))
[/code]

Is there a better way to to this in ignition 7.9/8? I need a simple countdown timer formatted as h:mm:ss between two timestamps (time remaining until shift change in my case).

I was hoping to be able to accomplish this with an expression.

1 Like

image

secondsBetween(now(),{root.Popup Calendar.date})

formatted as h:mm:ss

->

numberFormat(hoursBetween({Root Container.Popup Calendar.date}, now()), '00') + ':' +
numberFormat(minutesBetween({Root Container.Popup Calendar.date}, now()) % 60, '00') + ':' +
numberFormat(secondsBetween({Root Container.Popup Calendar.date}, now()) % 60, '00')

or you can do conversion math on the seconds.

3 Likes

This isn’t very elegant looking, but it works.

hoursBetween(now(0),{Root Container.Popup Calendar.date})+':'+
(minutesBetween(now(0),{Root Container.Popup Calendar.date})-(hoursBetween(now(0),{Root Container.Popup Calendar.date})*60)) +':'+ 
(secondsBetween(now(0),toDate("2019-01-15 16:00:00"))-(minutesBetween(now(0),{Root Container.Popup Calendar.date})*60))   

2 Likes

This is almost the "right" answer - slightly cleaner/better is to just use stringFormat:

stringFormat("%02d:%02d:%02d", 
	hoursBetween({Root Container.Popup Calendar.date}, now()),
	minutesBetween({Root Container.Popup Calendar.date}, now()) % 60,
	secondsBetween({Root Container.Popup Calendar.date}, now()) % 60
)

Note that it's worth a disclaimer that this will "break" if you overflow 24 hours. You can solve that with an additional if statement and more complex logic, but I'll leave that for the reader.

3 Likes

Curious why

dateFormat({[System]Gateway/CurrentDateTime},"H")

resolves (no need for toDate function) but

getHour24({[System]Gateway/CurrentDateTime})

does not? Instead I must use

getHour24(todate({[System]Gateway/CurrentDateTime}))

Just curious.

No particular reason, other than expression functions are (were) fairly rigorous in their expected types. There’s a pending change for 8.0 that will make things like that work as expected, as much as possible.

1 Like

In my case, I am reading a tag from the PLC which gives me seconds.
How could I display it on a label on that format 00:00?

It basically starts reading in seconds and counts up till the tag is reset.

Could this simply be an expression added on text binding?

This can be done easily with an expression. Something like:

dateFormat(addSeconds(midnight(now()),insert your seconds tag here),"HH:mm:ss")

If you just want hours and minutes you change the time format accordingly to “HH:mm”

6 Likes

Not a simple expression:

concat(toInt(floor({[default]path/to/tag}/60)),
		':', 
		numberFormat({[default]path/to/tag}%60,'00')
		)
2 Likes

That worked perfectly. Thank you

That worked perfectly. Thank you

So If I want to Display another Label showing time how would I implement this through a script?

If your talking doing the same thing but through a script it is identical but using script functions. You would need to do a system.tag.read(tag path).value to get your seconds and store it in a variable but then you would insert your variable into the script. Then it depends where the script is to how to put it in the label.

time = system.date.format(system.date.addSeconds(system.date.midnight(system.date.now()),insert your seconds val here),"HH:mm:ss")
2 Likes

divmod() works well. And we now get a more modern string formatting to play with.

secondsIn = 5000

m,s = divmod(secondsIn, 60)
h,m = divmod(m, 60)
print '{hr:02d}:{mn:02d}:{sc:02d}'.format(hr=h,mn=m,sc=s)

3 Likes

Very clean