Author Topic: Calendar 2021  (Read 6969 times)

0 Members and 1 Guest are viewing this topic.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Calendar 2021
« on: December 24, 2020, 06:45:17 pm »
https://1drv.ms/u/s!AknUrv8RXVYMkIMiwSDNKinhlbfuHg?e=6eumhM

It's the end of the year again, so I've sat down and starting working up a little calendar program for the next year (once again, like I've did for several years already...)

What I've got this time around is a nice little program which looks like the following:
Code: QB64: [Select]
  1. CONST ShowGrid = -1
  2. CONST ShowYear = 0
  3. CONST DesiredYear = 2021
  4.  
  5. SCREEN _NEWIMAGE(1283, 720, 32)
  6.  
  7.  
  8. DIM SHARED f: f = _LOADFONT("OLDENGL.ttf", 72)
  9. DIM SHARED ThisMonth, Today, ThisYear
  10. DIM SHARED BackGrounds(1 TO 12)
  11.  
  12. ThisMonth = VAL(DATE$)
  13. Today = VAL(MID$(DATE$, 4))
  14. ThisYear = VAL(RIGHT$(DATE$, 4))
  15.  
  16.  
  17.  
  18. TitleScreen
  19. IF ShowYear THEN
  20.     FOR i = 1 TO 12
  21.         CLS
  22.         _PUTIMAGE , BackGrounds(i)
  23.         IF ShowGrid THEN DrawLines
  24.         CenterMonth i, DesiredYear
  25.         DrawDays i, DesiredYear
  26.         SLEEP
  27.     NEXT
  28.     CLS
  29.     _PUTIMAGE , BackGrounds(1)
  30.     IF ShowGrid THEN DrawLines
  31.     CenterMonth ThisMonth, ThisYear
  32.     DrawDays ThisMonth, ThisYear
  33.     SLEEP
  34.  
  35.  
  36. SUB TitleScreen
  37.     _TITLE "Steve's Calendar"
  38.     CLS , SkyBlue
  39.     _FONT f
  40.     text$ = "Steve's Calendar"
  41.     pw = _PRINTWIDTH(text$) \ 2
  42.     _PRINTSTRING (640 - pw, 200), text$
  43.     IF ShowYear THEN
  44.         text$ = _TRIM$(STR$(DesiredYear))
  45.     ELSE
  46.         text$ = _TRIM$(STR$(ThisYear))
  47.     END IF
  48.     pw = _PRINTWIDTH(text$) \ 2
  49.     _PRINTSTRING (640 - pw, 300), text$
  50.     GetBackgrounds
  51.     _FONT 16
  52.     COLOR Black
  53.     text$ = "Press <ANY KEY> to continue."
  54.     pw = _PRINTWIDTH(text$) \ 2
  55.     _PRINTSTRING (640 - pw, 400), text$
  56.     COLOR White
  57.     _FONT f
  58.     SLEEP 2
  59.  
  60.  
  61. SUB GetHolidays (month, day, holiday() AS STRING)
  62.     REDIM holiday(0) AS STRING
  63.     SELECT CASE month
  64.         CASE 1
  65.             SELECT CASE day
  66.                 CASE 1: REDIM holiday(1) AS STRING: holiday(1) = "New Years Day"
  67.                 CASE 6: REDIM holiday(1) AS STRING: holiday(1) = "Epiphany"
  68.             END SELECT
  69.         CASE 2
  70.             SELECT CASE day
  71.                 CASE 1: REDIM holiday(1) AS STRING: holiday(1) = "Black History Month"
  72.                 CASE 2: REDIM holiday(1) AS STRING: holiday(1) = "Groundhog Day"
  73.                 CASE 14: REDIM holiday(1) AS STRING: holiday(1) = "Valentine's Day"
  74.             END SELECT
  75.         CASE 3
  76.             SELECT CASE day
  77.                 CASE 1: REDIM holiday(1) AS STRING: holiday(1) = "Women's History Month"
  78.             END SELECT
  79.         CASE 4
  80.             SELECT CASE day
  81.                 CASE 15: REDIM holiday(1) AS STRING: holiday(1) = "Tax Day"
  82.             END SELECT
  83.         CASE 5
  84.             SELECT CASE day
  85.             END SELECT
  86.         CASE 6
  87.             SELECT CASE day
  88.             END SELECT
  89.         CASE 7
  90.             SELECT CASE day
  91.                 CASE 4: REDIM holiday(1) AS STRING: holiday(1) = "Independence Day"
  92.             END SELECT
  93.         CASE 8
  94.             SELECT CASE day
  95.             END SELECT
  96.         CASE 9
  97.             SELECT CASE day
  98.                 CASE 25: REDIM holiday(1) AS STRING: holiday(1) = "Steve's Birthday"
  99.             END SELECT
  100.         CASE 10
  101.             SELECT CASE day
  102.                 CASE 31: REDIM holiday(1) AS STRING: holiday(1) = "Halloween"
  103.             END SELECT
  104.         CASE 11
  105.             SELECT CASE day
  106.                 CASE 1: REDIM holiday(1) AS STRING: holiday(1) = "All Saint's Day"
  107.                 CASE 2: REDIM holiday(1) AS STRING: holiday(1) = "All Soul's Day"
  108.                 CASE 11: REDIM holiday(1) AS STRING: holiday(1) = "Vetern's Day"
  109.             END SELECT
  110.         CASE 12
  111.             SELECT CASE day
  112.                 CASE 7: REDIM holiday(1) AS STRING: holiday(1) = "Pearl Harbor Remembrance"
  113.                 CASE 24: REDIM holiday(1) AS STRING: holiday(1) = "Christmas Eve"
  114.                 CASE 25: REDIM holiday(1) AS STRING: holiday(1) = "Christmas"
  115.                 CASE ELSE: REDIM holiday(0) AS STRING
  116.             END SELECT
  117.     END SELECT
  118.  
  119.  
  120. SUB GetBackgrounds
  121.     IF ShowYear THEN limit = 12 ELSE limit = 1
  122.     FOR i = 1 TO limit
  123.         redo:
  124.         t = INT(RND * 1088) + 1
  125.         FOR j = 1 TO i
  126.             IF BackGrounds(j) = t GOTO redo
  127.             t$ = ".\Backgrounds\" + _TRIM$(STR$(t)) + ".jpg"
  128.             t1 = _LOADIMAGE(t$, 32)
  129.             IF t1 = -1 THEN _FREEIMAGE t1: GOTO redo
  130.         NEXT
  131.         BackGrounds(i) = t1
  132.     NEXT
  133.  
  134. SUB CenterMonth (month, year)
  135.     _FONT f
  136.     SELECT CASE month
  137.         CASE 1: text$ = "January"
  138.         CASE 2: text$ = "February"
  139.         CASE 3: text$ = "March"
  140.         CASE 4: text$ = "April"
  141.         CASE 5: text$ = "May"
  142.         CASE 6: text$ = "June"
  143.         CASE 7: text$ = "July"
  144.         CASE 8: text$ = "August"
  145.         CASE 9: text$ = "September"
  146.         CASE 10: text$ = "October"
  147.         CASE 11: text$ = "November"
  148.         CASE 12: text$ = "December"
  149.     END SELECT
  150.     text$ = text$ + STR$(year)
  151.     pw = _PRINTWIDTH(text$) / 2
  152.     _PRINTSTRING (640 - pw, 0), text$
  153.  
  154.  
  155. SUB DrawLines
  156.     TopOffset = 72
  157.     FOR i = 0 TO 6
  158.         LINE (0, i * 90 + TopOffset)-STEP(1280, 3), _RGBA32(128, 128, 64, 160), BF
  159.     NEXT
  160.     FOR i = 0 TO 7
  161.         LINE (i * 1280 / 7, 0 + TopOffset)-STEP(3, 540), _RGBA32(128, 128, 64, 160), BF
  162.     NEXT
  163.  
  164.  
  165. SUB DrawDays (month, year)
  166.     SHARED highlightday
  167.     REDIM Holidays(0) AS STRING
  168.     TopOffset = 76
  169.     nod = NumberOfDays(month, year)
  170.     y = 0
  171.     FOR i = 1 TO nod
  172.         text$ = _TRIM$(STR$(i))
  173.         pw = _PRINTWIDTH(text$)
  174.         x = GetDay(month, i, year)
  175.         IF month = ThisMonth AND i = Today AND ThisYear = year THEN LINE ((x - 1) * 1280 / 7 + 3, y * 90 + TopOffset)-STEP(1280 / 7 - 3, 86), Blue, BF
  176.         _PRINTSTRING (x * 1280 / 7 - pw, y * 90 + TopOffset), text$
  177.         GetHolidays month, i, Holidays()
  178.         u = UBOUND(holidays)
  179.         IF u > 0 THEN
  180.             _FONT 8
  181.             FOR j = 1 TO u
  182.                 pw = _PRINTWIDTH(Holidays(j))
  183.                 _PRINTSTRING ((x - 1) * 1280 / 7 + 4, (y + 1) * 90 + TopOffset - 5 - j * 8), Holidays(j)
  184.             NEXT
  185.             _FONT f
  186.         END IF
  187.  
  188.         IF x = 7 THEN y = y + 1
  189.     NEXT
  190.  
  191.  
  192. FUNCTION NumberOfDays (month, year)
  193.     SELECT CASE month
  194.         CASE 1, 3, 5, 7, 8, 10, 12: NumberOfDays = 31
  195.         CASE 2: IF IsLeapYear(year) THEN NumberOfDays = 29 ELSE NumberOfDays = 28
  196.         CASE 4, 6, 9, 11: NumberOfDays = 30
  197.     END SELECT
  198.  
  199.  
  200. FUNCTION IsLeapYear (yyyy) 'use 4 digit year
  201.     IF GetDay(2, 29, yyyy) <> GetDay(3, 1, yyyy) THEN IsLeapYear = -1
  202.  
  203. FUNCTION GetDay (m, d, y) 'use 4 digit year
  204.     'From Zeller's congruence: https://en.wikipedia.org/wiki/Zeller%27s_congruence
  205.     mm = m: dd = d: yyyy = y
  206.     IF mm < 3 THEN mm = mm + 12: yyyy = yyyy - 1
  207.     century = yyyy MOD 100
  208.     zerocentury = yyyy \ 100
  209.     result = (dd + INT(13 * (mm + 1) / 5) + century + INT(century / 4) + INT(zerocentury / 4) + 5 * zerocentury) MOD 7
  210.     IF result = 0 THEN
  211.         GetDay = 7
  212.     ELSE
  213.         GetDay = result
  214.     END IF
  215.     'Function changed to return a numeric value instead of a string for this program
  216.     '    SELECT CASE result
  217.     '        CASE 7: GetDay$ = "Saturday"
  218.     '        CASE 1: GetDay$ = "Sunday"
  219.     '        CASE 2: GetDay$ = "Monday"
  220.     '        CASE 3: GetDay$ = "Tuesday"
  221.     '        CASE 4: GetDay$ = "Wednesday"
  222.     '        CASE 5: GetDay$ = "Thursday"
  223.     '        CASE 6: GetDay$ = "Friday"
  224.     '    END SELECT
  225.  


Note: You'll need the resource files for it to work as intended, and those can be downloaded from the links at top, bottom or here: https://1drv.ms/u/s!AknUrv8RXVYMkIMiwSDNKinhlbfuHg?e=6eumhM

Note 2: If you don't have the resource files, you'll need to build your own in the subfolders so you can have pretty little images to work with, such as the screenshot below:

 
Steve's Calendar.png



Note 3: I don't swear all the images in the folder are fully censored.  There's a small collection of 1088 images which I just grabbed out of a singular folder from one of my drives, and some of them may be NSFW.  There's no porn, or any such thing in there, but different folks have different artistic standards and some may view an image of the Roman statue of Venus and say, "Oh my gosh!  Not in my house!!"  If you're one of those folks, then simply don't download the resource pack, or else delete anything you find questionable.  There's nothing in it that I *personally* find inappropriate, but if my taste in "art" doesn't float your boat, feel free to replace anything with your own stuff.  :P



https://1drv.ms/u/s!AknUrv8RXVYMkIMiwSDNKinhlbfuHg?e=6eumhM
« Last Edit: January 05, 2021, 11:11:51 pm by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Calendar 2021
« Reply #1 on: December 24, 2020, 06:48:10 pm »
Also notice the few constants which are at the top of the program:

CONST ShowGrid = -1
CONST ShowYear = 0
CONST DesiredYear = 2021

Feel free to change those, if desired.  Personally, I have mine set to ShowYear = -1 (view a whole year at once), and then I've tossed in a simple little _PRINTIMAGE routine to print out the finished pages, and I've now got me a whole nice little set of calendars to tack up on my wall for the year.   ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Richard Frost

  • Seasoned Forum Regular
  • Posts: 316
  • Needle nardle noo. - Peter Sellers
    • View Profile
Re: Calendar 2021
« Reply #2 on: December 25, 2020, 03:13:23 am »
Code: QB64: [Select]
  1. ' 136 t1 = _LOADIMAGE(t$, 32)
  2. ' 137 IF t1 = -1 THEN _FREEIMAGE t1: GOTO redo
  3.  
  4. ' This bit caused me to wonder if an image that fails to load uses up memory, so
  5. ' I wrote the following test program.  Monitoring Task Manager tells me this code
  6. ' does not eat up memory.  If the line with _FREEIMAGE is commented in, an error is
  7. ' immediately generated, as I expected.
  8.  
  9. ' So, shouldn't line 137 be IF t1 >=-1 THEN GOTO redo?
  10.  
  11. ' I suppose your images are all present and readable, so you don't generate an error.
  12.  
  13. DEFLNG A-Z
  14.     i = _LOADIMAGE("leftover bacon.jpg", 32)
  15.     'IF i = -1 THEN _FREEIMAGE i
  16.     _DELAY .01
  17.  
It works better if you plug it in.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Calendar 2021
« Reply #3 on: December 25, 2020, 10:46:51 pm »
So, never one to be satisfied with something, I'm still tinkering around with this little project, converting it from what was just a calendar to what is now steadily on the way to also becoming a day planner...

Code: QB64: [Select]
  1. CONST ShowGrid = -1
  2. CONST ShowYear = 0
  3. CONST DesiredYear = 2021
  4. CONST ShowDays = -1
  5.  
  6. SCREEN _NEWIMAGE(1600, 720, 32)
  7.  
  8.  
  9. TYPE Sun_Data_type
  10.     value AS STRING
  11.  
  12. REDIM SHARED Sun(0) AS Sun_Data_type
  13. DIM SHARED f: f = _LOADFONT("OLDENGL.ttf", 72)
  14. DIM SHARED f1: f1 = _LOADFONT("OLDENGL.ttf", 32)
  15. DIM SHARED ThisMonth, Today, ThisYear
  16. DIM SHARED BackGrounds(1 TO 12)
  17. DIM Lat AS _FLOAT, Lon AS _FLOAT
  18.  
  19. ThisMonth = VAL(DATE$)
  20. Today = VAL(MID$(DATE$, 4))
  21. ThisYear = VAL(RIGHT$(DATE$, 4))
  22.  
  23. Lat_Long Lat, Lon, 0 'get latitude and longitude, but no need to force them to redownload over and over,
  24. '                     if we already have them saved on the disk.
  25.  
  26. SunStuff Lat, Lon, ThisMonth, Today, ThisYear
  27.  
  28. TitleScreen
  29.  
  30. IF ShowYear THEN
  31.     FOR i = 1 TO 12
  32.         CLS , SkyBlue
  33.         _PUTIMAGE (0, 0)-(1283, 720), BackGrounds(i)
  34.         IF ShowGrid THEN DrawLines
  35.         CenterMonth i, DesiredYear
  36.         DrawDays i, DesiredYear
  37.         ShowDailyStuff Lat, Lon
  38.         SLEEP
  39.     NEXT
  40.     CLS , SkyBlue
  41.     _PUTIMAGE (0, 0)-(1283, 720), BackGrounds(1)
  42.     IF ShowGrid THEN DrawLines
  43.     CenterMonth ThisMonth, ThisYear
  44.     DrawDays ThisMonth, ThisYear
  45.     ShowDailyStuff Lat, Lon
  46.     SLEEP
  47.  
  48.  
  49.  
  50. SUB ShowDailyStuff (Lat AS _FLOAT, Lon AS _FLOAT)
  51.     _FONT f1
  52.     COLOR Black
  53.     LINE (1320, 50)-(1560, 500), Gold, BF
  54.  
  55.     cp = 1280 + (1600 - 1280) \ 2 'center of our non-calendar area
  56.     t$ = ConvertToDay(GetDay(ThisMonth, Today, ThisYear)): _PRINTSTRING (cp - _PRINTWIDTH(t$) \ 2, 60), t$
  57.     t$ = DATE$: _PRINTSTRING (cp - _PRINTWIDTH(t$) \ 2, 95), t$
  58.     _FONT 16
  59.     t$ = "For Lat/Long:" + STR$(INT(100 * Lat) / 100) + "," + STR$(INT(100 * Lon) / 100)
  60.     _PRINTSTRING (1325, 130), t$
  61.     _PRINTSTRING (1325, 156), "Sun Rise  : " + Sun(1).value
  62.     _PRINTSTRING (1325, 174), "Sun Set   : " + Sun(2).value
  63.     _PRINTSTRING (1325, 192), "Solar Noon: " + Sun(3).value
  64.     _PRINTSTRING (1325, 210), "Day Length: " + Sun(4).value
  65.     _PRINTSTRING (1325, 228), "Moon Phase:" + MoonPhase$(month, day, year)
  66.     COLOR White
  67.     _FONT f
  68.     EXIT SUB
  69.  
  70.  
  71.  
  72.  
  73.  
  74. SUB TitleScreen
  75.     _TITLE "Steve's Calendar"
  76.     CLS , SkyBlue
  77.     _FONT f
  78.     text$ = "Steve's Calendar"
  79.     pw = _PRINTWIDTH(text$) \ 2
  80.     _PRINTSTRING (640 - pw, 200), text$
  81.     IF ShowYear THEN
  82.         text$ = _TRIM$(STR$(DesiredYear))
  83.     ELSE
  84.         text$ = _TRIM$(STR$(ThisYear))
  85.     END IF
  86.     pw = _PRINTWIDTH(text$) \ 2
  87.     _PRINTSTRING (640 - pw, 300), text$
  88.     GetBackgrounds
  89.     _FONT 16
  90.     COLOR Black
  91.     text$ = "Press <ANY KEY> to continue."
  92.     pw = _PRINTWIDTH(text$) \ 2
  93.     _PRINTSTRING (640 - pw, 400), text$
  94.     COLOR White
  95.     _FONT f
  96.     SLEEP 2
  97.  
  98.  
  99. SUB GetHolidays (month, day, holiday() AS STRING)
  100.     REDIM holiday(0) AS STRING
  101.     SELECT CASE month
  102.         CASE 1
  103.             SELECT CASE day
  104.                 CASE 1: REDIM holiday(1) AS STRING: holiday(1) = "New Years Day"
  105.                 CASE 6: REDIM holiday(1) AS STRING: holiday(1) = "Epiphany"
  106.             END SELECT
  107.         CASE 2
  108.             SELECT CASE day
  109.                 CASE 1: REDIM holiday(1) AS STRING: holiday(1) = "Black History Month"
  110.                 CASE 2: REDIM holiday(1) AS STRING: holiday(1) = "Groundhog Day"
  111.                 CASE 14: REDIM holiday(1) AS STRING: holiday(1) = "Valentine's Day"
  112.             END SELECT
  113.         CASE 3
  114.             SELECT CASE day
  115.                 CASE 1: REDIM holiday(1) AS STRING: holiday(1) = "Women's History Month"
  116.             END SELECT
  117.         CASE 4
  118.             SELECT CASE day
  119.                 CASE 15: REDIM holiday(1) AS STRING: holiday(1) = "Tax Day"
  120.             END SELECT
  121.         CASE 5
  122.             SELECT CASE day
  123.             END SELECT
  124.         CASE 6
  125.             SELECT CASE day
  126.             END SELECT
  127.         CASE 7
  128.             SELECT CASE day
  129.                 CASE 4: REDIM holiday(1) AS STRING: holiday(1) = "Independence Day"
  130.             END SELECT
  131.         CASE 8
  132.             SELECT CASE day
  133.             END SELECT
  134.         CASE 9
  135.             SELECT CASE day
  136.                 CASE 25: REDIM holiday(1) AS STRING: holiday(1) = "Steve's Birthday"
  137.             END SELECT
  138.         CASE 10
  139.             SELECT CASE day
  140.                 CASE 31: REDIM holiday(1) AS STRING: holiday(1) = "Halloween"
  141.             END SELECT
  142.         CASE 11
  143.             SELECT CASE day
  144.                 CASE 1: REDIM holiday(1) AS STRING: holiday(1) = "All Saint's Day"
  145.                 CASE 2: REDIM holiday(1) AS STRING: holiday(1) = "All Soul's Day"
  146.                 CASE 11: REDIM holiday(1) AS STRING: holiday(1) = "Vetern's Day"
  147.             END SELECT
  148.         CASE 12
  149.             SELECT CASE day
  150.                 CASE 7: REDIM holiday(1) AS STRING: holiday(1) = "Pearl Harbor Remembrance"
  151.                 CASE 24: REDIM holiday(1) AS STRING: holiday(1) = "Christmas Eve"
  152.                 CASE 25: REDIM holiday(1) AS STRING: holiday(1) = "Christmas"
  153.                 CASE ELSE: REDIM holiday(0) AS STRING
  154.             END SELECT
  155.     END SELECT
  156.  
  157.  
  158. SUB GetBackgrounds
  159.     IF ShowYear THEN limit = 12 ELSE limit = 1
  160.     FOR i = 1 TO limit
  161.         redo:
  162.         t = INT(RND * 1088) + 1
  163.         FOR j = 1 TO i
  164.             IF BackGrounds(j) = t GOTO redo
  165.             t$ = ".\Backgrounds\" + _TRIM$(STR$(t)) + ".jpg"
  166.             t1 = _LOADIMAGE(t$, 32)
  167.             IF t1 = -1 THEN GOTO redo
  168.         NEXT
  169.         BackGrounds(i) = t1
  170.     NEXT
  171.  
  172. SUB CenterMonth (month, year)
  173.     _FONT f
  174.     SELECT CASE month
  175.         CASE 1: text$ = "January"
  176.         CASE 2: text$ = "February"
  177.         CASE 3: text$ = "March"
  178.         CASE 4: text$ = "April"
  179.         CASE 5: text$ = "May"
  180.         CASE 6: text$ = "June"
  181.         CASE 7: text$ = "July"
  182.         CASE 8: text$ = "August"
  183.         CASE 9: text$ = "September"
  184.         CASE 10: text$ = "October"
  185.         CASE 11: text$ = "November"
  186.         CASE 12: text$ = "December"
  187.     END SELECT
  188.     text$ = text$ + STR$(year)
  189.     pw = _PRINTWIDTH(text$) / 2
  190.     _PRINTSTRING (640 - pw, 0), text$
  191.  
  192.  
  193. SUB DrawLines
  194.     TopOffset = 72
  195.  
  196.     IF ShowDays THEN
  197.         LINE (0, TopOffset)-STEP(1280, 3), _RGBA(128, 128, 64, 160), BF
  198.         FOR i = 0 TO 7
  199.             LINE (i * 1280 / 7, 0 + TopOffset)-STEP(3, 40), _RGBA32(128, 128, 64, 160), BF
  200.         NEXT
  201.         TopOffset = TopOffset + 40
  202.     END IF
  203.     FOR i = 0 TO 6
  204.         LINE (0, i * 90 + TopOffset)-STEP(1280, 3), _RGBA32(128, 128, 64, 160), BF
  205.     NEXT
  206.     FOR i = 0 TO 7
  207.         LINE (i * 1280 / 7, 0 + TopOffset)-STEP(3, 540), _RGBA32(128, 128, 64, 160), BF
  208.     NEXT
  209.  
  210. FUNCTION ConvertToDay$ (day) 'Function to return a string for a day
  211.     SELECT CASE day
  212.         CASE 1: ConvertToDay$ = "Sunday"
  213.         CASE 2: ConvertToDay$ = "Monday"
  214.         CASE 3: ConvertToDay$ = "Tuesday"
  215.         CASE 4: ConvertToDay$ = "Wednesday"
  216.         CASE 5: ConvertToDay$ = "Thursday"
  217.         CASE 6: ConvertToDay$ = "Friday"
  218.         CASE 7: ConvertToDay$ = "Saturday"
  219.     END SELECT
  220.  
  221. SUB DrawDays (month, year)
  222.     SHARED highlightday
  223.     REDIM Holidays(0) AS STRING
  224.     TopOffset = 76
  225.     IF ShowDays THEN
  226.         _FONT f1
  227.         bw = 1280 \ 7
  228.         FOR i = 1 TO 7
  229.             t$ = ConvertToDay(i)
  230.             pw = _PRINTWIDTH(t$) \ 2
  231.             _PRINTSTRING (bw * (i - 1) + bw \ 2 - pw, 80), t$
  232.         NEXT
  233.         TopOffset = TopOffset + 40
  234.         _FONT f
  235.     END IF
  236.  
  237.     nod = NumberOfDays(month, year)
  238.     y = 0
  239.     FOR i = 1 TO nod
  240.         text$ = _TRIM$(STR$(i))
  241.         pw = _PRINTWIDTH(text$)
  242.         x = GetDay(month, i, year)
  243.         IF month = ThisMonth AND i = Today AND ThisYear = year THEN LINE ((x - 1) * 1280 / 7 + 3, y * 90 + TopOffset)-STEP(1280 / 7 - 3, 86), _RGBA32(128, 128, 128, 128), BF
  244.         _PRINTSTRING (x * 1280 / 7 - pw, y * 90 + TopOffset), text$
  245.         GetHolidays month, i, Holidays()
  246.         u = UBOUND(holidays)
  247.         IF u > 0 THEN
  248.             _FONT 8
  249.             FOR j = 1 TO u
  250.                 pw = _PRINTWIDTH(Holidays(j))
  251.                 _PRINTSTRING ((x - 1) * 1280 / 7 + 4, (y + 1) * 90 + TopOffset - 5 - j * 8), Holidays(j)
  252.             NEXT
  253.             _FONT f
  254.         END IF
  255.  
  256.         IF x = 7 THEN y = y + 1
  257.     NEXT
  258.  
  259.  
  260. FUNCTION NumberOfDays (month, year)
  261.     SELECT CASE month
  262.         CASE 1, 3, 5, 7, 8, 10, 12: NumberOfDays = 31
  263.         CASE 2: IF IsLeapYear(year) THEN NumberOfDays = 29 ELSE NumberOfDays = 28
  264.         CASE 4, 6, 9, 11: NumberOfDays = 30
  265.     END SELECT
  266.  
  267.  
  268. FUNCTION IsLeapYear (yyyy) 'use 4 digit year
  269.     IF GetDay(2, 29, yyyy) <> GetDay(3, 1, yyyy) THEN IsLeapYear = -1
  270.  
  271. FUNCTION GetDay (m, d, y) 'use 4 digit year
  272.     'From Zeller's congruence: https://en.wikipedia.org/wiki/Zeller%27s_congruence
  273.     mm = m: dd = d: yyyy = y
  274.     IF mm < 3 THEN mm = mm + 12: yyyy = yyyy - 1
  275.     century = yyyy MOD 100
  276.     zerocentury = yyyy \ 100
  277.     result = (dd + INT(13 * (mm + 1) / 5) + century + INT(century / 4) + INT(zerocentury / 4) + 5 * zerocentury) MOD 7
  278.     IF result = 0 THEN
  279.         GetDay = 7
  280.     ELSE
  281.         GetDay = result
  282.     END IF
  283.     'Function changed to return a numeric value instead of a string for this program
  284.     '    SELECT CASE result
  285.     '        CASE 7: GetDay$ = "Saturday"
  286.     '        CASE 1: GetDay$ = "Sunday"
  287.     '        CASE 2: GetDay$ = "Monday"
  288.     '        CASE 3: GetDay$ = "Tuesday"
  289.     '        CASE 4: GetDay$ = "Wednesday"
  290.     '        CASE 5: GetDay$ = "Thursday"
  291.     '        CASE 6: GetDay$ = "Friday"
  292.     '    END SELECT
  293.  
  294.  
  295. FUNCTION GetPublicIP$ (force)
  296.     STATIC f
  297.     IF force = -1 OR _FILEEXISTS("PIP.txt") = 0 THEN
  298.         OPEN "PIP.txt" FOR OUTPUT AS #f: CLOSE f
  299.         SHELL _HIDE "cmd /c nslookup myip.opendns.com resolver1.opendns.com>tempPIP.txt"
  300.     END IF
  301.     f = FREEFILE
  302.     OPEN "tempPIP.txt" FOR INPUT AS #f
  303.     IF LOF(f) THEN
  304.         DO
  305.             LINE INPUT #f, temp$
  306.             IF temp$ <> "" THEN last$ = temp$ 'there's a blank line after the data we need.
  307.             '                                 Ignore it.  What we want is the last line of info generated here.
  308.         LOOP UNTIL EOF(1)
  309.         l = _INSTRREV(last$, "Address:")
  310.         IF l THEN GetPublicIP$ = MID$(last$, l + 10)
  311.     END IF
  312.     CLOSE f
  313.  
  314.  
  315. SUB Lat_Long (lat AS _FLOAT, lon AS _FLOAT, force)
  316.     STATIC f
  317.     ip$ = GetPublicIP$(0)
  318.     IF force = -1 OR _FILEEXISTS("LatAndLong.txt") = 0 THEN
  319.         DownloadURL "ip-api.com/line/" + ip$ + "?fields=lat,lon", "LatAndLong.txt"
  320.     END IF
  321.     f = FREEFILE
  322.     OPEN "LatAndLong.txt" FOR INPUT AS #f
  323.     IF LOF(f) = 0 THEN CLOSE f: EXIT SUB 'something didn't download.  this info isn't available to parse.
  324.     INPUT #f, lat
  325.     INPUT #f, lon
  326.     CLOSE f
  327.  
  328. SUB DownloadURL (link$, file$)
  329.     STATIC f
  330.     f = FREEFILE
  331.     OPEN file$ FOR OUTPUT AS #f: CLOSE #f 'erase any old file of the same name
  332.     $IF WIN THEN
  333.         out$ = "powershell.exe -c " + CHR$(34) + "Invoke-Webrequest '" + link$ + "' -OutFile '" + file$ + "'" + CHR$(34)
  334.     $ELSE
  335.         out$ = "wget " + chr$(34) + link$ + " -O " + file$ + chr$(34)
  336.     $END IF
  337.     SHELL _HIDE out$
  338.  
  339. FUNCTION GetHour (fromTime$) 'time should be hh:mm:ss WhateverM
  340.     l = INSTR(fromTime$, ":") '1st :
  341.     GetHour = VAL(LEFT$(fromTime$, l))
  342.  
  343. FUNCTION GetMinute (fromTime$) 'time should be hh:mm:ss WhateverM
  344.     l = INSTR(fromTime$, ":") '1st :
  345.     GetMinute = VAL(MID$(fromTime$, l + 1))
  346.  
  347.  
  348. FUNCTION GetSecond (fromTime$) 'time should be hh:mm:ss WhateverM
  349.     l = INSTR(fromTime$, ":") '1st :
  350.     l = INSTR(l + 1, fromTime$, ":") '2nd :
  351.     GetSecond = VAL(MID$(fromTime$, l + 1))
  352.  
  353.  
  354. FUNCTION GetTimeOffset
  355.     $IF WIN THEN
  356.         TYPE SYSTEMTIME
  357.             wYear AS _UNSIGNED INTEGER
  358.             wMonth AS _UNSIGNED INTEGER
  359.             wDayOfWeek AS _UNSIGNED INTEGER
  360.             wDay AS _UNSIGNED INTEGER
  361.             wHour AS _UNSIGNED INTEGER
  362.             wMinute AS _UNSIGNED INTEGER
  363.             wSecond AS _UNSIGNED INTEGER
  364.             wMilliseconds AS _UNSIGNED INTEGER
  365.         END TYPE
  366.  
  367.         TYPE TIME_ZONE_INFORMATION
  368.             Bias AS LONG
  369.             StandardName AS STRING * 64 'WCHAR      StandardName[32];
  370.             StandardDate AS SYSTEMTIME
  371.             StandardBias AS LONG
  372.             DaylightName AS STRING * 64 'WCHAR      DaylightName[32];
  373.             DaylightDate AS SYSTEMTIME
  374.             DaylightBias AS LONG
  375.         END TYPE
  376.  
  377.         DECLARE DYNAMIC LIBRARY "Kernel32"
  378.             SUB GetTimeZoneInformation (t AS TIME_ZONE_INFORMATION)
  379.         END DECLARE
  380.  
  381.         DIM t AS TIME_ZONE_INFORMATION
  382.         GetTimeZoneInformation t
  383.         GetTimeOffset = t.Bias
  384.     $END IF
  385.  
  386.  
  387.  
  388. SUB SunStuff (lat, lon, month, day, year)
  389.     STATIC f
  390.     d$ = _TRIM$(STR$(year)) + _TRIM$(STR$(month)) + _TRIM$(STR$(day))
  391.     link$ = "https://api.sunrise-sunset.org/json?lat=" + _TRIM$(STR$(lat)) + "&lng="
  392.     link$ = link$ + _TRIM$(STR$(lon)) + "&date=" + d$
  393.     DownloadURL link$, "temp.txt"
  394.     f = FREEFILE
  395.     OPEN "temp.txt" FOR BINARY AS #f
  396.  
  397.     IF LOF(f) = 0 THEN CLOSE f: EXIT SUB 'something didn't download.  this info isn't available to parse.
  398.  
  399.     t$ = SPACE$(LOF(f))
  400.     GET #1, 1, t$
  401.     CLOSE f
  402.  
  403.     'strip off unwanted stuff
  404.     l = INSTR(t$, ":{"): t$ = MID$(t$, l + 2) 'junk left of our initial data
  405.     DO
  406.         l = INSTR(t$, CHR$(34))
  407.         t$ = LEFT$(t$, l - 1) + MID$(t$, l + 1) 'remove all quotes completely from this data
  408.     LOOP UNTIL l = 0
  409.     DO
  410.         l = INSTR(t$, "_")
  411.         t$ = LEFT$(t$, l - 1) + " " + MID$(t$, l + 1) 'change all underscores to spaces in this data
  412.     LOOP UNTIL l = 0
  413.     t$ = _TRIM$(t$)
  414.     t$ = LEFT$(t$, LEN(t$) - 12) 'remove the last end of data }
  415.     PRINT t$
  416.  
  417.     'parse it down to field, data
  418.     DO
  419.         l = INSTR(t$, ",")
  420.         IF l = 0 THEN EXIT DO
  421.         count = count + 1
  422.         REDIM _PRESERVE Sun(count) AS Sun_Data_type
  423.         whole$ = LEFT$(t$, l)
  424.         Sun(count).field = LEFT$(whole$, INSTR(whole$, ":") - 1)
  425.         r$ = MID$(whole$, INSTR(whole$, ":") + 1)
  426.         r$ = LEFT$(r$, LEN(r$) - 1)
  427.         IF RIGHT$(r$, 1) = "M" THEN m$ = RIGHT$(r$, 3) ELSE m$ = ""
  428.         h = GetHour(r$): m = GetMinute(r$): s = GetSecond(r$)
  429.         IF m$ = " PM" AND h <> 12 THEN h = h + 12
  430.         IF count <> 4 THEN
  431.             h = h - GetTimeOffset / 60
  432.             IF h < 0 THEN h = 24 + h 'adjust for AM/PM difference, if ever necessary
  433.             IF h > 23 THEN h = h - 24 'adjust for AM/PM difference, if ever necessary
  434.             SELECT CASE h
  435.                 CASE 0: h = 12: m$ = " AM"
  436.                 CASE 12: m$ = " PM"
  437.                 CASE IS > 12: h = h - 12: m$ = " PM"
  438.                 CASE ELSE: m$ = " AM"
  439.             END SELECT
  440.         END IF
  441.         hour$ = _TRIM$(STR$(h)): IF LEN(hour$) = 1 THEN hour$ = "0" + hour$
  442.         min$ = _TRIM$(STR$(m)): IF LEN(min$) = 1 THEN min$ = "0" + min$
  443.         sec$ = _TRIM$(STR$(s)): IF LEN(sec$) = 1 THEN sec$ = "0" + sec$
  444.         Sun(count).value = hour$ + ":" + min$ + ":" + sec$ + m$
  445.         t$ = MID$(t$, l + 1)
  446.     LOOP
  447.  
  448.  
  449. FUNCTION MoonPhase$ (month, day, year)
  450.     DIM mooncycle AS _FLOAT
  451.     DIM fullmoon AS _FLOAT, dp AS _FLOAT, sod AS _FLOAT
  452.     mooncycle = 29.5305882 'days between moon rotations
  453.     sod = 24 * 60 * 60 'number of seconds in a day
  454.  
  455.     m$ = _TRIM$(STR$(month))
  456.     d$ = _TRIM$(STR$(day))
  457.     y$ = _TRIM$(STR$(year))
  458.     dt$ = m$ + "-" + d$ + "-" + y$
  459.     guessmoon = TimeStamp(dt$, 23 * 3600 + 59 * 60 + 59) 'what is the moon at 11:59:59 PM
  460.     fullmoon = TimeStamp("1-3-2020", 4 * 3600 + 46 * 60) ' full moon on 1-3-2020 at 4:46 AM UTC
  461.     dp = (guessmoon - fullmoon) / sod 'days past our full moon
  462.     r1 = dp - INT(dp / mooncycle) * mooncycle 'how far we are in repeating our rotation
  463.     SELECT CASE r1
  464.         CASE IS <= mooncycle / 4: MoonPhase$ = "1st Quarter"
  465.         CASE IS <= mooncycle / 2: MoonPhase$ = "Full moon"
  466.         CASE IS <= mooncycle * 3 / 4: MoonPhase$ = "3rd Quarter"
  467.         CASE ELSE: MoonPhase$ = "New Moon"
  468.     END SELECT
  469.  
  470.  
  471.  
  472. FUNCTION TimeStamp## (d$, t##) 'date and timer
  473.     'Based on Unix Epoch time, which starts at year 1970.
  474.     DIM s AS _FLOAT
  475.  
  476.     l = INSTR(d$, "-")
  477.     l1 = INSTR(l + 1, d$, "-")
  478.     m = VAL(LEFT$(d$, l))
  479.     d = VAL(MID$(d$, l + 1))
  480.     y = VAL(MID$(d$, l1 + 1))
  481.     IF y < 1970 THEN 'calculate shit backwards
  482.         SELECT CASE m 'turn the day backwards for the month
  483.             CASE 1, 3, 5, 7, 8, 10, 12: d = 31 - d '31 days
  484.             CASE 2: d = 28 - d 'special 28 or 29.
  485.             CASE 4, 6, 9, 11: d = 30 - d '30 days
  486.         END SELECT
  487.         IF y MOD 4 = 0 AND m < 3 THEN 'check for normal leap year, and we're before it...
  488.             d = d + 1 'assume we had a leap year, subtract another day
  489.             IF y MOD 100 = 0 AND y MOD 400 <> 0 THEN d = d - 1 'not a leap year if year is divisible by 100 and not 400
  490.         END IF
  491.  
  492.         'then count the months that passed after the current month
  493.         FOR i = m + 1 TO 12
  494.             SELECT CASE i
  495.                 CASE 2: d = d + 28
  496.                 CASE 3, 5, 7, 8, 10, 12: d = d + 31
  497.                 CASE 4, 6, 9, 11: d = d + 30
  498.             END SELECT
  499.         NEXT
  500.  
  501.         'we should now have the entered year calculated.  Now lets add in for each year from this point to 1970
  502.         d = d + 365 * (1969 - y) '365 days per each standard year
  503.         FOR i = 1968 TO y + 1 STEP -4 'from 1968 onwards,backwards, skipping the current year (which we handled previously in the FOR loop)
  504.             d = d + 1 'subtract an extra day every leap year
  505.             IF (i MOD 100) = 0 AND (i MOD 400) <> 0 THEN d = d - 1 'but skipping every year divisible by 100, but not 400
  506.         NEXT
  507.         s## = d * 24 * 60 * 60 'Seconds are days * 24 hours * 60 minutes * 60 seconds
  508.         TimeStamp## = -(s## + 24 * 60 * 60 - t##)
  509.         EXIT FUNCTION
  510.     ELSE
  511.         y = y - 1970
  512.     END IF
  513.  
  514.     FOR i = 1 TO m 'for this year,
  515.         SELECT CASE i 'Add the number of days for each previous month passed
  516.             CASE 1: d = d 'January doestn't have any carry over days.
  517.             CASE 2, 4, 6, 8, 9, 11: d = d + 31
  518.             CASE 3 'Feb might be a leap year
  519.                 IF (y MOD 4) = 2 THEN 'if this year is divisible by 4 (starting in 1972)
  520.                     d = d + 29 'its a leap year
  521.                     IF (y MOD 100) = 30 AND (y MOD 400) <> 30 THEN 'unless..
  522.                         d = d - 1 'the year is divisible by 100, and not divisible by 400
  523.                     END IF
  524.                 ELSE 'year not divisible by 4, no worries
  525.                     d = d + 28
  526.                 END IF
  527.             CASE 5, 7, 10, 12: d = d + 30
  528.         END SELECT
  529.     NEXT
  530.     d = (d - 1) + 365 * y 'current month days passed + 365 days per each standard year
  531.     FOR i = 2 TO y - 1 STEP 4 'from 1972 onwards, skipping the current year (which we handled previously in the FOR loopp)
  532.         d = d + 1 'add an extra day every leap year
  533.         IF (i MOD 100) = 30 AND (i MOD 400) <> 30 THEN d = d - 1 'but skiping every year divisible by 100, but not 400
  534.     NEXT
  535.     s## = d * 24 * 60 * 60 'Seconds are days * 24 hours * 60 minutes * 60 seconds
  536.     TimeStamp## = (s## + t##)
  537.  

Use the same resource file above, and save this source in the Calendar directory before compiling it.  I can't see redoing the whole archive while this is still a definite work-in-progress, but I thought I'd go ahead and share what it looks like for now.

 
Steve's Calendar.png


From this point, I'm going to externalize the holidays and also add events to the program, which the user can then add or edit with a few simple keystrokes or mouse clicks.  In the free space below our sun/moon information, there's room for me to display events such as:

Doctor's Appointment 2:45
Take dog to vet 4:25

I'm also thinking of scrolling daily news events to keep it vibrant and active, as well as possibly downloading the current weather conditions and forecast for the day from the web...

A project with a change from a simple calendar to print out and tack on the wall (though that will still be possible), to a full fledged scheduling tool.   
« Last Edit: December 25, 2020, 10:52:35 pm by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Calendar 2021
« Reply #4 on: December 26, 2020, 05:36:00 am »
I've got my holiday list now, and it's format is finalized.  See if this seems simple enough to add to, and if there's anything obvious which I'm missing on here:

Code: [Select]
Holidays are stored in the format:   MONTH, Modifier, Day, Name
01, ON, 01, New Years Day
01, ON, 06, Epiphany
01, ON, 07, Orthodox Christmas Day
01, ON, 13, Stephen Foster Memorial Day
01, ON, 14, Orthodox New Year
01, THIRD, Monday, Martin Luther King Day
02, ON, 01, National Freedom Day
02, ON, 01, Start of Black History Month
02, ON, 02, Groundhog's Day
02, FIRST, Sunday, Super Bowl
02, ON, 12, Lincoln's Birthday
02, ON, 14, Valentine's Day
02, THIRD, Monday, President's Day
03, ON, 01, Start of Women's History Month
03, SECOND, Sunday, Start of Daylight Saving's Time
03, ON, 17, Saint Patrick's Day
03, ON, 29, National Vietnam War Vetern's Day
05, SECOND, Sunday, Mother's Day
05, LAST, Monday, Memorial Day
06, THIRD, Sunday, Father's Day
07, ON, 04, Independence Day
07, ON, 15, Tax Day
09, FIRST, Monday, Labor Day
09, ON, 25, Steve McNeill's Birthday
10, ON, 31, Halloween
11, ON, 01, All Saint's Day
11, FIRST, Sunday, End of Daylight Saving's Time
11, ON, 02, All Soul's Day
11, ON, 11, Vetern's Day
11, FOURTH, Thursday, Thanksgiving
12, ON, 07, Pearl Harbor Remembrance Day
12, ON, 24, Christmas Eve
12, ON, 25, Christmas Day
12, ON, 31, New Year's Eve

There's a few things which I know I missed, which are like Black Friday -- Friday after Thanksgiving...  Well, Thanksgiving is a moving target (fourth thursday in november), and Black Friday isn't necessarily the 4th friday in november.  (For example, Nov 1st is a friday, then the first thursday would be on the 7th, and thanksgiving on the 28th...  The 4th friday, in this case, would be on the 22nd...)

Days that are in relation to other days are something which are a little more complex to incorporate, and I'm not bothering with them at this time.  Holidays ON, on in relation to a month itself, are are I'm bothering with, at the moment.  ;)

Anyone see anything I missed?  Or something which seems wrong?  I'll be working this file into my little program for the next version, so if anyone has any thoughts or suggestions on it, now's the time to speak up and mention them.  :D
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Calendar 2021
« Reply #5 on: December 26, 2020, 05:56:16 am »
Is it too soon to mention Easter?

I know, that one's a floater - but Kepler cracked it centuries ago... If the calculation is too tedious, I would just go grab a table.
You're not done when it works, you're done when it's right.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Calendar 2021
« Reply #6 on: December 26, 2020, 06:16:25 am »
Quote
Days that are in relation to other days are something which are a little more complex to incorporate, and I'm not bothering with them at this time.

Easter, Ash Wednesday, Good Friday, the seasons are all on this list.  Those are individual entries which will need some unique tweaking to work properly for us, but I'll probably end up sorting out some way to stick them in there before I'm all finished.  For now, it's one simple little alteration and addition at a time.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Calendar 2021
« Reply #7 on: December 26, 2020, 06:25:52 am »
Here's a little test code to calculate and spit out the holidays from the list above for us.  Test it out and see if everything matches up like it should for us.

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2.  
  3. TYPE Holiday_type
  4.     month AS INTEGER
  5.     day AS INTEGER
  6.     name AS STRING
  7.  
  8. REDIM SHARED HolidayList(0) AS Holiday_type
  9.  
  10.  
  11. GetHolidays 2021
  12. FOR i = 1 TO UBOUND(HolidayList)
  13.     PRINT HolidayList(i).month, HolidayList(i).day, HolidayList(i).name
  14.  
  15. SUB GetHolidays (year)
  16.     f = FREEFILE
  17.     IF _FILEEXISTS("Holidays.txt") = 0 THEN 'if the file doesn't exist, then create it with our default data
  18.         OPEN "Holidays.txt" FOR OUTPUT AS #f
  19.         PRINT #f, "Holidays are stored in the format:   MONTH, Modifier, Day, Name"
  20.         PRINT #f, "01, ON, 01, New Years Day"
  21.         PRINT #f, "01, ON, 06, Epiphany"
  22.         PRINT #f, "01, ON, 07, Orthodox Christmas Day"
  23.         PRINT #f, "01, ON, 13, Stephen Foster Memorial Day"
  24.         PRINT #f, "01, ON, 14, Orthodox New Year"
  25.         PRINT #f, "01, THIRD, Monday, Martin Luther King Day"
  26.         PRINT #f, "02, ON, 01, National Freedom Day"
  27.         PRINT #f, "02, ON, 01, Start of Black History Month"
  28.         PRINT #f, "02, ON, 02, Groundhog's Day"
  29.         PRINT #f, "02, FIRST, Sunday, Super Bowl"
  30.         PRINT #f, "02, ON, 12, Lincoln's Birthday"
  31.         PRINT #f, "02, ON, 14, Valentine's Day"
  32.         PRINT #f, "02, THIRD, Monday, President's Day"
  33.         PRINT #f, "03, ON, 01, Start of Women's History Month"
  34.         PRINT #f, "03, SECOND, Sunday, Start of Daylight Saving's Time"
  35.         PRINT #f, "03, ON, 17, Saint Patrick's Day"
  36.         PRINT #f, "03, ON, 29, National Vietnam War Vetern's Day"
  37.         PRINT #f, "05, SECOND, Sunday, Mother's Day"
  38.         PRINT #f, "05, LAST, Monday, Memorial Day"
  39.         PRINT #f, "06, THIRD, Sunday, Father's Day"
  40.         PRINT #f, "07, ON, 04, Independence Day"
  41.         PRINT #f, "07, ON, 15, Tax Day"
  42.         PRINT #f, "09, FIRST, Monday, Labor Day"
  43.         PRINT #f, "09, ON, 25, Steve McNeill's Birthday"
  44.         PRINT #f, "10, ON, 31, Halloween"
  45.         PRINT #f, "11, ON, 01, All Saint's Day"
  46.         PRINT #f, "11, FIRST, Sunday, End of Daylight Saving's Time"
  47.         PRINT #f, "11, ON, 02, All Soul's Day"
  48.         PRINT #f, "11, ON, 11, Vetern's Day"
  49.         PRINT #f, "11, FOURTH, Thursday, Thanksgiving"
  50.         PRINT #f, "12, ON, 07, Pearl Harbor Remembrance Day"
  51.         PRINT #f, "12, ON, 24, Christmas Eve"
  52.         PRINT #f, "12, ON, 25, Christmas Day"
  53.         PRINT #f, "12, ON, 31, New Year's Eve"
  54.         CLOSE f
  55.     END IF
  56.     OPEN "Holidays.txt" FOR INPUT AS #f
  57.     LINE INPUT #f, junk$ 'first line is file comment and not related to the data
  58.     DO UNTIL EOF(f)
  59.         INPUT #f, month
  60.         INPUT #f, event$: event$ = UCASE$(event$)
  61.         INPUT #f, day$
  62.         INPUT #f, nam$
  63.         '  PRINT month, event$, day$, nam$
  64.         count = count + 1
  65.         REDIM _PRESERVE HolidayList(count) AS Holiday_type
  66.         HolidayList(count).month = month
  67.         IF event$ = "ON" THEN
  68.             HolidayList(count).day = VAL(day$)
  69.         ELSEIF event$ = "LAST" THEN 'we need to count backwards to find the last target day
  70.             d = ConvertDayToNum(day$)
  71.             FOR i = NumberOfDays(month, year) TO 1 STEP -1
  72.                 IF GetDay(month, i, year) = d THEN HolidayList(count).day = i: EXIT FOR
  73.             NEXT
  74.         ELSE 'we count forwards
  75.             d = ConvertDayToNum(day$)
  76.             FOR i = 1 TO NumberOfDays(month, year)
  77.                 IF GetDay(month, i, year) = d THEN EXIT FOR
  78.             NEXT
  79.             SELECT CASE event$
  80.                 CASE "FIRST": HolidayList(count).day = i
  81.                 CASE "SECOND": HolidayList(count).day = i + 7
  82.                 CASE "THIRD": HolidayList(count).day = i + 14
  83.                 CASE "FOURTH": HolidayList(count).day = i + 21
  84.                 CASE "FIFTH": HolidayList(count).day = i + 28
  85.             END SELECT
  86.         END IF
  87.         HolidayList(count).name = nam$
  88.     LOOP
  89.  
  90. FUNCTION ConvertDayToNum (day$)
  91.     SELECT CASE day$
  92.         CASE "Sunday": ConvertDayToNum = 1
  93.         CASE "Monday": ConvertDayToNum = 2
  94.         CASE "Tuseday": ConvertDayToNum = 3
  95.         CASE "Wednesday": ConvertDayToNum = 4
  96.         CASE "Thursday": ConvertDayToNum = 5
  97.         CASE "Friday": ConvertDayToNum = 6
  98.         CASE "Saturday": ConvertDayToNum = 7
  99.     END SELECT
  100.  
  101.  
  102. FUNCTION GetDay (m, d, y) 'use 4 digit year
  103.     'From Zeller's congruence: https://en.wikipedia.org/wiki/Zeller%27s_congruence
  104.     mm = m: dd = d: yyyy = y
  105.     IF mm < 3 THEN mm = mm + 12: yyyy = yyyy - 1
  106.     century = yyyy MOD 100
  107.     zerocentury = yyyy \ 100
  108.     result = (dd + INT(13 * (mm + 1) / 5) + century + INT(century / 4) + INT(zerocentury / 4) + 5 * zerocentury) MOD 7
  109.     IF result = 0 THEN
  110.         GetDay = 7
  111.     ELSE
  112.         GetDay = result
  113.     END IF
  114.  
  115. FUNCTION IsLeapYear (yyyy) 'use 4 digit year
  116.     IF GetDay(2, 29, yyyy) <> GetDay(3, 1, yyyy) THEN IsLeapYear = -1
  117.  
  118. FUNCTION NumberOfDays (month, year)
  119.     SELECT CASE month
  120.         CASE 1, 3, 5, 7, 8, 10, 12: NumberOfDays = 31
  121.         CASE 2: IF IsLeapYear(year) THEN NumberOfDays = 29 ELSE NumberOfDays = 28
  122.         CASE 4, 6, 9, 11: NumberOfDays = 30
  123.     END SELECT
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Calendar 2021
« Reply #8 on: December 26, 2020, 08:46:24 pm »
This whole calendar has now basically been reinvented in the way it operates.

Code: QB64: [Select]
  1. CONST ShowGrid = -1
  2. CONST ShowYear = 0
  3. CONST DesiredYear = 2021
  4. CONST ShowDays = -1
  5.  
  6. SCREEN _NEWIMAGE(1600, 720, 32)
  7.  
  8.  
  9. TYPE Sun_Data_type
  10.     value AS STRING
  11.  
  12.  
  13. TYPE Holiday_type
  14.     month AS INTEGER
  15.     day AS INTEGER
  16.     name AS STRING
  17.  
  18. REDIM SHARED Sun(0) AS Sun_Data_type
  19. REDIM SHARED HolidayList(0) AS Holiday_type
  20.  
  21. DIM SHARED f72: f72 = _LOADFONT("OLDENGL.ttf", 72)
  22. DIM SHARED f32: f32 = _LOADFONT("OLDENGL.ttf", 32)
  23. DIM SHARED ThisMonth, Today, ThisYear
  24. DIM SHARED BackGrounds(-12 TO 12)
  25. DIM Lat AS _FLOAT, Lon AS _FLOAT
  26.  
  27. ThisMonth = VAL(DATE$)
  28. Today = VAL(MID$(DATE$, 4))
  29. ThisYear = VAL(RIGHT$(DATE$, 4))
  30.  
  31. Lat_Long Lat, Lon, 0 'get latitude and longitude, but no need to force them to redownload over and over,
  32. '                     if we already have them saved on the disk.
  33.  
  34. SunStuff Lat, Lon, ThisMonth, Today, ThisYear
  35. GetHolidays ThisYear
  36.  
  37. TitleScreen
  38.  
  39.  
  40. update = -1
  41.  
  42.  
  43. CurrentMonth = ThisMonth
  44. CurrentDay = Today
  45. Currentyear = ThisYear
  46.  
  47.     IF update THEN
  48.         CLS , SkyBlue
  49.         reload: 'load our background
  50.         IF bg >= -12 AND bg <= 12 THEN
  51.             'We store 12 set backgrounds before and after our current month, which don't change.
  52.             'But if we go any further than that, then we just use random backgrounds for extreme future events.
  53.             'This is to give an impression of stability for most usage.
  54.             'For example, I start up with an image of the moon on the screen for my current month.
  55.             'I then scroll a few screens to see what is coming up in a few months, and then want to scroll back.
  56.             'All I have to do is look for that visual cue of the image of the moon on my screen, as a quick reference guide.
  57.  
  58.             t$ = ".\Backgrounds\" + _TRIM$(STR$(BackGrounds(bg))) + ".jpg"
  59.             t1 = _LOADIMAGE(t$, 32)
  60.             IF t1 = -1 THEN 'if this is a bad background, then load a different one
  61.                 redo:
  62.                 t = INT(RND * 1088) + 1
  63.                 FOR j = 1 TO i
  64.                     IF BackGrounds(j) = t GOTO redo
  65.                     IF t1 = -1 THEN GOTO redo
  66.                 NEXT
  67.                 BackGrounds(i) = t
  68.                 GOTO reload
  69.             END IF
  70.         ELSE
  71.             'But after a dozen months or so?  No need to keep those image handles in memory.  Just toss them,
  72.             'as my poor memory couldn't store that much information anyway.  :P
  73.  
  74.             DO
  75.                 t$ = ".\Backgrounds\" + _TRIM$(STR$(INT(RND * 1088) + 1)) + ".jpg"
  76.                 t1 = _LOADIMAGE(t$, 32)
  77.             LOOP UNTIL t1 < -1
  78.         END IF
  79.  
  80.         _PUTIMAGE (0, 0)-(1283, 720), t1
  81.         _FREEIMAGE t1
  82.         IF ShowGrid THEN DrawLines
  83.         CenterMonth CurrentMonth, Currentyear
  84.         DrawDays CurrentMonth, Currentyear
  85.         ShowDailyStuff Lat, Lon
  86.         update = 0
  87.     END IF
  88.  
  89.     k = _KEYHIT
  90.     IF _KEYDOWN(100305) OR _KEYDOWN(100306) THEN
  91.         SELECT CASE k
  92.             CASE 19200 'left
  93.                 CurrentMonth = CurrentMonth - 1
  94.                 IF CurrentMonth < 1 THEN CurrentMonth = 12: Currentyear = Currentyear - 1
  95.                 bg = bg - 1
  96.                 update = -1
  97.             CASE 19712 'right
  98.                 CurrentMonth = CurrentMonth + 1
  99.                 IF CurrentMonth > 12 THEN CurrentMonth = 1: Currentyear = Currentyear + 1
  100.                 bg = bg + 1
  101.                 update = -1
  102.         END SELECT
  103.     ELSE
  104.         SELECT CASE k
  105.             CASE 27 'ESC
  106.                 SYSTEM
  107.         END SELECT
  108.     END IF
  109.  
  110.     _LIMIT 30
  111.     _DISPLAY
  112.  
  113.  
  114.  
  115.  
  116. SUB ShowDailyStuff (Lat AS _FLOAT, Lon AS _FLOAT)
  117.     _FONT f32
  118.     COLOR Black
  119.     LINE (1320, 50)-(1560, 500), Gold, BF
  120.  
  121.     cp = 1280 + (1600 - 1280) \ 2 'center of our non-calendar area
  122.     t$ = ConvertToDay(GetDay(ThisMonth, Today, ThisYear)): _PRINTSTRING (cp - _PRINTWIDTH(t$) \ 2, 60), t$
  123.     t$ = DATE$: _PRINTSTRING (cp - _PRINTWIDTH(t$) \ 2, 95), t$
  124.     _FONT 16
  125.     t$ = "For Lat/Long:" + STR$(INT(100 * Lat) / 100) + "," + STR$(INT(100 * Lon) / 100)
  126.     _PRINTSTRING (1325, 130), t$
  127.     _PRINTSTRING (1325, 156), "Sun Rise  : " + Sun(1).value
  128.     _PRINTSTRING (1325, 174), "Sun Set   : " + Sun(2).value
  129.     _PRINTSTRING (1325, 192), "Solar Noon: " + Sun(3).value
  130.     _PRINTSTRING (1325, 210), "Day Length: " + Sun(4).value
  131.     _PRINTSTRING (1325, 228), "Moon Phase: " + MoonPhase$(month, day, year)
  132.     COLOR White
  133.     _FONT f72
  134.     EXIT SUB
  135.  
  136.  
  137.  
  138.  
  139.  
  140. SUB TitleScreen
  141.     _TITLE "Steve's Calendar"
  142.     CLS , SkyBlue
  143.     _FONT f72
  144.     text$ = "Steve's Calendar"
  145.     pw = _PRINTWIDTH(text$) \ 2
  146.     _PRINTSTRING (800 - pw, 200), text$
  147.     IF ShowYear THEN
  148.         text$ = _TRIM$(STR$(DesiredYear))
  149.     ELSE
  150.         text$ = _TRIM$(STR$(ThisYear))
  151.     END IF
  152.     pw = _PRINTWIDTH(text$) \ 2
  153.     _PRINTSTRING (800 - pw, 300), text$
  154.     GetBackgrounds
  155.     _FONT 16
  156.     COLOR Black
  157.     text$ = "Press <ANY KEY> to continue."
  158.     pw = _PRINTWIDTH(text$) \ 2
  159.     _PRINTSTRING (800 - pw, 400), text$
  160.     COLOR White
  161.     _FONT f72
  162.     SLEEP 2
  163.  
  164.  
  165. SUB GetHolidays (year)
  166.  
  167.  
  168.     f1 = FREEFILE
  169.     IF _FILEEXISTS("Holidays.txt") = 0 THEN 'if the file doesn't exist, then create it with our default data
  170.         OPEN "Holidays.txt" FOR OUTPUT AS #f1
  171.         PRINT #f1, "Holidays are stored in the format:   MONTH, Modifier, Day, Name"
  172.         PRINT #f1, "01, ON, 01, New Years Day"
  173.         PRINT #f1, "01, ON, 06, Epiphany"
  174.         PRINT #f1, "01, ON, 07, Orthodox Christmas Day"
  175.         PRINT #f1, "01, ON, 13, Stephen Foster Memorial Day"
  176.         PRINT #f1, "01, ON, 14, Orthodox New Year"
  177.         PRINT #f1, "01, THIRD, Monday, Martin Luther King Day"
  178.         PRINT #f1, "02, ON, 01, National Freedom Day"
  179.         PRINT #f1, "02, ON, 01, Start of Black History Month"
  180.         PRINT #f1, "02, ON, 02, Groundhog's Day"
  181.         PRINT #f1, "02, FIRST, Sunday, Super Bowl"
  182.         PRINT #f1, "02, ON, 12, Lincoln's Birthday"
  183.         PRINT #f1, "02, ON, 14, Valentine's Day"
  184.         PRINT #f1, "02, THIRD, Monday, President's Day"
  185.         PRINT #f1, "03, ON, 01, Start of Women's History Month"
  186.         PRINT #f1, "03, SECOND, Sunday, Start of Daylight Saving's Time"
  187.         PRINT #f1, "03, ON, 17, Saint Patrick's Day"
  188.         PRINT #f1, "03, ON, 29, National Vietnam War Vetern's Day"
  189.         PRINT #f1, "05, SECOND, Sunday, Mother's Day"
  190.         PRINT #f1, "05, LAST, Monday, Memorial Day"
  191.         PRINT #f1, "06, THIRD, Sunday, Father's Day"
  192.         PRINT #f1, "07, ON, 04, Independence Day"
  193.         PRINT #f1, "07, ON, 15, Tax Day"
  194.         PRINT #f1, "09, FIRST, Monday, Labor Day"
  195.         PRINT #f1, "09, ON, 25, Steve McNeill's Birthday"
  196.         PRINT #f1, "10, ON, 31, Halloween"
  197.         PRINT #f1, "11, ON, 01, All Saint's Day"
  198.         PRINT #f1, "11, FIRST, Sunday, End of Daylight Saving's Time"
  199.         PRINT #f1, "11, ON, 02, All Soul's Day"
  200.         PRINT #f1, "11, ON, 11, Vetern's Day"
  201.         PRINT #f1, "11, FOURTH, Thursday, Thanksgiving"
  202.         PRINT #f1, "12, ON, 07, Pearl Harbor Remembrance Day"
  203.         PRINT #f1, "12, ON, 24, Christmas Eve"
  204.         PRINT #f1, "12, ON, 25, Christmas Day"
  205.         PRINT #f1, "12, ON, 31, New Year's Eve"
  206.         CLOSE f1
  207.     END IF
  208.     OPEN "Holidays.txt" FOR INPUT AS #f1
  209.     LINE INPUT #f1, junk$ 'first line is file comment and not related to the data
  210.     DO UNTIL EOF(f1)
  211.         INPUT #f1, month
  212.         INPUT #f1, event$: event$ = UCASE$(event$)
  213.         INPUT #f1, day$
  214.         INPUT #f1, nam$
  215.         '  PRINT month, event$, day$, nam$
  216.         count = count + 1
  217.         REDIM _PRESERVE HolidayList(count) AS Holiday_type
  218.         HolidayList(count).month = month
  219.         IF event$ = "ON" THEN
  220.             HolidayList(count).day = VAL(day$)
  221.         ELSEIF RIGHT$(event$, 4) = "LAST" THEN 'we need to count backwards to find the last target day
  222.             d = ConvertDayToNum(day$)
  223.             FOR i = NumberOfDays(month, year) TO 1 STEP -1
  224.                 IF GetDay(month, i, year) = d THEN EXIT FOR
  225.             NEXT
  226.             SELECT CASE event$
  227.                 CASE "LAST": HolidayList(count).day = i
  228.                 CASE "SECOND TO LAST": HolidayList(count).day = i - 7
  229.                 CASE "THIRD TO LAST": HolidayList(count).day = i - 14
  230.                 CASE "FOURTH TO LAST": HolidayList(count).day = i - 21
  231.                 CASE "FIFTH TO LAST": HolidayList(count).day = i - 28
  232.             END SELECT
  233.         ELSE 'we count forwards
  234.             d = ConvertDayToNum(day$)
  235.             FOR i = 1 TO NumberOfDays(month, year)
  236.                 IF GetDay(month, i, year) = d THEN EXIT FOR
  237.             NEXT
  238.             SELECT CASE event$
  239.                 CASE "FIRST": HolidayList(count).day = i
  240.                 CASE "SECOND": HolidayList(count).day = i + 7
  241.                 CASE "THIRD": HolidayList(count).day = i + 14
  242.                 CASE "FOURTH": HolidayList(count).day = i + 21
  243.                 CASE "FIFTH": HolidayList(count).day = i + 28
  244.             END SELECT
  245.         END IF
  246.         HolidayList(count).name = nam$
  247.  
  248.  
  249.         '*******************************************************************
  250.         '**   Special Exceptions for days which are hard to calculate otherwise
  251.         '*******************************************************************
  252.  
  253.         IF HolidayList(count).name = "Thanksgiving" THEN 'Add Black Friday and Cyber Monday
  254.             d = HolidayList(count).day
  255.             count = count + 2
  256.             REDIM _PRESERVE HolidayList(count) AS Holiday_type
  257.             HolidayList(count - 1).month = 11
  258.             HolidayList(count - 1).day = d + 1
  259.             HolidayList(count - 1).name = "Black Fridy"
  260.             d = HolidayList(count - 1).day + 4
  261.             HolidayList(count).month = 11
  262.             IF d > 30 THEN d = d - 30: HolidayList(count).month = 12
  263.             HolidayList(count).day = d
  264.             HolidayList(count).name = "Cyber Monday"
  265.         END IF
  266.     LOOP
  267.     CLOSE #f1
  268.  
  269.     '*******************************************************************
  270.     '**   Seasons, which are on a simple look-up table
  271.     '*******************************************************************
  272.     IF _FILEEXISTS("Seasons.txt") = 0 THEN
  273.         OPEN "Seasons.txt" FOR OUTPUT AS #f1
  274.         PRINT #f1, "2016, 20, Mar, 04:30 GMT, 20, Jun, 23:34 BST, 22, Sep, 15:21 BST, 21, Dec, 10:44 GMT"
  275.         PRINT #f1, "2017, 20, Mar, 10:29 GMT, 21, Jun, 05:24 BST, 22, Sep, 21:02 BST, 21, Dec, 16:28 GMT"
  276.         PRINT #f1, "2018, 20, Mar, 16:15 GMT, 21, Jun, 11:07 BST, 23, Sep, 02:54 BST, 21, Dec, 22:23 GMT"
  277.         PRINT #f1, "2019, 20, Mar, 21:59 GMT, 21, Jun, 16:54 BST, 23, Sep, 08:50 BST, 22, Dec, 04:19 GMT"
  278.         PRINT #f1, "2020, 20, Mar, 03:50 GMT, 20, Jun, 22:44 BST, 22, Sep, 14:31 BST, 21, Dec, 10:02 GMT"
  279.         PRINT #f1, "2021, 20, Mar, 09:37 GMT, 21, Jun, 04:32 BST, 22, Sep, 20:21 BST, 21, Dec, 15:59 GMT"
  280.         PRINT #f1, "2022, 20, Mar, 15:33 GMT, 21, Jun, 10:14 BST, 23, Sep, 02:04 BST, 21, Dec, 21:48 GMT"
  281.         PRINT #f1, "2023, 20, Mar, 21:24 GMT, 21, Jun, 15:58 BST, 23, Sep, 07:50 BST, 22, Dec, 03:27 GMT"
  282.         PRINT #f1, "2024, 20, Mar, 03:06 GMT, 20, Jun, 21:51 BST, 22, Sep, 13:43 BST, 21, Dec, 09:20 GMT"
  283.         PRINT #f1, "2025, 20, Mar, 09:01 GMT, 21, Jun, 03:42 BST, 22, Sep, 19:19 BST, 21, Dec, 15:03 GMT"
  284.         PRINT #f1, "2026, 20, Mar, 14:46 GMT, 21, Jun, 09:24 BST, 23, Sep, 01:05 BST, 21, Dec, 20:50 GMT"
  285.         PRINT #f1, "2027, 20, Mar, 20:25 GMT, 21, Jun, 15:11 BST, 23, Sep, 07:02 BST, 22, Dec, 02:42 GMT"
  286.         PRINT #f1, "2028, 20, Mar, 02:17 GMT, 20, Jun, 21:02 BST, 22, Sep, 12:45 BST, 21, Dec, 08:20 GMT"
  287.         PRINT #f1, "2029, 20, Mar, 08:02 GMT, 21, Jun, 02:48 BST, 22, Sep, 18:38 BST, 21, Dec, 14:14 GMT"
  288.         PRINT #f1, "2030, 20, Mar, 13:52 GMT, 21, Jun, 08:31 BST, 23, Sep, 00:27 BST, 21, Dec, 20:09 GMT"
  289.         PRINT #f1, "2031, 20, Mar, 19:41 GMT, 21, Jun, 14:17 BST, 23, Sep, 06:15 BST, 22, Dec, 01:55 GMT"
  290.         PRINT #f1, "2032, 20, Mar, 01:22 GMT, 20, Jun, 20:09 BST, 22, Sep, 12:11 BST, 21, Dec, 07:56 GMT"
  291.         PRINT #f1, "2033, 20, Mar, 07:23 GMT, 21, Jun, 02:01 BST, 22, Sep, 17:51 BST, 21, Dec, 13:46 GMT"
  292.         PRINT #f1, "2034, 20, Mar, 13:17 GMT, 21, Jun, 07:44 BST, 22, Sep, 23:39 BST, 21, Dec, 19:34 GMT"
  293.         PRINT #f1, "2035, 20, Mar, 19:02 GMT, 21, Jun, 13:33 BST, 23, Sep, 05:39 BST, 22, Dec, 01:31 GMT"
  294.         PRINT #f1, "2036, 20, Mar, 01:03 GMT, 20, Jun, 19:32 BST, 22, Sep, 11:23 BST, 21, Dec, 07:13 GMT"
  295.         PRINT #f1, "2037, 20, Mar, 06:50 GMT, 21, Jun, 01:22 BST, 22, Sep, 17:13 BST, 21, Dec, 13:08 GMT"
  296.         PRINT #f1, "2038, 20, Mar, 12:41 GMT, 21, Jun, 07:09 BST, 22, Sep, 23:02 BST, 21, Dec, 19:02 GMT"
  297.         PRINT #f1, "2039, 20, Mar, 18:32 GMT, 21, Jun, 12:57 BST, 23, Sep, 04:49 BST, 22, Dec, 00:40 GMT"
  298.         PRINT #f1, "2040, 20, Mar, 00:11 GMT, 20, Jun, 18:46 BST, 22, Sep, 10:45 BST, 21, Dec, 06:33 GMT"
  299.         PRINT #f1, "2041, 20, Mar, 06:07 GMT, 21, Jun, 00:36 BST, 22, Sep, 16:26 BST, 21, Dec, 12:18 GMT"
  300.         PRINT #f1, "2042, 20, Mar, 11:53 GMT, 21, Jun, 06:16 BST, 22, Sep, 22:11 BST, 21, Dec, 18:04 GMT"
  301.         PRINT #f1, "2043, 20, Mar, 17:28 GMT, 21, Jun, 11:58 BST, 23, Sep, 04:07 BST, 22, Dec, 00:01 GMT"
  302.         PRINT #f1, "2044, 19, Mar, 23:20 GMT, 20, Jun, 17:51 BST, 22, Sep, 09:48 BST, 21, Dec, 05:43 GMT"
  303.         PRINT #f1, "2045, 20, Mar, 05:07 GMT, 20, Jun, 23:34 BST, 22, Sep, 15:33 BST, 21, Dec, 11:35 GMT"
  304.         PRINT #f1, "2046, 20, Mar, 10:58 GMT, 21, Jun, 05:14 BST, 22, Sep, 21:21 BST, 21, Dec, 17:28 GMT"
  305.         PRINT #f1, "2047, 20, Mar, 16:52 GMT, 21, Jun, 11:03 BST, 23, Sep, 03:08 BST, 21, Dec, 23:07 GMT"
  306.         PRINT #f1, "2048, 19, Mar, 22:34 GMT, 20, Jun, 16:54 BST, 22, Sep, 09:00 BST, 21, Dec, 05:02 GMT"
  307.         PRINT #f1, "2049, 20, Mar, 04:28 GMT, 20, Jun, 22:47 BST, 22, Sep, 14:42 BST, 21, Dec, 10:52 GMT"
  308.         PRINT #f1, "2050, 20, Mar, 10:19 GMT, 21, Jun, 04:33 BST, 22, Sep, 20:28 BST, 21, Dec, 16:38 GMT"
  309.         PRINT #f1, "2051, 20, Mar, 15:59 GMT, 21, Jun, 10:18 BST, 23, Sep, 02:27 BST, 21, Dec, 22:34 GMT"
  310.         PRINT #f1, "2052, 19, Mar, 21:56 GMT, 20, Jun, 16:16 BST, 22, Sep, 08:15 BST, 21, Dec, 04:17 GMT"
  311.         PRINT #f1, "2053, 20, Mar, 03:47 GMT, 20, Jun, 22:04 BST, 22, Sep, 14:06 BST, 21, Dec, 10:10 GMT"
  312.         PRINT #f1, "2054, 20, Mar, 09:34 GMT, 21, Jun, 03:47 BST, 22, Sep, 19:59 BST, 21, Dec, 16:10 GMT"
  313.         PRINT #f1, "2055, 20, Mar, 15:28 GMT, 21, Jun, 09:40 BST, 23, Sep, 01:48 BST, 21, Dec, 21:55 GMT"
  314.         PRINT #f1, "2056, 19, Mar, 21:11 GMT, 20, Jun, 15:28 BST, 22, Sep, 07:39 BST, 21, Dec, 03:51 GMT"
  315.         PRINT #f1, "2057, 20, Mar, 03:08 GMT, 20, Jun, 21:19 BST, 22, Sep, 13:23 BST, 21, Dec, 09:43 GMT"
  316.         PRINT #f1, "2058, 20, Mar, 09:05 GMT, 21, Jun, 03:04 BST, 22, Sep, 19:08 BST, 21, Dec, 15:25 GMT"
  317.         PRINT #f1, "2059, 20, Mar, 14:44 GMT, 21, Jun, 08:47 BST, 23, Sep, 01:03 BST, 21, Dec, 21:18 GMT"
  318.         PRINT #f1, "2060, 19, Mar, 20:38 GMT, 20, Jun, 14:45 BST, 22, Sep, 06:48 BST, 21, Dec, 03:01 GMT"
  319.         PRINT #f1, "2061, 20, Mar, 02:26 GMT, 20, Jun, 20:32 BST, 22, Sep, 12:31 BST, 21, Dec, 08:49 GMT"
  320.         PRINT #f1, "2062, 20, Mar, 08:07 GMT, 21, Jun, 02:11 BST, 22, Sep, 18:20 BST, 21, Dec, 14:42 GMT"
  321.         PRINT #f1, "2063, 20, Mar, 13:59 GMT, 21, Jun, 08:02 BST, 23, Sep, 00:08 BST, 21, Dec, 20:21 GMT"
  322.         PRINT #f1, "2064, 19, Mar, 19:38 GMT, 20, Jun, 13:45 BST, 22, Sep, 05:57 BST, 21, Dec, 02:09 GMT"
  323.         PRINT #f1, "2065, 20, Mar, 01:28 GMT, 20, Jun, 19:32 BST, 22, Sep, 11:42 BST, 21, Dec, 08:00 GMT"
  324.         PRINT #f1, "2066, 20, Mar, 07:20 GMT, 21, Jun, 01:16 BST, 22, Sep, 17:27 BST, 21, Dec, 13:45 GMT"
  325.         PRINT #f1, "2067, 20, Mar, 12:53 GMT, 21, Jun, 06:56 BST, 22, Sep, 23:19 BST, 21, Dec, 19:43 GMT"
  326.         PRINT #f1, "2068, 19, Mar, 18:49 GMT, 20, Jun, 12:53 BST, 22, Sep, 05:07 BST, 21, Dec, 01:32 GMT"
  327.         PRINT #f1, "2069, 20, Mar, 00:45 GMT, 20, Jun, 18:41 BST, 22, Sep, 10:51 BST, 21, Dec, 07:22 GMT"
  328.         PRINT #f1, "2070, 20, Mar, 06:34 GMT, 21, Jun, 00:22 BST, 22, Sep, 16:45 BST, 21, Dec, 13:19 GMT"
  329.         PRINT #f1, "2071, 20, Mar, 12:34 GMT, 21, Jun, 06:21 BST, 22, Sep, 22:37 BST, 21, Dec, 19:04 GMT"
  330.         PRINT #f1, "2072, 19, Mar, 18:21 GMT, 20, Jun, 12:13 BST, 22, Sep, 04:27 BST, 21, Dec, 00:56 GMT"
  331.         PRINT #f1, "2073, 20, Mar, 00:13 GMT, 20, Jun, 18:07 BST, 22, Sep, 10:15 BST, 21, Dec, 06:50 GMT"
  332.         PRINT #f1, "2074, 20, Mar, 06:09 GMT, 20, Jun, 23:58 BST, 22, Sep, 16:03 BST, 21, Dec, 12:35 GMT"
  333.         PRINT #f1, "2075, 20, Mar, 11:46 GMT, 21, Jun, 05:40 BST, 22, Sep, 21:59 BST, 21, Dec, 18:27 GMT"
  334.         PRINT #f1, "2076, 19, Mar, 17:39 GMT, 20, Jun, 11:36 BST, 22, Sep, 03:50 BST, 21, Dec, 00:13 GMT"
  335.         PRINT #f1, "2077, 19, Mar, 23:31 GMT, 20, Jun, 17:23 BST, 22, Sep, 09:36 BST, 21, Dec, 06:01 GMT"
  336.         PRINT #f1, "2078, 20, Mar, 05:11 GMT, 20, Jun, 22:58 BST, 22, Sep, 15:24 BST, 21, Dec, 11:58 GMT"
  337.         PRINT #f1, "2079, 20, Mar, 11:00 GMT, 21, Jun, 04:49 BST, 22, Sep, 21:13 BST, 21, Dec, 17:44 GMT"
  338.         PRINT #f1, "2080, 19, Mar, 16:44 GMT, 20, Jun, 10:34 BST, 22, Sep, 02:56 BST, 20, Dec, 23:33 GMT"
  339.         PRINT #f1, "2081, 19, Mar, 22:34 GMT, 20, Jun, 16:16 BST, 22, Sep, 08:37 BST, 21, Dec, 05:22 GMT"
  340.         PRINT #f1, "2082, 20, Mar, 04:30 GMT, 20, Jun, 22:03 BST, 22, Sep, 14:23 BST, 21, Dec, 11:04 GMT"
  341.         PRINT #f1, "2083, 20, Mar, 10:10 GMT, 21, Jun, 03:44 BST, 22, Sep, 20:11 BST, 21, Dec, 16:53 GMT"
  342.         PRINT #f1, "2084, 19, Mar, 15:59 GMT, 20, Jun, 09:40 BST, 22, Sep, 01:59 BST, 20, Dec, 22:41 GMT"
  343.         PRINT #f1, "2085, 19, Mar, 21:53 GMT, 20, Jun, 15:33 BST, 22, Sep, 07:43 BST, 21, Dec, 04:28 GMT"
  344.         PRINT #f1, "2086, 20, Mar, 03:35 GMT, 20, Jun, 21:09 BST, 22, Sep, 13:32 BST, 21, Dec, 10:22 GMT"
  345.         PRINT #f1, "2087, 20, Mar, 09:28 GMT, 21, Jun, 03:06 BST, 22, Sep, 19:28 BST, 21, Dec, 16:08 GMT"
  346.         PRINT #f1, "2088, 19, Mar, 15:17 GMT, 20, Jun, 08:56 BST, 22, Sep, 01:18 BST, 20, Dec, 21:56 GMT"
  347.         PRINT #f1, "2089, 19, Mar, 21:06 GMT, 20, Jun, 14:43 BST, 22, Sep, 07:07 BST, 21, Dec, 03:52 GMT"
  348.         PRINT #f1, "2090, 20, Mar, 03:02 GMT, 20, Jun, 20:36 BST, 22, Sep, 12:59 BST, 21, Dec, 09:43 GMT"
  349.         PRINT #f1, "2091, 20, Mar, 08:42 GMT, 21, Jun, 02:19 BST, 22, Sep, 18:51 BST, 21, Dec, 15:38 GMT"
  350.         PRINT #f1, "2092, 19, Mar, 14:33 GMT, 20, Jun, 08:15 BST, 22, Sep, 00:42 BST, 20, Dec, 21:32 GMT"
  351.         PRINT #f1, "2093, 19, Mar, 20:34 GMT, 20, Jun, 14:07 BST, 22, Sep, 06:29 BST, 21, Dec, 03:21 GMT"
  352.         PRINT #f1, "2094, 20, Mar, 02:21 GMT, 20, Jun, 19:42 BST, 22, Sep, 12:16 BST, 21, Dec, 09:13 GMT"
  353.         PRINT #f1, "2095, 20, Mar, 08:15 GMT, 21, Jun, 01:39 BST, 22, Sep, 18:11 BST, 21, Dec, 15:01 GMT"
  354.         PRINT #f1, "2096, 19, Mar, 14:03 GMT, 20, Jun, 07:31 BST, 21, Sep, 23:55 BST, 20, Dec, 20:46 GMT"
  355.         PRINT #f1, "2097, 19, Mar, 19:48 GMT, 20, Jun, 13:13 BST, 22, Sep, 05:36 BST, 21, Dec, 02:37 GMT"
  356.         PRINT #f1, "2098, 20, Mar, 01:40 GMT, 20, Jun, 19:03 BST, 22, Sep, 11:24 BST, 21, Dec, 08:21 GMT"
  357.         PRINT #f1, "2099, 20, Mar, 07:17 GMT, 21, Jun, 00:41 BST, 22, Sep, 17:11 BST, 21, Dec, 14:04 GMT"
  358.         CLOSE #f1
  359.     END IF
  360.     IF year > 2015 AND year < 2100 THEN
  361.         count = count + 4
  362.         REDIM _PRESERVE HolidayList(count) AS Holiday_type
  363.         HolidayList(count - 3).month = 3: HolidayList(count - 3).name = "Spring Starts"
  364.         HolidayList(count - 2).month = 6: HolidayList(count - 2).name = "Summer Starts"
  365.         HolidayList(count - 1).month = 9: HolidayList(count - 1).name = "Autumn Starts"
  366.         HolidayList(count).month = 12: HolidayList(count).name = "Winter Starts"
  367.         HolidayList(count - 1).day = d + 1
  368.         OPEN "Seasons.txt" FOR INPUT AS #f1
  369.         DO UNTIL EOF(1)
  370.             INPUT #f1, y
  371.             INPUT #f1, HolidayList(count - 3).day
  372.             INPUT #f1, junk$
  373.             INPUT #f1, junk$
  374.             INPUT #f1, HolidayList(count - 2).day
  375.             INPUT #f1, junk$
  376.             INPUT #f1, junk$
  377.             INPUT #f1, HolidayList(count - 1).day
  378.             INPUT #f1, junk$
  379.             INPUT #f1, junk$
  380.             INPUT #f1, HolidayList(count).day
  381.             INPUT #f1, junk$
  382.             INPUT #f1, junk$
  383.             IF y = year THEN EXIT DO
  384.         LOOP
  385.         CLOSE #f1
  386.     END IF
  387.  
  388.  
  389. SUB GetBackgrounds
  390.     FOR i = -12 TO 12
  391.         redo:
  392.         t = INT(RND * 1088) + 1
  393.         FOR j = -12 TO i
  394.             IF BackGrounds(j) = t GOTO redo
  395.         NEXT
  396.         BackGrounds(i) = t
  397.     NEXT
  398.  
  399. SUB CenterMonth (month, year)
  400.     _FONT f72
  401.     SELECT CASE month
  402.         CASE 1: text$ = "January"
  403.         CASE 2: text$ = "February"
  404.         CASE 3: text$ = "March"
  405.         CASE 4: text$ = "April"
  406.         CASE 5: text$ = "May"
  407.         CASE 6: text$ = "June"
  408.         CASE 7: text$ = "July"
  409.         CASE 8: text$ = "August"
  410.         CASE 9: text$ = "September"
  411.         CASE 10: text$ = "October"
  412.         CASE 11: text$ = "November"
  413.         CASE 12: text$ = "December"
  414.     END SELECT
  415.     text$ = text$ + STR$(year)
  416.     pw = _PRINTWIDTH(text$) / 2
  417.     _PRINTSTRING (640 - pw, 0), text$
  418.  
  419.  
  420. SUB DrawLines
  421.     TopOffset = 72
  422.  
  423.     IF ShowDays THEN
  424.         LINE (0, TopOffset)-STEP(1280, 3), _RGBA(128, 128, 64, 160), BF
  425.         FOR i = 0 TO 7
  426.             LINE (i * 1280 / 7, 0 + TopOffset)-STEP(3, 40), _RGBA32(128, 128, 64, 160), BF
  427.         NEXT
  428.         TopOffset = TopOffset + 40
  429.     END IF
  430.     FOR i = 0 TO 6
  431.         LINE (0, i * 90 + TopOffset)-STEP(1280, 3), _RGBA32(128, 128, 64, 160), BF
  432.     NEXT
  433.     FOR i = 0 TO 7
  434.         LINE (i * 1280 / 7, 0 + TopOffset)-STEP(3, 540), _RGBA32(128, 128, 64, 160), BF
  435.     NEXT
  436.  
  437. FUNCTION ConvertToDay$ (day) 'Function to return a string for a day
  438.     SELECT CASE day
  439.         CASE 1: ConvertToDay$ = "Sunday"
  440.         CASE 2: ConvertToDay$ = "Monday"
  441.         CASE 3: ConvertToDay$ = "Tuesday"
  442.         CASE 4: ConvertToDay$ = "Wednesday"
  443.         CASE 5: ConvertToDay$ = "Thursday"
  444.         CASE 6: ConvertToDay$ = "Friday"
  445.         CASE 7: ConvertToDay$ = "Saturday"
  446.     END SELECT
  447.  
  448. SUB DrawDays (month, year)
  449.     SHARED highlightday
  450.     REDIM Holidays(0) AS STRING
  451.     TopOffset = 76
  452.     IF ShowDays THEN
  453.         _FONT f32
  454.         bw = 1280 \ 7
  455.         FOR i = 1 TO 7
  456.             t$ = ConvertToDay(i)
  457.             pw = _PRINTWIDTH(t$) \ 2
  458.             _PRINTSTRING (bw * (i - 1) + bw \ 2 - pw, 80), t$
  459.         NEXT
  460.         TopOffset = TopOffset + 40
  461.         _FONT f72
  462.     END IF
  463.  
  464.     nod = NumberOfDays(month, year)
  465.     y = 0
  466.     FOR i = 1 TO nod
  467.         text$ = _TRIM$(STR$(i))
  468.         pw = _PRINTWIDTH(text$)
  469.         x = GetDay(month, i, year)
  470.         IF month = ThisMonth AND i = Today AND ThisYear = year THEN LINE ((x - 1) * 1280 / 7 + 3, y * 90 + TopOffset)-STEP(1280 / 7 - 3, 86), _RGBA32(128, 128, 128, 128), BF
  471.         _PRINTSTRING (x * 1280 / 7 - pw, y * 90 + TopOffset), text$
  472.  
  473.         '
  474.  
  475.  
  476.         u = UBOUND(HolidayList)
  477.         IF u > 0 THEN
  478.             _FONT 8
  479.             count = 0
  480.             FOR j = 1 TO u
  481.                 IF month = HolidayList(j).month AND i = HolidayList(j).day THEN
  482.                     count = count + 1
  483.                     _PRINTSTRING ((x - 1) * 1280 / 7 + 4, (y + 1) * 90 + TopOffset - 5 - count * 8), LEFT$(HolidayList(j).name, 22)
  484.                 END IF
  485.             NEXT
  486.             _FONT f72
  487.         END IF
  488.         IF x = 7 THEN y = y + 1
  489.     NEXT
  490.  
  491.  
  492. FUNCTION NumberOfDays (month, year)
  493.     SELECT CASE month
  494.         CASE 1, 3, 5, 7, 8, 10, 12: NumberOfDays = 31
  495.         CASE 2: IF IsLeapYear(year) THEN NumberOfDays = 29 ELSE NumberOfDays = 28
  496.         CASE 4, 6, 9, 11: NumberOfDays = 30
  497.     END SELECT
  498.  
  499.  
  500. FUNCTION IsLeapYear (yyyy) 'use 4 digit year
  501.     IF GetDay(2, 29, yyyy) <> GetDay(3, 1, yyyy) THEN IsLeapYear = -1
  502.  
  503. FUNCTION GetDay (m, d, y) 'use 4 digit year
  504.     'From Zeller's congruence: https://en.wikipedia.org/wiki/Zeller%27s_congruence
  505.     mm = m: dd = d: yyyy = y
  506.     IF mm < 3 THEN mm = mm + 12: yyyy = yyyy - 1
  507.     century = yyyy MOD 100
  508.     zerocentury = yyyy \ 100
  509.     result = (dd + INT(13 * (mm + 1) / 5) + century + INT(century / 4) + INT(zerocentury / 4) + 5 * zerocentury) MOD 7
  510.     IF result = 0 THEN
  511.         GetDay = 7
  512.     ELSE
  513.         GetDay = result
  514.     END IF
  515.     'Function changed to return a numeric value instead of a string for this program
  516.     '    SELECT CASE result
  517.     '        CASE 7: GetDay$ = "Saturday"
  518.     '        CASE 1: GetDay$ = "Sunday"
  519.     '        CASE 2: GetDay$ = "Monday"
  520.     '        CASE 3: GetDay$ = "Tuesday"
  521.     '        CASE 4: GetDay$ = "Wednesday"
  522.     '        CASE 5: GetDay$ = "Thursday"
  523.     '        CASE 6: GetDay$ = "Friday"
  524.     '    END SELECT
  525.  
  526.  
  527. FUNCTION GetPublicIP$ (force)
  528.  
  529.     f1 = FREEFILE
  530.     IF force = -1 OR _FILEEXISTS("PIP.txt") = 0 THEN
  531.         OPEN "PIP.txt" FOR OUTPUT AS #f1: CLOSE f1
  532.         SHELL _HIDE "cmd /c nslookup myip.opendns.com resolver1.opendns.com>PIP.txt"
  533.     END IF
  534.  
  535.     OPEN "PIP.txt" FOR INPUT AS #f1
  536.     IF LOF(f1) THEN
  537.         DO
  538.             LINE INPUT #f1, temp$
  539.             IF temp$ <> "" THEN last$ = temp$ 'there's a blank line after the data we need.
  540.             '                                 Ignore it.  What we want is the last line of info generated here.
  541.         LOOP UNTIL EOF(1)
  542.         l = _INSTRREV(last$, "Address:")
  543.         IF l THEN GetPublicIP$ = MID$(last$, l + 10)
  544.     END IF
  545.     CLOSE f1
  546.  
  547. SUB Lat_Long (lat AS _FLOAT, lon AS _FLOAT, force)
  548.     ip$ = GetPublicIP$(0)
  549.     IF force = -1 OR _FILEEXISTS("LatAndLong.txt") = 0 THEN
  550.         DownloadURL "ip-api.com/line/" + ip$ + "?fields=lat,lon", "LatAndLong.txt"
  551.     END IF
  552.     f1 = FREEFILE
  553.     OPEN "LatAndLong.txt" FOR INPUT AS #f1
  554.     IF LOF(f1) = 0 THEN CLOSE f1: EXIT SUB 'something didn't download.  this info isn't available to parse.
  555.     INPUT #f1, lat
  556.     INPUT #f1, lon
  557.     CLOSE f1
  558.  
  559. SUB DownloadURL (link$, file$)
  560.     f1 = FREEFILE
  561.     OPEN file$ FOR OUTPUT AS #f1: CLOSE #f1 'erase any old file of the same name
  562.     $IF WIN THEN
  563.         out$ = "powershell.exe -c " + CHR$(34) + "Invoke-Webrequest '" + link$ + "' -OutFile '" + file$ + "'" + CHR$(34)
  564.     $ELSE
  565.         out$ = "wget " + chr$(34) + link$ + " -O " + file$ + chr$(34)
  566.     $END IF
  567.     SHELL _HIDE out$
  568.  
  569. FUNCTION GetHour (fromTime$) 'time should be hh:mm:ss WhateverM
  570.     l = INSTR(fromTime$, ":") '1st :
  571.     GetHour = VAL(LEFT$(fromTime$, l))
  572.  
  573. FUNCTION GetMinute (fromTime$) 'time should be hh:mm:ss WhateverM
  574.     l = INSTR(fromTime$, ":") '1st :
  575.     GetMinute = VAL(MID$(fromTime$, l + 1))
  576.  
  577.  
  578. FUNCTION GetSecond (fromTime$) 'time should be hh:mm:ss WhateverM
  579.     l = INSTR(fromTime$, ":") '1st :
  580.     l = INSTR(l + 1, fromTime$, ":") '2nd :
  581.     GetSecond = VAL(MID$(fromTime$, l + 1))
  582.  
  583.  
  584. FUNCTION GetTimeOffset
  585.     $IF WIN THEN
  586.         TYPE SYSTEMTIME
  587.             wYear AS _UNSIGNED INTEGER
  588.             wMonth AS _UNSIGNED INTEGER
  589.             wDayOfWeek AS _UNSIGNED INTEGER
  590.             wDay AS _UNSIGNED INTEGER
  591.             wHour AS _UNSIGNED INTEGER
  592.             wMinute AS _UNSIGNED INTEGER
  593.             wSecond AS _UNSIGNED INTEGER
  594.             wMilliseconds AS _UNSIGNED INTEGER
  595.         END TYPE
  596.  
  597.         TYPE TIME_ZONE_INFORMATION
  598.             Bias AS LONG
  599.             StandardName AS STRING * 64 'WCHAR      StandardName[32];
  600.             StandardDate AS SYSTEMTIME
  601.             StandardBias AS LONG
  602.             DaylightName AS STRING * 64 'WCHAR      DaylightName[32];
  603.             DaylightDate AS SYSTEMTIME
  604.             DaylightBias AS LONG
  605.         END TYPE
  606.  
  607.         DECLARE DYNAMIC LIBRARY "Kernel32"
  608.             SUB GetTimeZoneInformation (t AS TIME_ZONE_INFORMATION)
  609.         END DECLARE
  610.  
  611.         DIM t AS TIME_ZONE_INFORMATION
  612.         GetTimeZoneInformation t
  613.         GetTimeOffset = t.Bias
  614.     $END IF
  615.  
  616.  
  617.  
  618. SUB SunStuff (lat, lon, month, day, year)
  619.     STATIC f
  620.     d$ = _TRIM$(STR$(year)) + _TRIM$(STR$(month)) + _TRIM$(STR$(day))
  621.     link$ = "https://api.sunrise-sunset.org/json?lat=" + _TRIM$(STR$(lat)) + "&lng="
  622.     link$ = link$ + _TRIM$(STR$(lon)) + "&date=" + d$
  623.     DownloadURL link$, "temp.txt"
  624.     f = FREEFILE
  625.     OPEN "temp.txt" FOR BINARY AS #f
  626.  
  627.     IF LOF(f) = 0 THEN CLOSE f: EXIT SUB 'something didn't download.  this info isn't available to parse.
  628.  
  629.     t$ = SPACE$(LOF(f))
  630.     GET #1, 1, t$
  631.     CLOSE f
  632.  
  633.     'strip off unwanted stuff
  634.     l = INSTR(t$, ":{"): t$ = MID$(t$, l + 2) 'junk left of our initial data
  635.     DO
  636.         l = INSTR(t$, CHR$(34))
  637.         t$ = LEFT$(t$, l - 1) + MID$(t$, l + 1) 'remove all quotes completely from this data
  638.     LOOP UNTIL l = 0
  639.     DO
  640.         l = INSTR(t$, "_")
  641.         t$ = LEFT$(t$, l - 1) + " " + MID$(t$, l + 1) 'change all underscores to spaces in this data
  642.     LOOP UNTIL l = 0
  643.     t$ = _TRIM$(t$)
  644.     t$ = LEFT$(t$, LEN(t$) - 12) 'remove the last end of data }
  645.     PRINT t$
  646.  
  647.     'parse it down to field, data
  648.     DO
  649.         l = INSTR(t$, ",")
  650.         IF l = 0 THEN EXIT DO
  651.         count = count + 1
  652.         REDIM _PRESERVE Sun(count) AS Sun_Data_type
  653.         whole$ = LEFT$(t$, l)
  654.         Sun(count).field = LEFT$(whole$, INSTR(whole$, ":") - 1)
  655.         r$ = MID$(whole$, INSTR(whole$, ":") + 1)
  656.         r$ = LEFT$(r$, LEN(r$) - 1)
  657.         IF RIGHT$(r$, 1) = "M" THEN m$ = RIGHT$(r$, 3) ELSE m$ = ""
  658.         h = GetHour(r$): m = GetMinute(r$): s = GetSecond(r$)
  659.         IF m$ = " PM" AND h <> 12 THEN h = h + 12
  660.         IF count <> 4 THEN
  661.             h = h - GetTimeOffset / 60
  662.             IF h < 0 THEN h = 24 + h 'adjust for AM/PM difference, if ever necessary
  663.             IF h > 23 THEN h = h - 24 'adjust for AM/PM difference, if ever necessary
  664.             SELECT CASE h
  665.                 CASE 0: h = 12: m$ = " AM"
  666.                 CASE 12: m$ = " PM"
  667.                 CASE IS > 12: h = h - 12: m$ = " PM"
  668.                 CASE ELSE: m$ = " AM"
  669.             END SELECT
  670.         END IF
  671.         hour$ = _TRIM$(STR$(h)): IF LEN(hour$) = 1 THEN hour$ = "0" + hour$
  672.         min$ = _TRIM$(STR$(m)): IF LEN(min$) = 1 THEN min$ = "0" + min$
  673.         sec$ = _TRIM$(STR$(s)): IF LEN(sec$) = 1 THEN sec$ = "0" + sec$
  674.         Sun(count).value = hour$ + ":" + min$ + ":" + sec$ + m$
  675.         t$ = MID$(t$, l + 1)
  676.     LOOP
  677.  
  678.  
  679. FUNCTION MoonPhase$ (month, day, year)
  680.     DIM mooncycle AS _FLOAT
  681.     DIM fullmoon AS _FLOAT, dp AS _FLOAT, sod AS _FLOAT
  682.     mooncycle = 29.5305882 'days between moon rotations
  683.     sod = 24 * 60 * 60 'number of seconds in a day
  684.  
  685.     m$ = _TRIM$(STR$(month))
  686.     d$ = _TRIM$(STR$(day))
  687.     y$ = _TRIM$(STR$(year))
  688.     dt$ = m$ + "-" + d$ + "-" + y$
  689.     guessmoon = TimeStamp(dt$, 23 * 3600 + 59 * 60 + 59) 'what is the moon at 11:59:59 PM
  690.     fullmoon = TimeStamp("1-3-2020", 4 * 3600 + 46 * 60) ' full moon on 1-3-2020 at 4:46 AM UTC
  691.     dp = (guessmoon - fullmoon) / sod 'days past our full moon
  692.     r1 = dp - INT(dp / mooncycle) * mooncycle 'how far we are in repeating our rotation
  693.     SELECT CASE r1
  694.         CASE IS <= mooncycle / 4: MoonPhase$ = "1st Quarter"
  695.         CASE IS <= mooncycle / 2: MoonPhase$ = "Full moon"
  696.         CASE IS <= mooncycle * 3 / 4: MoonPhase$ = "3rd Quarter"
  697.         CASE ELSE: MoonPhase$ = "New Moon"
  698.     END SELECT
  699.  
  700.  
  701.  
  702. FUNCTION TimeStamp## (d$, t##) 'date and timer
  703.     'Based on Unix Epoch time, which starts at year 1970.
  704.     DIM s AS _FLOAT
  705.  
  706.     l = INSTR(d$, "-")
  707.     l1 = INSTR(l + 1, d$, "-")
  708.     m = VAL(LEFT$(d$, l))
  709.     d = VAL(MID$(d$, l + 1))
  710.     y = VAL(MID$(d$, l1 + 1))
  711.     IF y < 1970 THEN 'calculate shit backwards
  712.         SELECT CASE m 'turn the day backwards for the month
  713.             CASE 1, 3, 5, 7, 8, 10, 12: d = 31 - d '31 days
  714.             CASE 2: d = 28 - d 'special 28 or 29.
  715.             CASE 4, 6, 9, 11: d = 30 - d '30 days
  716.         END SELECT
  717.         IF y MOD 4 = 0 AND m < 3 THEN 'check for normal leap year, and we're before it...
  718.             d = d + 1 'assume we had a leap year, subtract another day
  719.             IF y MOD 100 = 0 AND y MOD 400 <> 0 THEN d = d - 1 'not a leap year if year is divisible by 100 and not 400
  720.         END IF
  721.  
  722.         'then count the months that passed after the current month
  723.         FOR i = m + 1 TO 12
  724.             SELECT CASE i
  725.                 CASE 2: d = d + 28
  726.                 CASE 3, 5, 7, 8, 10, 12: d = d + 31
  727.                 CASE 4, 6, 9, 11: d = d + 30
  728.             END SELECT
  729.         NEXT
  730.  
  731.         'we should now have the entered year calculated.  Now lets add in for each year from this point to 1970
  732.         d = d + 365 * (1969 - y) '365 days per each standard year
  733.         FOR i = 1968 TO y + 1 STEP -4 'from 1968 onwards,backwards, skipping the current year (which we handled previously in the FOR loop)
  734.             d = d + 1 'subtract an extra day every leap year
  735.             IF (i MOD 100) = 0 AND (i MOD 400) <> 0 THEN d = d - 1 'but skipping every year divisible by 100, but not 400
  736.         NEXT
  737.         s## = d * 24 * 60 * 60 'Seconds are days * 24 hours * 60 minutes * 60 seconds
  738.         TimeStamp## = -(s## + 24 * 60 * 60 - t##)
  739.         EXIT FUNCTION
  740.     ELSE
  741.         y = y - 1970
  742.     END IF
  743.  
  744.     FOR i = 1 TO m 'for this year,
  745.         SELECT CASE i 'Add the number of days for each previous month passed
  746.             CASE 1: d = d 'January doestn't have any carry over days.
  747.             CASE 2, 4, 6, 8, 9, 11: d = d + 31
  748.             CASE 3 'Feb might be a leap year
  749.                 IF (y MOD 4) = 2 THEN 'if this year is divisible by 4 (starting in 1972)
  750.                     d = d + 29 'its a leap year
  751.                     IF (y MOD 100) = 30 AND (y MOD 400) <> 30 THEN 'unless..
  752.                         d = d - 1 'the year is divisible by 100, and not divisible by 400
  753.                     END IF
  754.                 ELSE 'year not divisible by 4, no worries
  755.                     d = d + 28
  756.                 END IF
  757.             CASE 5, 7, 10, 12: d = d + 30
  758.         END SELECT
  759.     NEXT
  760.     d = (d - 1) + 365 * y 'current month days passed + 365 days per each standard year
  761.     FOR i = 2 TO y - 1 STEP 4 'from 1972 onwards, skipping the current year (which we handled previously in the FOR loopp)
  762.         d = d + 1 'add an extra day every leap year
  763.         IF (i MOD 100) = 30 AND (i MOD 400) <> 30 THEN d = d - 1 'but skiping every year divisible by 100, but not 400
  764.     NEXT
  765.     s## = d * 24 * 60 * 60 'Seconds are days * 24 hours * 60 minutes * 60 seconds
  766.     TimeStamp## = (s## + t##)
  767.  
  768. FUNCTION ConvertDayToNum (day$)
  769.     SELECT CASE day$
  770.         CASE "Sunday": ConvertDayToNum = 1
  771.         CASE "Monday": ConvertDayToNum = 2
  772.         CASE "Tuseday": ConvertDayToNum = 3
  773.         CASE "Wednesday": ConvertDayToNum = 4
  774.         CASE "Thursday": ConvertDayToNum = 5
  775.         CASE "Friday": ConvertDayToNum = 6
  776.         CASE "Saturday": ConvertDayToNum = 7
  777.     END SELECT

I updated the resource files in the 7zip archive in my dropbox, so if you want, you can grab the latest complete package just by using the same link as before, at the bottom of the first post.

At this point, we're now using external holiday files, and they're smart enough to calculate days for us like Thanksgiving (Last Thursday in November).  We're no longer limited to exact days, but now find days in relation to when they fall inside a month.

I've added the sunrise, sunset, and moon cycles to our "Today" information.

The starting days for the seasons have been added for all the years from 2016 to 2099.

We can now manually move forward and backwards in the calendar with the arrow keys.  CTRL-LEFT moves us back a month, CTRL-RIGHT moves us forward a month.

**********************

Now that I can manually choose the month, I need to implement a method to manually choose a day, so we can add/edit/delete events on that day.  That'll be what my next version of this little project does.

I'm thinking basic input would be:
LEFT, RIGHT, UP, DOWN -- move a daily selector across the screen.
A -- Add an Event for the chosen day
D -- Delete an Event for the chosen day
E -- Edit an Event for the chosen day
P -- Print month
C -- Change month's background (some might look nice, but not be suitable for printing)
R -- Remove/Restore month's background (just turn it black to print a simple grid without using all the color ink in the printer)
ESC -- End program

Other functionality to be added/edited as inspiration hits and this little thing keeps growing.  It's readily on the way to go from just a simple "yearly printout" to becoming some sort of schedule organization tool. 

