![]() |
Forum Index : Microcontroller and PC projects : A day of the year function.
Page 1 of 2 ![]() ![]() |
|||||
Author | Message | ||||
Paul_L Guru ![]() Joined: 03/03/2016 Location: United StatesPosts: 769 |
Take a look at this day of the year function which I dashed off just now. I wonder if anyone can suggest a better way to do it. Paul in NY ' DofY.bas, P Lepkowski, 7/9/2018 ' tests function DofY(d$) which finds the numeric day of any year ' run it under MMBasic for DOS GLOBALS: Option base 1 Dim m%,d%,y%,day$, year%,LeapYear% ' date$="dd-mm-yyyy", time$="hh:mm:ss" main: Do Print "Enter a day, month and year or '0' (zero) to end!" Input "day"; d%: If (d%<1 Or d%>31) Then Exit Do Input "month"; m%: If (m%<1 Or m%>12) Then Exit Do Input "year"; y%: If y%<100 Then y%=2000+y% day$=Str$(d%,2,0,"0")+"-"+Str$(m%,2,0,"0")+"-"+Str$(y%,4,0,"0") Print day$+" is the "+ Str$( DofY%(day$) )+" day of the year." Loop Print "Today is "+Date$+" which is the "+ Str$( DofY%(Date$) )+" day of the year." Print "This displays all years from 2000 to 2500 followed by '1' if it is a leap year or '0' if it is not a leap year." Print "It verifies that 2100, 2200, 2300 and 2500 are not leap years." Print "Hint: stretch this window horizontally and vertically until you see 20 columns and 25 rows!." For year%=2000 To 2500 If (year%\100)=(year%/100) Then LeapYear%=((year%\400)=(year%/400)) Else LeapYear%=((year%\4)=(year%/4)) EndIf Print Str$(year%)+" "+Str$(LeapYear%), Next year% End Function DofY%(DofY.dat$) 'accepts date$() or "dd-mm-yyyy" Local DofY.i%, DofY.d%, DofY.m%, DofY.y%, DofY.LeapY%, DofY.inMo%(12) ' parse DofY.dat$ passed in DofY.d%=Val(Mid$(DofY.dat$,1,2)) DofY.m%=Val(Mid$(DofY.dat$,4,2)) DofY.y%=Val(Mid$(DofY.dat$,7,4)) ' is DofY.Y% a leap year If (DofY.y%\100)=(DofY.y%/100) Then DofY.LeapY%=((DofY.y%\400)=(DofY.y%/400)) Else DofY.LeapY%=((DofY.y%\4)=(DofY.y%/4)) EndIf ' load DofY.inMo%(12) array If DofY.LeapY%=1 Then Restore DofYleapData Else Restore DofYData For DofY.i%=1 To 12:Read DofY.inMo%(DofY.i%):Next DofY.i% ' calculate Day of Year If DofY.m%=1 Then DofY%=DofY.d% Else DofY%=DofY.d%+DofY.inMo%(DofY.m%-1) End Function 'DofY% DofYData: Data 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 DofYleapData: Data 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 ''''''''''''''''''''''''''''eof |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9610 |
I setup a one-dimensional array to hold the days: DOW$(0)="Sunday":DOW$(1)="Monday":DOW$(2)="Tuesday":DOW$(3)="Wednesday" DOW$(4)="Thursday":DOW$(5)="Friday":DOW$(6)="Saturday" ...then a Function to calculate the day reference: function DayOfWeek(year, month, day) a = int((14-month)/12) m = month + 12*a - 2 y = year - a DayOfWeek = (day + y + int(y/4)-int(y/100)+int(y/400)+int(31*m/12)) mod 7 end function ...then used a simple SUB to build the date string whenever I needed it: SUB BUILD_DATE YEAR=val(MID$(DATE$,7,4)):MONTH=VAL(MID$(DATE$,4,2)):DAY=val(MID$(DATE$,1,2)) DOW_DAY$=DOW$(DayOfWeek(YEAR,MONTH,DAY)) + ", " + DATE$ CtrlVal(MM_DAD)="THE DATE TODAY IS: "+DOW_DAY$ END SUB Result: ![]() The formula for DayOfWeek came from someone here on the forums, and I think they got it from the net. I understand it is a reasonably well known formula for calculating the day of the week. Smoke makes things work. When the smoke gets out, it stops! |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
Yep, that would have been me. :) Used that for so many years even back in the GWBasic days. I know I got it from somewhere (was not the internet at that time!) :) I made it a bit smaller, and more obscure I think, to fit in a tiny function that can be included when needed. Microblocks. Build with logic. |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9610 |
![]() Smoke makes things work. When the smoke gets out, it stops! |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
This is a SUB I have used in the past. It was before Integers were available and includes the Microsoft Excel 'days since 1900'. You can remove or just ignore that line. I did a quick check and it seems to agree with your code. Jim VK7JH MMedit |
||||
greybeard Senior Member ![]() Joined: 04/01/2010 Location: AustraliaPosts: 174 |
Probably a bit simple ![]() function DayOfWeek(year, month, day) DayOfWeek = Today end Function |
||||
Paul_L Guru ![]() Joined: 03/03/2016 Location: United StatesPosts: 769 |
@TassyJim - thanks, that's a nice one. The rest of youse guys, DofY should return an integer from 1 to 366, never "Monday". Paul in NY |
||||
rave Newbie ![]() Joined: 24/02/2018 Location: United StatesPosts: 28 |
True. The following two simple functions do the trick (this is all very standard stuff and published elsewhere): ' return days since 01-01-0001 without Julian calendar correction Function Days(d, m, y) Local a a = Int((14-m)/12) m = m+12*a y = y-a Days = 365*y+Int(y/4)-Int(y/100)+Int(y/400)+Int((153*m-457)/5)+d-306 End Function ' return the weekday of the given date Function WeekDay$(d, m, y) Local a,w$ a = 7*(Days(d, m, y) Mod 7)+1 w$ = "Sun Mon Tues Wednes Thurs Fri Satur " WeekDay$ = Mid$(w$,a,Instr(a,w$," ")-a)+"day" End Function I shamelessly optimized string storage requirements, in the second function, sacrificing its readability ![]() - Rob |
||||
Paul_L Guru ![]() Joined: 03/03/2016 Location: United StatesPosts: 769 |
Hi Rob, it's good to see you drop in here. That's a nice way to optimize string storage in that second function, but I'm not sure it works in MMBasic. I believe that Geoff had to compromise and allocate 256 bytes for any string so using an array might work better but even then it might have 256 bytes reserved. option base 1 ' return days since 01-01-0001 without Julian calendar correction Function Days(d, m, y) Local a a = Int((14-m)/12) m = m+12*a y = y-a Days = 365*y+Int(y/4)-Int(y/100)+Int(y/400)+Int((153*m-457)/5)+d-306 End Function ' return the weekday of the given date Function WeekDay$(d, m, y) Local a,w$(7) length 6 =("Sun","Mon","Tues","Wednes","Thurs","Fri","Satur") ' the entire w$() array might still use 256 bytes instead of 49 bytes a = 7*(Days(d, m, y) Mod 7)+1 WeekDay$ = w$(a)+"day" End Function While we're at it, do you see any way to optimize this further? Dim d%,m%,y%,day$="dd-mm-yyyy",DOY% d%=11:m%=2:y%=1940:DOY%=DofY%():print DOY%, day$="11-02-1940":DOY%=DofYs%(day$):print DOY%, DOY%=DofYs%(DATE$):print DOY%, END function DofYs%(d$) ' return dayofyear% given DATE$() or "dd-mm-yyyy" d%=Val(Mid$(d$,1,2)):m%=Val(Mid$(d$,4,2)):y%=Val(Mid$(d$,7,4)):DofYs%=DofY%() End function 'DofYs%(d$) ' return dayofyear% given DATE$() or "dd-mm-yyyy" Function DofY%() ' return dayofyear% given globals d%, m%, y% DofY%= d% + Int((m%-1)*30.57+0.5) If m%>2 Then DofY%=DofY%-1 If (y% Mod 4)>0 Then DofY%= DofY%-1 'not leap year If (y% Mod 100)=0 Then DofY%= DofY%-1 'not leap century If (y% Mod 400)=0 Then DofY%= DofY%+1 'leap 4th century EndIf End Function 'DofY%() ' return dayofyear% given globals d%, m%, y% Paul in NY |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
Either way works. I often use Rob's method. Jim VK7JH MMedit |
||||
rave Newbie ![]() Joined: 24/02/2018 Location: United StatesPosts: 28 |
Hi Paul, I like your suggestion to use the inline array!! Unfortunately, MMBASIC V4.5 runs on the Colour MaxiMite that I'm using and does not support this. Sure, I'd reckon that your DofY%() function can be simplified to: Function DofY%() Local mm%,yy%,a% a% = Int((14-m%)/12) mm% = m%+12*a% yy% = y%-a% DofY% = 365*yy%+Int(yy%/4)-Int(yy%/100)+Int(yy%/400)+Int((153*mm%-457)/5)+d%-306 End Function PS. Note that the Days() function in my earlier example changes the arguments m and y when passed as variables to the function, which in general we want to avoid by using locals mm% and yy% such as in the code above. - Rob |
||||
lew247![]() Guru ![]() Joined: 23/12/2015 Location: United KingdomPosts: 1702 |
I'm still having problems with the day of the week function It keeps saying the day is Sat Can anyone see any problems with this code? I'm using a PICROMITE - the code should be identical to any other version of the MM though [code] DOW$(0)="Sun":DOW$(1)="Mon":DOW$(2)="Tue":DOW$(3)="Wed":DOW$(4)="Thu":DOW$(5)="Fri":DOW$(6)="Sat" Year=Val(Mid$(Date$,7,4)):Month=Val(Mid$(Date$,4,2)):Day=Val(Mid$(Date$,1,2)) dowx1$=DOW$(DayOfWeek(YEAR,MONTH,DAY)) do print DOW$(DayOfWeek(YEAR,MONTH,DAY)) pause 2000 print DOW$(DayOfWeek(YEAR,MONTH,DAY)) @print 2nd time to see if it changes the day after a pause end function DayOfWeek(year, month, day) print year 'to check if it's correct print month 'to check if it's correct print day 'to check if it's correct local a,m,y a = int((14-month)/12) m = month + 12*a - 2 y = year - a DayOfWeek = (day + y + int(y/4)-int(y/100)+int(y/400)+int(31*m/12)) mod 7 end function [/code] |
||||
CaptainBoing![]() Guru ![]() Joined: 07/09/2016 Location: United KingdomPosts: 2170 |
really tiny Leapyear function. returns a boolean so if you want, you can just "add" it to 365 for days in a particular year http://www.fruitoftheshed.com/MMBasic.IsLeapYear-Function-to-determine-if-the-given-year-is-a-Leap-Year-on-the-Gregorian -western-calendar.ashx |
||||
Paul_L Guru ![]() Joined: 03/03/2016 Location: United StatesPosts: 769 |
Hi Lew ... It looks like your code repetitively extracts Year, Month, and Day from the MMVar DATE$. If you run this under DOS then DATE$ will get the current date from DOS (Windowze?). If you run it on a chip it might return the correct date if you have an RTC module hooked up and it's set properly, or if it has access to a GPS receiver. If you just start up a cold PIC chip I don't know what DATE$ will initially return. It does make sense that it will repetitively return the same day, ("Sat"), if DATE$ doesn't change. I have added comments and indented your code below. Paul in NY [code] DOW$(0)="Sun":DOW$(1)="Mon":DOW$(2)="Tue":DOW$(3)="Wed":DOW$(4)="Thu":DOW$(5)="Fri":DOW$(6)="Sat" Year=Val(Mid$(Date$,7,4)):Month=Val(Mid$(Date$,4,2)):Day=Val(Mid$(Date$,1,2)) dowx1$=DOW$(DayOfWeek(YEAR,MONTH,DAY)) 'DOESN'T DO ANYTHING BECAUSE dowx1$ IS NEVER USED BELOW do 'THIS DO DOESN'T DO ANYTHING BECAUSE THERE IS NO LOOP BELOW print DOW$(DayOfWeek(YEAR,MONTH,DAY)) pause 2000 'YEAR, MONTH, or DAY don't change during this pause 'DATE$ will change if you pass midnight during the pause 'but YEAR, MONTH and DAY still won't change unless you specifically 'set them again with line #2 above print DOW$(DayOfWeek(YEAR,MONTH,DAY)) '@print 2nd time to see if it changes the day after a pause end function DayOfWeek(year, month, day) print year 'to check if it's correct print month 'to check if it's correct print day 'to check if it's correct local a,m,y a = int((14-month)/12) m = month + 12*a - 2 y = year - a DayOfWeek = (day + y + int(y/4)-int(y/100)+int(y/400)+int(31*m/12)) mod 7 end function [/code] |
||||
lew247![]() Guru ![]() Joined: 23/12/2015 Location: United KingdomPosts: 1702 |
Hi Paul I only included the actual DOW part of the actual code Yes when booted up it uses the default date I have told it to use whic is 01-01-1999 After 2 seconds the Picromite has got the current correct local time and date and stored it in DAY$ and DATE$ I'm only trying to get the day of the week after the correct local time and date has been processes The "only" reason I have the Pause in the code above is to confirm it prints the same day both times - it's not actually needed |
||||
GoodToGo!![]() Senior Member ![]() Joined: 23/04/2017 Location: AustraliaPosts: 188 |
Hi Lew, I tried your code in DOS MMBasic ver 5.04.05 Beta 6 and it worked fine after I made a couple of edits:- I had to declare the variable DOW$(6) at the start, I commented out the 'do' I commented out the 'dowx1$=DOW$...etc etc line. dim DOW$(6) as string DOW$(0)="Sun":DOW$(1)="Mon":DOW$(2)="Tue":DOW$(3)="Wed":DOW$(4)="Thu":DOW$(5)="Fri":DOW$(6)="Sat" Year=Val(Mid$(Date$,7,4)):Month=Val(Mid$(Date$,4,2)):Day=Val(Mid$(Date$,1,2)) 'dowx1$=DOW$(DayOfWeek(YEAR,MONTH,DAY)) 'DOESN'T DO ANYTHING BECAUSE dowx1$ IS NEVER USED BELOW 'do 'THIS DO DOESN'T DO ANYTHING BECAUSE THERE IS NO LOOP BELOW print DOW$(DayOfWeek(YEAR,MONTH,DAY)) pause 2000 'YEAR, MONTH, or DAY don't change during this pause 'DATE$ will change if you pass midnight during the pause 'but YEAR, MONTH and DAY still won't change unless you specifically 'set them again with line #2 above print DOW$(DayOfWeek(YEAR,MONTH,DAY)) '@print 2nd time to see if it changes the day after a pause end function DayOfWeek(year, month, day) print year 'to check if it's correct print month 'to check if it's correct print day 'to check if it's correct local a,m,y a = int((14-month)/12) m = month + 12*a - 2 y = year - a DayOfWeek = (day + y + int(y/4)-int(y/100)+int(y/400)+int(31*m/12)) mod 7 end function And the result was:- ![]() Is the format of Date$ the same in Picromite as it is in the normal MMbasic? ie. dd-mm-yyyy format? Cheers, GTG! ![]() ...... Don't worry mate, it'll be GoodToGo! |
||||
lew247![]() Guru ![]() Joined: 23/12/2015 Location: United KingdomPosts: 1702 |
Thanks G2G I thought I'd got everything correct In my code I had DIM DOW$ and not DIM DOW$(6) Tiny little error but stopped it working Thanks for spotting that ![]() Yes the Date format is the same dd-mm-yyyy Lewis |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
This is an error that should be getting caught by the MMBasic parser when you assign to DOW$(n). I've reported it to Geoff and I'm sure a fix will be included in a subsequent version of MMBasic so that it does generate an error. DIM DOW$ DOW$(1)="test" ' this statement should generate an error |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 5091 |
It was in K&R standard book on C. Volhout PicomiteVGA PETSCII ROBOTS |
||||
barewires Newbie ![]() Joined: 13/04/2015 Location: United KingdomPosts: 32 |
I keep a Perpetual Calendar in my head. Made an interesting programming exercise which I have somewhere on an old drive. Remember the following phrases and sets of numbers. "I work at the 7-11 from 9-5. Reverse 11-7 and 5-9. Remember 2-2, 4-4, 6-6, 8-8, 10-10 and 12-12. Last day of February." These dates were all Wednesday in 2018. Add a day for next year or two days if coming into a leap year. 2018 Wed 2019 Thu 2020 Sat 2021 Sun 2022 Mon 2023 Tue 2024 Thu January and March do not equate by this but are easy to calculate. Enjoy and have a Happy New Year and remember the magic day for 2019 is Thursday! |
||||
Page 1 of 2 ![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |