# Day of year

## Recommended Posts

• MVP 2022

One of my customers is looking to record possibly long time periods that the system is turned off. This would be much easier if we had a "Day of Year" SI register, so we wouldn't have to calculate total days with a complex ladder considering the number of days in each month. Don't forget leap years.

Or am I doing this wrong?

Joe T.

##### Share on other sites

I'd say you're doing it wrong.

Use the RTC to UTC function block - that gives you a value in seconds from the epoch (1 Jan 1900). If you store the UTC value in a DW register once a second as the last thing you do in the main block, then on power-up you can calculate UTC and subtract the stored value (which would be when the PLC was powered down.) That result is the number of seconds the PLC was powered down - divide by 86400 (seconds per day) to get days powered down.

##### Share on other sites

• MVP 2022

Thanks, Phil. The significance of UTC never dawned on me. The Help says this will work until 2024 - will that be the Y2.024K bug?

Joe T.

##### Share on other sites

It's the Mayan apocalypse - turns out that they were off by a base-twelve decade.

(I suspect that by then, we'll have a new function block which moves the epoch from 1900 to 1970 and buys us another 70 years, or gives us a 64 bit UTC value. Trouble is, of course, that 32 bits' worth of seconds is about 136 years...)

##### Share on other sites

Interesting question Joe. What is going to be the solution to this? Also, when using the UTC, do you have to create a variable in a display to use it? I have no desire to display the time and date I just need it so that I can do a UTC to a RTU (DW to MI).Also, I am unclear how you can store a date in seconds with out the hours and seconds remaining. Is the UTC basically just using very large numbers to corespond to a particular date? I think my main issued is how you go from a date to just HH:MM.SS. Am I reading the help section incorrectly? From my understanding if the zero was set at 1900 - 01 - 01 00:00.00 then when the 32 bit binary number was at 1111 1111 1111 1111 1111 1111 1111 1111 that would give us an integer of 4294967295 seconds which when converted would give us a value of 136.19251950152207 years. How are we going to get ok readings until 2024 and not 2036? Is because the maximum MI is 32767?If what I am saying is right then one UTC can be used for when the power is lost but still a significant amount of code will have to be written to account for the actual time elapsed in years, months, days, hours, seconds with multiple RTU (MI) numbers or can XI (no information on this in the help) or SI be used to cover longer lengths of time?Thanks,Dan

##### Share on other sites

If a new function block isn't developed by then, does that mean that I will have to go out into the field and reprogram every PLC that I have installed once the function block exists? This could be very costly...

##### Share on other sites

> Also, when using the UTC, do you have to create a variable in a display to use it?

No, it's just a number in one 32-bit register (DW).

> I have no desire to display the time and date I just need it so that I can do a UTC to a RTU (DW to MI).

If you need to send that value, it'll have to go as two 16-bit registers (MI). You can use the vector instruction "Map Register Bytes" to control which bytes of the source DW go into which byte of each word of the two destination MIs.

> Also, I am unclear how you can store a date in seconds with out the hours and seconds remaining. Is the UTC

> basically just using very large numbers to corespond to a particular date? I think my main issued is how you

> go from a date to just HH:MM.SS. Am I reading the help section incorrectly?

The function returns a 32-bit integer which is the number of seconds since the Epoch. No hours, minutes, days, years are returned in the result - just a huge number of seconds.

> From my understanding if the zero was set at 1900 - 01 - 01 00:00.00 then when the 32 bit binary number was at

> 1111 1111 1111 1111 1111 1111 1111 1111 that would give us an integer of 4294967295 seconds which when converted

> would give us a value of 136.19251950152207 years. How are we going to get ok readings until 2024 and not 2036?

That's a good question. Maybe somebody miscounted when putting together the manual?

> Is because the maximum MI is 32767?

I don't think so, no.

> If what I am saying is right then one UTC can be used for when the power is lost but still a significant amount

> of code will have to be written to account for the actual time elapsed in years, months, days, hours, seconds

> with multiple RTU (MI) numbers

If anyone were to actually care about that, then, yes. Remember that "Year" and "Month" are variable lengths of time, so it's meaningless to say "This system has been down for two months, seven days" - which months? Do you count from the start of a month, or backwards from now? If it's been down for 32 days and it's the middle of the month, is it one month and one day, or one month and fifteen days? You're much better off to just say "342 days", or "48.85 weeks" or something like that. Remember also that in the specific case of how long the system's been powered down, there's a lithium battery involved which will limit the maximum duration to much sooner than 14 years from now.

> or can XI (no information on this in the help) or SI be used to cover longer lengths of time?