Is there anything I'm missing?  Anything which someone else would like to see added to this?  All comments, requests, and feedback are appreciated.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Adrian

  • Newbie
  • Posts: 39
    • View Profile
Re: Calendar 2021
« Reply #9 on: December 29, 2020, 01:37:40 pm »
Easter, Ash Wednesday, Good Friday, the seasons are all on this list.  Those are individual entries which will need some unique tweaking to work properly for us, but I'll probably end up sorting out some way to stick them in there before I'm all finished.  For now, it's one simple little alteration and addition at a time.  ;)

Can try Ron Mallen's algorithm for calculating Easter. Adding Good Friday and Ash Wednesday should then be quite straightforward.

Code: QB64: [Select]
  1. ' EASTER DATE CALCULATION FOR YEARS 1583 TO 4099
  2.  
  3. ' y is a 4 digit year 1583 to 4099
  4. ' d returns the day of the month of Easter
  5. ' m returns the month of Easter
  6.  
  7. ' Easter Sunday is the Sunday following the Paschal Full Moon
  8. ' (PFM) date for the year
  9.  
  10. ' This algorithm is an arithmetic interpretation of the 3 step
  11. ' Easter Dating Method developed by Ron Mallen
  12.  
  13. DIM FirstDig, Remain19, temp 'intermediate results
  14. DIM tA, tB, tC, tD, tE 'table A to E results
  15.  
  16. INPUT "year "; y
  17. FirstDig = y \ 100 'first 2 digits of year
  18. Remain19 = y MOD 19 'remainder of year / 19
  19.  
  20. ' calculate PFM date
  21. temp = (FirstDig - 15) \ 2 + 202 - 11 * Remain19
  22.  
  23. SELECT CASE FirstDig
  24.     CASE 21, 24, 25, 27 TO 32, 34, 35, 38
  25.         temp = temp - 1
  26.     CASE 33, 36, 37, 39, 40
  27.         temp = temp - 2
  28. temp = temp MOD 30
  29.  
  30. tA = temp + 21
  31. IF temp = 29 THEN tA = tA - 1
  32. IF (temp = 28 AND Remain19 > 10) THEN tA = tA - 1
  33.  
  34. 'find the next Sunday
  35. tB = (tA - 19) MOD 7
  36.  
  37. tC = (40 - FirstDig) MOD 4
  38. IF tC = 3 THEN tC = tC + 1
  39. IF tC > 1 THEN tC = tC + 1
  40.  
  41. temp = y MOD 100
  42. tD = (temp + temp \ 4) MOD 7
  43.  
  44. tE = ((20 - tB - tC - tD) MOD 7) + 1
  45. d = tA + tE
  46.  
  47. 'return the date
  48. IF d > 31 THEN
  49.     d = d - 31
  50.     m = 4: m$ = "April"
  51.     m = 3: m$ = "March"
  52.  
  53. PRINT m$, d
  54.  

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Calendar 2021
« Reply #10 on: December 29, 2020, 07:41:27 pm »
Or you can dig out the code from my Calendar Maker from last year. I added Easter code to it. Feel free to use any of this code. The meat of the code starts at line 356.
I found this Easter code somewhere online but I can't remember where.

