My seconds to date function in C ( easy port to spin) for years 2000 to 2136
tonyp12
Posts: 1,951
rtc struct is 6 bytes with the names: .year .month .day .hour .minute . second
Use this website to calculate seconds, we are in DST now so there is a option to add timezone conversion.
https://www.timeanddate.com/date/durationresult.html?m1=1&d1=1&y1=2000&m2=4&d2=5&y2=2135&h1=0&i1=0&s1=0&h2=16&i2=42&s2=45
Systems with signed 32bit unix from 1970 will soon get Y2K38 problems, this one uses unsigned from 2000, so a embedded system using it will get plenty of life.
I did not look at any other code examples as I did not want to get "bad" influences.
Mine is fast and uses no multiplications/division and no fractions, pasm have cmpsub so that would be even faster.
Use this website to calculate seconds, we are in DST now so there is a option to add timezone conversion.
https://www.timeanddate.com/date/durationresult.html?m1=1&d1=1&y1=2000&m2=4&d2=5&y2=2135&h1=0&i1=0&s1=0&h2=16&i2=42&s2=45
Systems with signed 32bit unix from 1970 will soon get Y2K38 problems, this one uses unsigned from 2000, so a embedded system using it will get plenty of life.
I did not look at any other code examples as I did not want to get "bad" influences.
Mine is fast and uses no multiplications/division and no fractions, pasm have cmpsub so that would be even faster.
const unsigned long secinamonth[13] = {0,0,0,31*86400,30*86400,31*86400,30*86400,31*86400,31*86400,30*86400,31*86400,30*86400,31*86400}; void seconds_to_rtc(unsigned long sec) // unsigned 32bit input { char temp = 0; // start at year 2000 while (sec >= 126230400 && temp <100){ sec -= 126230400; temp +=4;} // four year blocks until 2100 if (temp == 100){while (sec >= 31536000 && temp <104){ sec -= 31536000; temp +=1;}}//no leapyears while (sec >= 126230400){ sec -= 126230400; temp +=4;}// four year blocks again if (sec >= 31622400){ sec -= 31622400; temp +=1; // first year after a 4yr block is a leapyear while (sec >= 31536000){ sec -= 31536000; temp +=1;}// then it can only be two years left } rtc.year = temp; temp = 1; // let it go past 99 to max 136 for year 2136 if (sec >= 86400*31){ // January sec -= 86400*31; temp +=1; unsigned long tempfeb = 86400*28; if (rtc.year !=100 && !(rtc.year & 3)) tempfeb = 86400*29;// 2100 is no leap year if (sec >= tempfeb){ sec -= tempfeb; temp +=1; // do the other months now while (sec >= secinamonth[temp]){ sec -= secinamonth[temp]; temp +=1;} } } rtc.month = temp; temp = 1; while (sec >= 86400){ sec -= 86400; temp +=1;} // days rtc.day = temp; temp = 0; while (sec >= 3600){ sec -= 3600; temp +=1;} // hour rtc.hour = temp; temp = 0; while (sec >= 60){ sec -= 60; temp +=1;} // minute rtc.minute = temp; rtc.second = sec; // seconds }
Comments
Jan 1 2000 was a Saturday,
(Sorry, you hit on one of my pet peeves -- lots of people think Unix time_t and similar timestamps count "seconds since the epoch", but in fact they actually count 86400*"days since the epoch", and the two are not the same -- not all days have 86400 seconds.)
You can also do local time: And it's up to user to adjust rt.c.zone ±3600 on the dst-dates.
seconds could be a #define to directly pointing to counter register,
or a function that merge a much faster running counter like 8192Hz rightshifted >>13 and adding to it a software counter that rollover IRQ have been adding upper values to.
So what is best is to have a que message system, that you call to insert a time and event flag and it sorts them. (eg. a rtc alarm)
As you could then insert the 2am/3am DST dates as a event.
Though there are no CCR register and IRQ's for counters on a P1 and waitcnt only taps in on system counter.
leap seconds, leap smear is probably safer, Google did that last time on Dec31 2016 over a 10hr timespan.
You should use a timeserver that gives you seconds from 2000 that don't include leap seconds as actually seconds counted.
Or base your system time on GPS time, it was zero at ( Jan6 ?) 1980 and since it is not perturbed by leap seconds GPS is now ahead of UTC by 18 seconds.
Are leap-smears still seconds added to the seconds-between-two-dates?
quote:
The irregularity and unpredictability of UTC leap seconds is problematic for several areas, especially computing.
For example, to compute the elapsed time in seconds between two given UTC past dates requires the consultation of a table of leap seconds, which needs to be updated whenever a new leap second is announced.
Moreover, it is not possible to compute accurate time intervals for UTC dates that are more than about six months in the future.
Two timescales that do not follow leap seconds are already available, International Atomic Time (TAI) and Global Positioning System (GPS) time
Instead of inserting a leap second at the end of the day, Google servers implement a leap smear, extending seconds slightly over a time window prior to the leap second.
Amazon has announced it would follow a similar, but slightly different, pattern for the introduction of the June 30, 2015 leap second,leading to another case of the proliferation of timescales.
But if not syncing up on Jan1 or July1 (two dates most likely to just had a leap second) and it runs of a hardware rtc it will be a second off until next sync.
And where does it store leapsecond lookup table?, so how does ZigBee handle leapseconds when its trying to calculate dates?, I guess that is up to programmer?
...and DST even more...
Why not
1: Just always add two leap seconds to the leapday Feb29, in the last 26 years the average have been 2.17yrs between a added leap second.
OR
2: Use a leap-minute every 100 years, on Jan-1 2100 everyone gets an extra minute of sleep.
In November 2015 it was again decided to continue using leap seconds, pending further study and consideration at the next conference in 2023.
This one I use runtime multiplications, as all ARM have single cycle multi.