Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 22:20 13 Nov 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : More time routines

Author Message
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 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
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 10:03pm 20 Apr 2018
Copy link to clipboard 
Print this post

Really useful. Particularly for measuring intervals.

I did something simplistic but only did seconds from midnight, so could not be used for periods longer that 24 hours.

The other Function I have will be useful for the above to format a "Seconds Elapsed" value back to a string.

Runtime & Uptime were my uses.

[Code]Function SecsTime(TimeInt as Integer) as String

Local Integer DD,HH,MM,SS

Local Integer TimeIn,DD,HH,MM,SS

TimeIn=Timer\1000
DD=(TimeIn\86400)
HH=(TimeIn-DD*86400)\3600
MM=(TimeIn-DD*86400-HH*3600)\60
SS=(TimeIn-DD*86400-HH*3600-MM*60)
If DD>0 then SecsTime=Str$(DD,2,0,"0")+":"+SecsTime

End Function[/code]

Phil.

Edit; DD= was missing from the copy I took.Edited by Phil23 2018-04-22
 
lew247

Guru

Joined: 23/12/2015
Location: United Kingdom
Posts: 1702
Posted: 08:50am 03 Dec 2018
Copy link to clipboard 
Print this post

Is there a way to print the number of seconds of the day it is?

but only out of 43200 ie 12 hour days

so midnight would be zero and midday be zero

1:12:32 would be 4352
which is 60 secs * 72 +32

13:12:32 would be the exact same number


 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10575
Posted: 10:02am 03 Dec 2018
Copy link to clipboard 
Print this post

Don't really understand the question as it doesn't seem to have a relationship to the posted code.

What you want is easy

secs=(Val(Left$(Time$,1)) Mod 12) * 3600 + Val(Mid$(Time$,4,2)) * 60 + Val(Right$(Time$,2))
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 4139
Posted: 12:15pm 03 Dec 2018
Copy link to clipboard 
Print this post

Might need the first Left$ to use ,2 instead of ,1.

John
 
Greg Fordyce
Senior Member

Joined: 16/09/2011
Location: United Kingdom
Posts: 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
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025