Code: QB64: [Select]
  1. 'This is my very first calendar making program!
  2. 'Thanks to the guys from the QB64.org forum for the help: bplus, SMcNeill, euklides, and TempodiBasic!
  3. 'This is a freeware program like all my other programs and games, only free.
  4. 'Feel free to use this code in your own programs.
  5. 'This version has the ability to add info or holidays to dates.
  6. 'Made on Thursday, September 19, 2019 by Ken G.
  7.  
  8. start:
  9. _TITLE "Calendar Maker"
  10. _LIMIT 1000
  11. DIM newinfo$(50)
  12. DIM dayinfo(50)
  13. dd = 0
  14. leap = 0
  15. m = 0
  16. mm = 0
  17. y = 0
  18. yy = 0
  19. w = 0
  20. weekday = 0
  21. days = 0
  22. holidays = 0
  23. SCREEN _NEWIMAGE(800, 600, 32)
  24. PRINT "                                  Monthly Calendar Maker"
  25. PRINT "                                        By Ken G."
  26. PRINT "                         With some help from the QB64.org Forum guys!"
  27. PRINT "          This program will make a calendar for the year and month you want."
  28. PRINT "          It will also name some U.S. holidays on their dates if you choose that."
  29. PRINT "          You also can add holidays or info to any day you wish with up to 12"
  30. PRINT "          letters, numbers, symbols, or spaces."
  31. PRINT "          This uses the Gregorian Calendar which became common practice in"
  32. PRINT "          England in 1753 and we still use it today."
  33. PRINT "          First make a calendar, then if you want to save it as a .bmp file,"
  34. PRINT "          press the 'S' key and it will save it as the month and year for its name."
  35. PRINT "          For example, if you made a calendar for January 2020 and wish to save it,"
  36. PRINT "          press the 'S' key and it will save it as 1-2020.bmp"
  37. PRINT "          If you wish to print your calendar on your printer, press 'P' once."
  38. PRINT "          Feel free to print as many times as you wish. They take up 1 page each."
  39. PRINT "          If you save the .bmp calendar, it will be put in the same directory as this program."
  40. PRINT "          To switch to the last month use the left arrow key, to the next month the right arrow key."
  41. PRINT "          Switching months with the arrow keys will not save your new date info if you come back."
  42. PRINT "          To make a different calendar without saving, press the Space Bar."
  43. PRINT "          Keyboard commands will be listed on the title bar of the window."
  44. again1:
  45. INPUT "          Type the year here (1753-9999): ", y
  46. IF y <> INT(y) THEN PRINT "Cannot use decimals, try again.": GOTO again1:
  47. IF y < 1753 OR y > 9999 THEN PRINT "The year can only be between 1753 and 9999, try again.": GOTO again1:
  48. again2:
  49. INPUT "          Type the month here (1-12): ", m
  50. IF m <> INT(m) THEN PRINT "Cannot use decimals, try again.": GOTO again2:
  51. IF m < 1 OR m > 12 THEN PRINT "1-12 only, try again.": GOTO again2:
  52. INPUT "          Do you want U.S. holidays added (Y/N)?", hol$
  53. IF LEFT$(hol$, 1) = "y" OR LEFT$(hol$, 1) = "Y" THEN holidays = 1
  54. INPUT "          Do you want to add your own holidays or info (Y/N)?", adding$
  55. calculate:
  56. info = 0
  57. infos = 0
  58. 'Get the month name.
  59. IF m = 1 THEN month$ = " January"
  60. IF m = 2 THEN month$ = "February"
  61. IF m = 3 THEN month$ = "  March"
  62. IF m = 4 THEN month$ = "  April"
  63. IF m = 5 THEN month$ = "  May"
  64. IF m = 6 THEN month$ = "  June"
  65. IF m = 7 THEN month$ = "  July"
  66. IF m = 8 THEN month$ = " August"
  67. IF m = 9 THEN month$ = "September"
  68. IF m = 10 THEN month$ = " October"
  69. IF m = 11 THEN month$ = "November"
  70. IF m = 12 THEN month$ = "December"
  71.  
  72. 'Calculate to see if it's a Leap Year.
  73. IF m <> 2 THEN GOTO nex:
  74. IF y / 400 = INT(y / 400) THEN leap = 1: GOTO more:
  75. IF y / 4 = INT(y / 4) THEN leap = 1
  76. IF y / 100 = INT(y / 100) THEN leap = 0
  77.  
  78. 'Get the number of days for each month.
  79. more:
  80. IF leap = 1 THEN days = 29
  81. IF leap = 0 THEN days = 28
  82. GOTO weekday:
  83. nex:
  84. IF m = 1 THEN days = 31
  85. IF m = 3 THEN days = 31
  86. IF m = 4 THEN days = 30
  87. IF m = 5 THEN days = 31
  88. IF m = 6 THEN days = 30
  89. IF m = 7 THEN days = 31
  90. IF m = 8 THEN days = 31
  91. IF m = 9 THEN days = 30
  92. IF m = 10 THEN days = 31
  93. IF m = 11 THEN days = 30
  94. IF m = 12 THEN days = 31
  95. weekday:
  96.  
  97. 'Set the month, year, and weekday variables to start with.
  98. mm = m
  99. yy = y
  100. GetDay mm, dd, y, weekday
  101.  
  102.  
  103. IF LEFT$(adding$, 1) = "y" OR LEFT$(adding$, 1) = "Y" THEN GOSUB adding:
  104. adding$ = ""
  105.  
  106. 'This section makes the calendar graph.
  107. make:
  108. SCREEN _NEWIMAGE(800, 600, 32)
  109. LINE (0, 0)-(800, 600), _RGB32(255, 255, 255), BF
  110. _TITLE "Press 'S' to Save, 'P' to Print, Left and Right Arrow Keys To Switch Months, Space Bar For Different One, or 'Esc' to Quit."
  111. COLOR _RGB32(0, 0, 0), _RGB32(255, 255, 255)
  112. LOCATE 3, 42: PRINT month$; "  "; yy
  113.  
  114. FOR x = 20 TO 780 STEP 108
  115.     LINE (x, 100)-(x, 580), _RGB32(0, 0, 0)
  116. FOR z = 100 TO 580 STEP 80
  117.     LINE (16, z)-(780, z), _RGB32(0, 0, 0)
  118.  
  119. LOCATE 5, 8: PRINT "SUNDAY"
  120. LOCATE 5, 21: PRINT "MONDAY"
  121. LOCATE 5, 34: PRINT "TUESDAY"
  122. LOCATE 5, 47: PRINT "WEDNESDAY"
  123. LOCATE 5, 60: PRINT "THURSDAY"
  124. LOCATE 5, 75: PRINT "FRIDAY"
  125. LOCATE 5, 87: PRINT "SATURDAY"
  126.  
  127. 'Finding Date of Easter
  128. PQA = yy
  129. GOSUB PAQUES
  130. 'month = PQM, day = PQJ, year = PQA
  131.  
  132. 'This section puts the right dates and holidays in the right squares for the calendar.
  133. w = (weekday * 108) + 25
  134. FOR weeky = 110 TO 570 STEP 80
  135.     FOR dayx = w TO 692 STEP 108
  136.         _LIMIT 1000
  137.         dd = dd + 1
  138.         GetDay mm, dd, y, weekday
  139.         IF weekday = 1 THEN GOSUB coloring:
  140.         IF weekday <> 1 THEN COLOR _RGB32(0, 0, 0), _RGB32(255, 255, 255)
  141.         dd$ = STR$(dd)
  142.         _FONT 8
  143.         IF dd = dayinfo(infos) THEN
  144.             GOSUB coloring:
  145.             i = LEN(newinfo$(infos))
  146.             IF i < 8 THEN ii = 25
  147.             IF i > 7 AND i < 12 THEN ii = 11
  148.             IF i > 11 AND i < 14 THEN ii = 5
  149.             IF i > 13 THEN ii = 2
  150.             _PRINTSTRING (dayx + ii, weeky + 20), newinfo$(infos)
  151.             infos = infos + 1
  152.             ye = 1
  153.         END IF
  154.         IF holidays = 0 THEN GOTO skip:
  155.         IF m = 1 AND dd = 1 THEN
  156.             GOSUB coloring:
  157.             _PRINTSTRING (dayx + 15, weeky + 60), "New Years"
  158.         END IF
  159.         IF m = 1 AND weekday = 2 AND dd > 14 AND dd < 22 THEN
  160.             GOSUB coloring:
  161.             _PRINTSTRING (dayx + 25, weeky + 60), "MLK Jr."
  162.         END IF
  163.         IF m = 2 AND dd = 2 THEN
  164.             GOSUB coloring:
  165.             _PRINTSTRING (dayx + 13, weeky + 60), "Groundhog"
  166.         END IF
  167.         IF m = 2 AND weekday = 2 AND dd > 14 AND dd < 22 THEN
  168.             GOSUB coloring:
  169.             _PRINTSTRING (dayx + 10, weeky + 60), "Presidents"
  170.         END IF
  171.         IF m = 2 AND dd = 14 THEN
  172.             GOSUB coloring:
  173.             _PRINTSTRING (dayx + 10, weeky + 60), "Valentines"
  174.         END IF
  175.         IF m = 3 AND dd = 17 THEN
  176.             GOSUB coloring:
  177.             _PRINTSTRING (dayx + 5, weeky + 60), "St. Patrick"
  178.         END IF
  179.         IF m = PQM AND dd = PQJ THEN
  180.             GOSUB coloring:
  181.             _PRINTSTRING (dayx + 25, weeky + 60), "Easter"
  182.         END IF
  183.         IF m = 4 AND dd > 23 AND weekday = 7 THEN
  184.             GOSUB coloring:
  185.             _PRINTSTRING (dayx + 25, weeky + 60), "Arbor"
  186.         END IF
  187.         IF m = 5 AND weekday = 0 AND dd > 14 AND dd < 22 THEN
  188.             GOSUB coloring:
  189.             _PRINTSTRING (dayx + 2, weeky + 60), "Armed Forces"
  190.         END IF
  191.         IF m = 5 AND weekday = 2 AND dd > 24 THEN
  192.             GOSUB coloring:
  193.             _PRINTSTRING (dayx + 15, weeky + 60), "Memorial"
  194.         END IF
  195.         IF m = 5 AND weekday = 1 AND dd > 7 AND dd < 15 THEN
  196.             GOSUB coloring:
  197.             _PRINTSTRING (dayx + 2, weeky + 60), "Mother's Day"
  198.         END IF
  199.         IF m = 6 AND weekday = 1 AND dd > 14 AND dd < 22 THEN
  200.             GOSUB coloring:
  201.             _PRINTSTRING (dayx + 2, weeky + 60), "Father's Day"
  202.         END IF
  203.         IF m = 6 AND dd = 14 THEN
  204.             GOSUB coloring:
  205.             _PRINTSTRING (dayx + 35, weeky + 60), "Flag"
  206.         END IF
  207.         IF m = 7 AND dd = 4 THEN
  208.             GOSUB coloring:
  209.             _PRINTSTRING (dayx + 2, weeky + 60), "Independence"
  210.         END IF
  211.         IF m = 9 AND weekday = 2 AND dd < 8 THEN
  212.             GOSUB coloring:
  213.             _PRINTSTRING (dayx + 27, weeky + 60), "Labor"
  214.         END IF
  215.         IF m = 10 AND dd > 9 AND dd < 16 AND weekday = 2 THEN
  216.             GOSUB coloring:
  217.             _PRINTSTRING (dayx + 17, weeky + 60), "Columbus"
  218.         END IF
  219.         IF m = 10 AND dd = 31 THEN
  220.             GOSUB coloring:
  221.             _PRINTSTRING (dayx + 15, weeky + 60), "Halloween"
  222.         END IF
  223.         IF m = 11 AND dd = 11 THEN
  224.             GOSUB coloring:
  225.             _PRINTSTRING (dayx + 19, weeky + 60), "Veterans"
  226.         END IF
  227.         IF m = 11 AND dd > 21 AND dd < 29 AND weekday = 5 THEN
  228.             GOSUB coloring:
  229.             _PRINTSTRING (dayx + 2, weeky + 60), "Thanksgiving"
  230.         END IF
  231.         IF m = 12 AND dd = 25 THEN
  232.             GOSUB coloring:
  233.             _PRINTSTRING (dayx + 15, weeky + 60), "Christmas"
  234.         END IF
  235.         skip:
  236.         ye = 0
  237.         _FONT 16
  238.         _PRINTSTRING (dayx, weeky), dd$
  239.         _FONT 8
  240.         IF dd = days THEN _FONT 16: GOTO more2:
  241.     NEXT dayx
  242.     w = 25
  243. NEXT weeky
  244.  
  245. more2:
  246. _LIMIT 1000
  247. a$ = INKEY$
  248. IF a$ = CHR$(27) THEN CLS: PRINT: PRINT: PRINT "Goodbye.": END
  249. IF a$ = "s" OR a$ = "S" THEN GOTO saving:
  250. IF a$ = " " THEN GOTO start:
  251. IF a$ = "p" OR a$ = "P" THEN
  252.     'printer prep (code copied and pasted from bplus Free Calendar Program)
  253.     YMAX = _HEIGHT: XMAX = _WIDTH
  254.     landscape& = _NEWIMAGE(YMAX, XMAX, 32)
  255.     _MAPTRIANGLE (XMAX, 0)-(0, 0)-(0, YMAX), 0 TO(0, 0)-(0, XMAX)-(YMAX, XMAX), landscape&
  256.     _MAPTRIANGLE (XMAX, 0)-(XMAX, YMAX)-(0, YMAX), 0 TO(0, 0)-(YMAX, 0)-(YMAX, XMAX), landscape&
  257.     _PRINTIMAGE landscape&
  258.  
  259. IF a$ = CHR$(0) + CHR$(77) THEN
  260.     m = m + 1
  261.     IF m > 12 THEN
  262.         m = 1
  263.         yy = yy + 1
  264.     END IF
  265.     y = yy
  266.     IF y > 9999 THEN y = 1753
  267.     dd = 0
  268.     leap = 0
  269.     _DELAY .1
  270.     CLS
  271.     GOTO calculate:
  272. IF a$ = CHR$(0) + CHR$(75) THEN
  273.     m = m - 1
  274.     IF m < 1 THEN
  275.         m = 12
  276.         yy = yy - 1
  277.     END IF
  278.     y = yy
  279.     IF y < 1753 THEN y = 9999
  280.     dd = 0
  281.     leap = 0
  282.     _DELAY .1
  283.     CLS
  284.     GOTO calculate:
  285.  
  286. GOTO more2:
  287.  
  288. adding:
  289. add:
  290. olddayinfo = dayinfo(info)
  291. info = info + 1
  292. infos = 1
  293. adding2:
  294. IF info > days THEN PRINT "You have reached the maximum amount of holidays or info for this month.": INPUT "Press enter to create calendar.", pe$: RETURN
  295. PRINT "Your dates must go in order here."
  296. PRINT "for example, you cannot put info for day 15 and then put info for day 1."
  297. PRINT "They must all follow from smallest number to highest number or it will tell you to start over again."
  298. PRINT "Also, you cannot change a day by doing it over again, so if you mess up, create a new month."
  299. PRINT info; ". ";
  300. INPUT "Which day of the month for new holiday or information: ", dayinfo(info)
  301. IF dayinfo(info) > days THEN PRINT "That day is not on this calendar, try again.": GOTO adding2:
  302. IF dayinfo(info) < 1 THEN PRINT "You cannot type a date less than 1, try again.": GOTO adding2:
  303. IF dayinfo(info) <> INT(dayinfo(info)) THEN PRINT "You cannot type a decimal for a date, try again.": GOTO adding2:
  304. IF dayinfo(info) < olddayinfo THEN
  305.     PRINT
  306.     PRINT "You have put a date before your previous one which cannot work, start over from your first date."
  307.     FOR dl = 1 TO info
  308.         newinfo$(dl) = ""
  309.         dayinfo(dl) = 0
  310.     NEXT dl
  311.     olddayinfo = 0
  312.     info = 0
  313.     GOTO add:
  314. adding3:
  315. PRINT "Type up to 12 letters, numbers, or spaces that will be put for that day."
  316. INPUT "->", newinfo$(info)
  317. infoamount = LEN(newinfo$(info))
  318. IF infoamount > 12 THEN PRINT "Too long, try again.": GOTO adding3:
  319. IF infoamount < 1 THEN PRINT "Nothing typed, try again.": GOTO adding3:
  320. INPUT "Do you want to add more (Y/N):", yn$
  321. IF LEFT$(yn$, 1) = "y" OR LEFT$(yn$, 1) = "Y" THEN GOTO adding:
  322.  
  323. 'Color all Sundays and holidays
  324. coloring:
  325. IF ye = 1 THEN RETURN
  326. LINE (dayx - 4, weeky - 9)-(dayx + 102, weeky + 68), _RGB32(255, 255, 127), BF: COLOR _RGB32(0, 0, 0), _RGB32(255, 255, 127)
  327.  
  328.  
  329. 'Find the right date for Easter.
  330. PAQUES:
  331. PQM = INT(PQA / 100): PQ1 = PQA - PQM * 100: PQJ = INT(((PQA / 19 - INT(PQA / 19)) + .001) * 19)
  332. PQ2 = INT(PQM / 4): PQ3 = INT(((PQM / 4) - PQ2 + .001) * 4): PQ4 = INT((8 + PQM) / 25)
  333. PQ5 = INT((1 + PQM - PQ4 + .001) / 3): PQ4 = (15 + 19 * PQJ + PQM - PQ2 - PQ5 + .001) / 30: PQ4 = PQ4 - INT(PQ4)
  334. PQ4 = INT(PQ4 * 30): PQ5 = INT(PQ1 / 4): PQ6 = ((PQ1 / 4) - PQ5) * 4
  335. PQ7 = (32 + 2 * PQ3 + 2 * PQ5 - PQ4 - PQ6 + .001) / 7: PQ7 = (PQ7 - INT(PQ7)) * 7: PQ6 = (PQJ + 11 * PQ4 + 22 * PQ7) / 451
  336. PQ6 = INT(PQ6): PQ2 = (114 + PQ4 + PQ7 - 7 * PQ6) / 31: PQM = INT(PQ2): PQJ = INT((PQ2 - PQM + .001) * 31 + 1)
  337.  
  338.  
  339. 'This section saves the calendar to a BMP file along with the SUB at the end of this program.
  340. saving:
  341. mo$ = STR$(m)
  342. mo$ = LTRIM$(RTRIM$(mo$))
  343. year$ = STR$(yy)
  344. year$ = LTRIM$(RTRIM$(year$))
  345. nm$ = mo$ + "-"
  346. nm$ = LTRIM$(RTRIM$(nm$))
  347. nm$ = nm$ + year$
  348. nm$ = LTRIM$(RTRIM$(nm$))
  349. SaveImage 0, nm$ 'saves entire program screen,"
  350. nm2$ = nm$ + ".bmp"
  351. nm2$ = LTRIM$(RTRIM$(nm2$))
  352. PRINT "                                           Saving"
  353. PRINT "                          "; nm2$; " has been saved to your computer."
  354. INPUT "                         Do you wish to make another calendar (Y/N)"; ag$
  355. IF LEFT$(ag$, 1) = "y" OR LEFT$(ag$, 1) = "Y" THEN GOTO start:
  356. PRINT "                         Goodbye."
  357.  
  358. weekdays:
  359.  
  360. 'This section gets the right weekday.
  361. SUB GetDay (mm, dd, y, weekday) 'use 4 digit year
  362.     'From Zeller's congruence: https://en.wikipedia.org/wiki/Zeller%27s_congruence
  363.     IF mm < 3 THEN mm = mm + 12: y = y - 1
  364.     century = y MOD 100
  365.     zerocentury = y \ 100
  366.     weekday = (dd + INT(13 * (mm + 1) / 5) + century + INT(century / 4) + INT(zerocentury / 4) + 5 * zerocentury) MOD 7
  367.  
  368. 'This section saves the .bmp picture file.
  369. SUB SaveImage (image AS LONG, filename AS STRING)
  370.     bytesperpixel& = _PIXELSIZE(image&)
  371.     IF bytesperpixel& = 0 THEN PRINT "Text modes unsupported!": END
  372.     IF bytesperpixel& = 1 THEN bpp& = 8 ELSE bpp& = 24
  373.     x& = _WIDTH(image&)
  374.     y& = _HEIGHT(image&)
  375.     b$ = "BM????QB64????" + MKL$(40) + MKL$(x&) + MKL$(y&) + MKI$(1) + MKI$(bpp&) + MKL$(0) + "????" + STRING$(16, 0) 'partial BMP header info(???? to be filled later)
  376.     IF bytesperpixel& = 1 THEN
  377.         FOR c& = 0 TO 255 ' read BGR color settings from JPG image + 1 byte spacer(CHR$(0))
  378.             cv& = _PALETTECOLOR(c&, image&) ' color attribute to read.
  379.             b$ = b$ + CHR$(_BLUE32(cv&)) + CHR$(_GREEN32(cv&)) + CHR$(_RED32(cv&)) + CHR$(0) 'spacer byte
  380.         NEXT
  381.     END IF
  382.     MID$(b$, 11, 4) = MKL$(LEN(b$)) ' image pixel data offset(BMP header)
  383.     lastsource& = _SOURCE
  384.     _SOURCE image&
  385.     IF ((x& * 3) MOD 4) THEN padder$ = STRING$(4 - ((x& * 3) MOD 4), 0)
  386.     FOR py& = y& - 1 TO 0 STEP -1 ' read JPG image pixel color data
  387.         r$ = ""
  388.         FOR px& = 0 TO x& - 1
  389.             c& = POINT(px&, py&) 'POINT 32 bit values are large LONG values
  390.             IF bytesperpixel& = 1 THEN r$ = r$ + CHR$(c&) ELSE r$ = r$ + LEFT$(MKL$(c&), 3)
  391.         NEXT px&
  392.         d$ = d$ + r$ + padder$
  393.     NEXT py&
  394.     _SOURCE lastsource&
  395.     MID$(b$, 35, 4) = MKL$(LEN(d$)) ' image size(BMP header)
  396.     b$ = b$ + d$ ' total file data bytes to create file
  397.     MID$(b$, 3, 4) = MKL$(LEN(b$)) ' size of data file(BMP header)
  398.     IF LCASE$(RIGHT$(filename$, 4)) <> ".bmp" THEN ext$ = ".bmp"
  399.     f& = FREEFILE
  400.     OPEN filename$ + ext$ FOR OUTPUT AS #f&: CLOSE #f& ' erases an existing file
  401.     OPEN filename$ + ext$ FOR BINARY AS #f&
  402.     PUT #f&, , b$
  403.     CLOSE #f&
  404.  

