matherp Guru
 Joined: 11/12/2012 Location: United KingdomPosts: 10575 |
| Posted: 04:25pm 20 Apr 2018 |
Copy link to clipboard |
 Print this post |
|
This code implements the full Unix epoch time in MMBasic.
Simply this is the number of seconds since since January 1, 1970 (midnight UTC/GMT), not counting leap seconds.
Having calculated this it is then easy to do time arithmetic without worrying about day rollovers etc.
By-products of the calculations are the day of the week and the day of the year
The demo program shows how simple it is to calculate times in the past and into the future and how to test for events a certain number of seconds from now

Option explicit Option default integer ' const EPOCH_YR = 1970 CONST SECS_DAY = 86400 CONST SECS_HOUR = 3600 CONST SECS_MIN = 60
dim ytab1(11)=(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) dim monoff(11) = ( 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334) dim daysofweek$(6) length 9 =("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday", "Saturday") dim my_year, my_month, my_day, my_hour, my_min, my_sec, my_dayno, my_dayinyear, my_timestamp dim monthsinyear$(11) length 9 = ("January", "February", "March", "April", "May", "June" , "July", "August", "September", "October", "November", "December") dim th$(30) length 2 = ("st","nd","rd","th","th","th","th","th","th","th","th","th","th","th","th","th","th","th","th","th","st","nd","rd","th" ,"th","th","th","th","th","th","st") '
dim nowtime convert_time() 'convert time$ and date$ to Unix epoch time print format_time$()," ",daysofweek$(my_dayno), my_day,th$(my_day-1), " ", monthsinyear$(my_month-1) , " ",my_year ' what was the time and date 400 days, 17 hours, 15 minutes and 22 seconds ago? gmtime(my_timestamp-(400*SECS_DAY + 17*SECS_HOUR + 15*SECS_MIN + 22)) print format_time$()," ",daysofweek$(my_dayno), my_day,th$(my_day-1), " ", monthsinyear$(my_month-1) , " ",my_year ' what will be the time and date 200,000,000 seconds in the future? gmtime(my_timestamp+200000000) print format_time$()," ",daysofweek$(my_dayno), my_day,th$(my_day-1), " ", monthsinyear$(my_month-1) , " ",my_year convert_time() nowtime=my_timestamp do convert_time() loop until my_timestamp>=nowtime+10 print "Starting programmed event @ ",format_time$()," ",daysofweek$(my_dayno), my_day,th$(my_day-1), " ", monthsinyear$(my_month-1) , " ",my_year do convert_time() loop until my_timestamp>=nowtime+20 print "Stopping programmed event @ ",format_time$()," ",daysofweek$(my_dayno), my_day,th$(my_day-1), " ", monthsinyear$(my_month-1) , " ",my_year end ' sub convert_time() 'loads global time variables from time$ and date$ rtc gettime my_year= val(right$(date$,4)) my_month=val(mid$(date$,4,2)) my_day=val(left$(date$,2)) my_hour=val(left$(time$,2)) my_min=val(mid$(time$,4,2)) my_sec=val(right$(time$,2)) my_timestamp=timegm(my_year, my_month, my_day, my_hour, my_min, my_sec) daycalcs(my_timestamp) end sub
function is_leap_year(year as integer) as integer is_leap_year = 0 if year mod 4 = 0 then is_leap_year=1 if year mod 100 = 0 then is_leap_year=0 if year mod 400 = 0 then is_leap_year=1 end function
function leap_days(yy1 as integer, yy2 as integer)as integer local integer y1=yy1, y2=yy2 y1=y1-1 y2=y2-1 leap_days= (y2\4 -y1\4) - (y2\100 -y1\100) + (y2\400 -y1\400) end function
function timegm(tm_year as integer, tm_mon as integer, tm_mday as integer, tm_hour as integer, tm_min as integer, tm_sec as integer) as integer local integer year, days, hours, minutes year = tm_year days = 365 * (year-1970) + leap_days(1970,year) days=days + monoff(tm_mon-1) if tm_mon>1 and is_leap_year(year) then days=days+1 days = days + tm_mday -1 hours = days * 24 + tm_hour minutes = hours * 60 + tm_min timegm = minutes * 60 + tm_sec end function
sub daycalcs(tm_seconds as integer) 'calculate day of week and day in year local integer year = EPOCH_YR, dayno = tm_seconds\SECS_DAY my_dayno = (dayno + 4) mod 7 do while dayno>=yearsize(year) dayno=dayno-yearsize(year) year=year+1 loop my_dayinyear=dayno end sub
sub gmtime(tm_seconds as integer) 'calculate all parameters from the epoch time local integer year = EPOCH_YR, dayclock = tm_seconds mod SECS_DAY, dayno = tm_seconds\SECS_DAY, tm_mon=0 my_sec = dayclock mod 60 my_min = (dayclock mod 3600) \60 my_hour = dayclock \ 3600 my_dayno = (dayno + 4) mod 7 do while dayno>=yearsize(year) dayno=dayno-yearsize(year) year=year+1 loop my_year=year my_dayinyear=dayno do while dayno>=ytab1(tm_mon) dayno=dayno-ytab1(tm_mon) if tm_mon=1 and is_leap_year(year) then dayno=dayno-1 tm_mon=tm_mon+1 loop my_month=tm_mon+1 my_day=dayno+1 end sub
function yearsize(year as integer) as integer yearsize=365 if is_leap_year(year) then yearsize=366 end function
function format_time$() as string format_time$=str$(my_hour,2)+":"+right$(str$(my_min+100),2)+":"+right$(str$(my_sec+100),2) end function
|
Greg Fordyce Senior Member
 Joined: 16/09/2011 Location: United KingdomPosts: 153 |