An XI is more or less like an MI which can be accessed faster, and doesn't retain its value on powerdown. An SI is something that the system calculates, or you put a value in to modify the system's operation. Neither of these will help with longer lengths of time. The general method for handling this problem is to use 64 bit numbers for UTC, or to move the Epoch date. If we had a different function which returned and manipulated UTC values based on a 1970 (Unix) epoch instead of a 1900 (Microsoft Excel) epoch, we could get another 70 years out of the existing setup. Another possible cheat would be to have a "Days since the Epoch" value which was separate from the time of day, but that gets messy when you want to add and subtract values.

##### Share on other sites

UTC input values definitely won't let you put in a year of 2024, even though there's room left in the 32-bit register for more seconds. Interestingly enough, if you put a date into the RTC past 2024, the clock seems to work, but the UTC calculated from that date is incorrect - there's probably some overrun of a 16 bit variable in the internal calculations

for going from Gregorian Date to UTC and back. They can probably fix it fairly easily, extending the function to 2036 instead of 2024.

##### Share on other sites

>> Also, when using the UTC, do you have to create a variable in a display to use it? >No, it's just a number in one 32-bit register (DW).I think I am missing what DW the UTC will store its information if you don't call it on a HMI screen and designate it a DW for it. Am I missing a function block that will call the UTC?

##### Share on other sites

> I think I am missing what DW the UTC will store its information if you don't call it on a HMI screen and designate

> it a DW for it. Am I missing a function block that will call the UTC?

Yes - at least on V570, there are two function blocks: "Utils/Clock/UTC/RTC to UTC", and "Utils/Clock/UTC/UTC to RTC". The "RTC" field is the value of the first MI of a group in the Real Time Clock ordering - just like SI 30. The "UTC" field is any doubleword which will hold the 32-bit UTC value.

##### Share on other sites

I want to make sure I understand this clearly because I am still a bit confused on what the UTC is for. I understand that the UTC can hold an integer that tells you where you are in time with respect to the epoch, what I don't understand is how to get the value itself. If I take the RTC to UTC and send SI 30 to DW 0, am I going to get the time in seconds from the epoch? Does the RTU to UTC account for the year, days, and hours in seconds and add them to the UTC or do I have to account for all of that in my one DW that is the time since the epoch?

##### Share on other sites

> I want to make sure I understand this clearly because I am still a bit confused on what the UTC is for.

> I understand that the UTC can hold an integer that tells you where you are in time with respect to the epoch,

> what I don't understand is how to get the value itself. If I take the RTC to UTC and send SI 30 to DW 0, am I

> going to get the time in seconds from the epoch?

Yes. If you put any set of seconds, minutes, hours, etc. in a different set of MI registers in the same pattern as the RTC is laid out, you'll get a UTC result that corresponds to the time and date you fed in.

> Does the RTU to UTC account for the year, days, and hours in seconds and add them to the UTC or do I have to account

> for all of that in my one DW that is the time since the epoch?

The "RTC to UTC" function accounts for all hours, days, months, leap years, and so on, and produces a 32-bit integer which is the exact number of seconds between the Epoch and the RTC formatted date you fed in. It is a one-to-one correspondence - any RTC date within the allowable range will produce one and only one UTC result, and any UTC value within the allowable range will produce one and only one RTC formatted date value. That's all you need to do - give it a date, it gives you a 32-bit integer. You can add or subtract a value (in seconds) from that integer, and feed it to the "UTC to RTC" function, and the result will be whatever date that winds up being.

If you want to play with some examples, go to the Epoch Converter Page and feed it some date values. Note that this page uses the Unix Epoch of 1970, not the Excel Epoch of 1900, so the resulting UTC numbers will be off by a fixed amount from the UTC numbers in the PLC.

##### Share on other sites

So now that I know the time of the power failure and the length of time the unit was powered down I have run accross a completely different issue. I need to determine if a particular time of day on a given day of the week passed while the power was off. I just can't seem to come up with a way to determine if that time. I.E. last Wednesday using the DOW box, and the time by using the HOUR indirect ttime function. Any ideas?

##### Share on other sites

At power-up, take the current RTC registers, move the whole set of them to a batch of work registers with a vector copy. Change the time of day registers in the work area (hour, minutes, seconds) to the time of day you're trying to check on, and convert the work area to a UTC value. Take the DOW register from the work area, which is today's day of week, and use that to see how many days you need to back up the calculated UTC value to get to the desired day of week - subtract 86,400 times the number of days from that UTC value. That's now the UTC value for the time of day you're looking for, on the day of the week you're looking for. Now compare that UTC to the saved power-down UTC - if the saved value is less than the calculated "magic date/time", the PLC was powered off at that time.

##### Share on other sites

• 4 years later...

Sorry Guys, using UTC and counting seconds since the Epoch was more complicated than what I needed, and possibly more than most who simply need an integer for Day of Year.

The attached isn't the most clever code I've ever written, but it gets the job done, is easy for the next guy to understand, and as a bonus, catches leap years.  I hope it helps others with the same need.

I put a subroutine call to DOY in !Main on the 1 sec pulse (SB13).

VisiLogic DOY.pdf

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×