Here is how I use the variables. m = month, dd = day. coloring: is just where I fill in the holidays and Sundays with a color. 

Code: QB64: [Select]
  1.         IF m = PQM AND dd = PQJ THEN
  2.             GOSUB coloring:
  3.             _PRINTSTRING (dayx + 25, weeky + 60), "Easter"
  4.         END IF
  5.  
« Last Edit: December 29, 2020, 07:48:02 pm by SierraKen »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Calendar 2021
« Reply #11 on: January 05, 2021, 11:09:19 pm »
Now that I'm back home, I've managed to work on this little project once again, and it now allows us to add up to 10 custom events to our days.

 
SS1.png


 
SS2.png


Project is being uploaded to my public OneDrive folder, and should be available for download in a few moments, if anyone wants to test it out at:  https://1drv.ms/u/s!AknUrv8RXVYMkIMiwSDNKinhlbfuHg?e=6eumhM
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Ryster

  • Newbie
  • Posts: 77
    • View Profile
Re: Calendar 2021
« Reply #12 on: January 07, 2021, 01:38:44 pm »
Feel free to download my calendar (calculator), which I have been working on for 15 years and is constantly being expanded. I can say with full responsibility that there is no other such calendar with such computing capabilities anywhere in the world (who would like to write). The program includes several dozen calculation subroutines (58). The calculation range is 1 - 9999. The exe file weighs over 21.1 MB. The program is only in the 64-bit version, because the 32-bit version cannot cope with the code due to the size of the file. Due to the fact that I was directly ridiculed not only on this Forum, but also on N54 once, when I reported irregularities, please find the link to the website on your own, if someone is interested in this topic.
If someone was offended by this entry - sorry. Program language - Polish.
Regards - Ryster

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Calendar 2021
« Reply #13 on: January 07, 2021, 03:12:44 pm »
Ryster I could not find what you're talking about. Link plz.
You're not done when it works, you're done when it's right.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Calendar 2021
« Reply #14 on: January 07, 2021, 03:25:06 pm »
Edit: sorry this distracted from lovely thread Steve started.

« Last Edit: January 08, 2021, 11:59:25 am by bplus »