| Posted: 01:17pm 29 May 2020 |
Copy link to clipboard |
 Print this post |
|
Thanks matherp for this example, I suddenly needed to calculate the epoch value and this came to the rescue. The only problem I had was that my existing program had OPTION BASE 1 set so I had to change a few lines. I haven't fully tested this as all I need is the epoch time but my changes are below.
option base 1 Option explicit Option default integer ' const EPOCH_YR = 1970 CONST SECS_DAY = 86400 CONST SECS_HOUR = 3600 CONST SECS_MIN = 60 dim ytab1(12)=(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) dim monoff(12) = ( 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334) dim daysofweek$(7) length 9 =("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday", "Saturday") dim my_year, my_month, my_day, my_hour, my_min, my_sec, my_dayno, my_dayinyear, my_timestamp dim monthsinyear$(112) length 9 = ("January", "February", "March", "April", "May", "June" , "July", "August", "September", "October", "November", "December") dim th$(31) length 2 = ("st","nd","rd","th","th","th","th","th","th","th","th","th","th","th","th","th","th","th","th","th","st","nd","rd","th" ,"th","th","th","th","th","th","st") ' dim nowtime convert_time() 'convert time$ and date$ to Unix epoch time print format_time$()," ",daysofweek$(my_dayno), my_day,th$(my_day-1), " ", monthsinyear$(my_month-1) , " ",my_year ' what was the time and date 400 days, 17 hours, 15 minutes and 22 seconds ago? gmtime(my_timestamp-(400*SECS_DAY + 17*SECS_HOUR + 15*SECS_MIN + 22)) print format_time$()," ",daysofweek$(my_dayno), my_day,th$(my_day-1), " ", monthsinyear$(my_month-1) , " ",my_year ' what will be the time and date 200,000,000 seconds in the future? gmtime(my_timestamp+200000000) print format_time$()," ",daysofweek$(my_dayno), my_day,th$(my_day-1), " ", monthsinyear$(my_month-1) , " ",my_year convert_time() nowtime=my_timestamp do convert_time() loop until my_timestamp>=nowtime+10 print "Starting programmed event @ ",format_time$()," ",daysofweek$(my_dayno), my_day,th$(my_day-1), " ", monthsinyear$(my_month-1) , " ",my_year do convert_time() loop until my_timestamp>=nowtime+20 print "Stopping programmed event @ ",format_time$()," ",daysofweek$(my_dayno), my_day,th$(my_day-1), " ", monthsinyear$(my_month-1) , " ",my_year end ' sub convert_time() 'loads global time variables from time$ and date$ rtc gettime my_year= val(right$(date$,4)) my_month=val(mid$(date$,4,2)) my_day=val(left$(date$,2)) my_hour=val(left$(time$,2)) my_min=val(mid$(time$,4,2)) my_sec=val(right$(time$,2)) my_timestamp=timegm(my_year, my_month, my_day, my_hour, my_min, my_sec) daycalcs(my_timestamp) end sub function is_leap_year(year as integer) as integer is_leap_year = 0 if year mod 4 = 0 then is_leap_year=1 if year mod 100 = 0 then is_leap_year=0 if year mod 400 = 0 then is_leap_year=1 end function function leap_days(yy1 as integer, yy2 as integer)as integer local integer y1=yy1, y2=yy2 y1=y1-1 y2=y2-1 leap_days= (y2\4 -y1\4) - (y2\100 -y1\100) + (y2\400 -y1\400) end function function timegm(tm_year as integer, tm_mon as integer, tm_mday as integer, tm_hour as integer, tm_min as integer, tm_sec as integer) as integer local integer year, days, hours, minutes year = tm_year days = 365 * (year-1970) + leap_days(1970,year) days=days + monoff(tm_mon-1) if tm_mon>1 and is_leap_year(year) then days=days+1 days = days + tm_mday -1 hours = days * 24 + tm_hour minutes = hours * 60 + tm_min timegm = minutes * 60 + tm_sec end function sub daycalcs(tm_seconds as integer) 'calculate day of week and day in year local integer year = EPOCH_YR, dayno = tm_seconds\SECS_DAY my_dayno = (dayno + 4) mod 7 do while dayno>=yearsize(year) dayno=dayno-yearsize(year) year=year+1 loop my_dayinyear=dayno end sub sub gmtime(tm_seconds as integer) 'calculate all parameters from the epoch time local integer year = EPOCH_YR, dayclock = tm_seconds mod SECS_DAY, dayno = tm_seconds\SECS_DAY, tm_mon=1 my_sec = dayclock mod 60 my_min = (dayclock mod 3600) \60 my_hour = dayclock \ 3600 my_dayno = (dayno + 4) mod 7 do while dayno>=yearsize(year) dayno=dayno-yearsize(year) year=year+1 loop my_year=year my_dayinyear=dayno do while dayno>=ytab1(tm_mon) dayno=dayno-ytab1(tm_mon) if tm_mon=1 and is_leap_year(year) then dayno=dayno-1 tm_mon=tm_mon+1 loop my_month=tm_mon+1 my_day=dayno+1 end sub function yearsize(year as integer) as integer yearsize=365 if is_leap_year(year) then yearsize=366 end function function format_time$() as string format_time$=str$(my_hour,2)+":"+right$(str$(my_min+100),2)+":"+right$(str$(my_sec+100),2) end function |