October 28, 2020, 11:11:32 PM

Author Topic: [bmx] Calendar  (Read 2084 times)

Offline Krischan

  • Full Member
  • ***
  • Posts: 221
    • Krischan's Homepage
[bmx] Calendar
« on: November 09, 2017, 06:30:12 PM »
This is a basic calendar output inspired by the Windows 10 calendar. It contains some useful functions like get the current UNIX timestamp from OS, create a formatted time output from a timestamp or calculate the current weekday and considers leap years (9/11 was on a tuesday, correct?). Could be optimized regarding the pre/after days and uses too many globals but can be a still good start to deal with a custom calender as I couldn't find any useful examples in the archives for Blitzmax. ;D

Use Arrow keys to cycle through months and years, limited to 1970-2100.

Code: BlitzMax
  1. SuperStrict
  2.  
  3. Framework brl.glmax2d
  4. Import brl.retro
  5.  
  6. AppTitle = "Krischans Blitzmax Calendar"
  7.  
  8. ' input year/month: current date
  9. Local Scale:Float = 2
  10. Local border:Int = 10
  11. Local curdate:String = FTimestamp(GetTimeStamp(), "%Y%m")
  12. Local y:Int = Int(Mid(curdate, 1, 4))
  13. Local m:Int = Int(Mid(curdate, 5, 2))
  14.  
  15. ' number of days and month names
  16. Global days:Int[] = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
  17. Global months:String[] = ["", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
  18.  
  19. ' output
  20. Global out:String[10]
  21. Global header:String[4]
  22. Global pre:String
  23. Global aft:String[4]
  24. Global o:Int
  25.  
  26. ' next month / old month
  27. Global mm:Int
  28. Global om:Int = Null
  29.  
  30. ' next year / old year
  31. Global yy:Int
  32. Global oy:Int = Null
  33.  
  34. Graphics((160 * Scale) + (border * Scale * 2), (160 * Scale) + (border * Scale * 2), 0, 60)
  35.  
  36. ' selected month/year must match input
  37. mm = m
  38. yy = y
  39.  
  40. CreateCalendar()
  41.  
  42. While Not (KeyHit(KEY_ESCAPE) Or AppTerminate())
  43.  
  44.         Cls
  45.                
  46.         ' change month with LR arrows
  47.         mm:+(KeyHit(KEY_RIGHT) - KeyHit(KEY_LEFT))
  48.         If om <> mm Then
  49.        
  50.                 ' wrap months and years
  51.                 If mm < 1 Then mm = 12 ; yy:-1
  52.                 If mm > 12 Then mm = 1 ; yy:+1
  53.                
  54.                 om = mm
  55.                
  56.                 CreateCalendar()
  57.        
  58.         EndIf
  59.  
  60.         ' change year with UD arrows
  61.         yy:+(KeyHit(KEY_UP) - KeyHit(KEY_DOWN))
  62.         If oy <> yy Then
  63.        
  64.                 ' limit years
  65.                 If yy < 1970 Then yy = 1970
  66.                 If yy > 2100 Then yy = 2100
  67.                
  68.                 oy = yy
  69.                
  70.                 CreateCalendar()
  71.        
  72.         EndIf
  73.                                
  74.         ' output calendar
  75.         SetScale(Scale, Scale)
  76.         SetColor(255, 255, 255)
  77.         SetBlend ALPHABLEND
  78.  
  79.         ' current month days
  80.         SetAlpha(0.8)
  81.         For Local i:Int = 0 To o
  82.                
  83.                 DrawText out[i], (border * Scale), (border * Scale) + (i * (15 * Scale))
  84.                
  85.         Next
  86.        
  87.         ' days before and after to fill gaps
  88.         SetAlpha(0.25)
  89.         DrawText pre, (border * Scale), (border * Scale) + (4 * (15 * Scale))
  90.        
  91.         For Local i:Int = 0 To 2
  92.        
  93.                 DrawText aft[i], (border * Scale), (border * Scale) + ((o + i) * (15 * Scale))
  94.                
  95.         Next
  96.                
  97.         Flip
  98.        
  99. Wend
  100.  
  101. End
  102.  
  103. ' creates the calendar
  104. Function CreateCalendar()
  105.  
  106.         Local cnt1:Int = 0
  107.         Local cnt2:Int = 0
  108.         Local cnt3:Int = 0
  109.         Local mm2:Int
  110.  
  111.         ' reset output
  112.         out = New String[10]
  113.         pre = ""
  114.         aft = New String[4]
  115.         o = 0
  116.  
  117.         ' fix leap days
  118.         FixLeapYear(yy)
  119.        
  120.         ' calculate weekday of given month
  121.         Local weekday:Int = GetWeekDay(yy, mm, 1) Mod 7
  122.        
  123.         ' calender header
  124.         out[0] = months[mm] + " " + yy
  125.         out[1] = ""
  126.         out[2] = "Mo Tu We Th Fr Sa Su"
  127.         out[3] = "===================="
  128.        
  129.         ' calendar whitespaces
  130.         If weekday > 0 Then
  131.        
  132.                 ' fill gaps if week doesn't start at monday
  133.                 For Local d:Int = 1 To weekday
  134.                        
  135.                         out[4]:+"   "
  136.                        
  137.                 Next
  138.                
  139.                 ' previous month
  140.                 mm2 = mm - 1
  141.                 If mm2 < 1 Then mm2 = 12
  142.                                                
  143.                 ' add previous month days (pre)
  144.                 For Local d:Int = days[mm2] - weekday + 1 To days[mm2]
  145.                
  146.                         pre:+FormatDay(d)
  147.                
  148.                 Next
  149.                
  150.                 o = 4
  151.                
  152.         Else
  153.        
  154.                 o = 3
  155.                
  156.         EndIf
  157.        
  158.         ' calendar days
  159.         For Local d:Int = 1 To days[mm]
  160.        
  161.                 ' count day on current row
  162.                 cnt1:+1
  163.                
  164.                 ' next row if sunday
  165.                 If (d + weekday - 1) Mod 7 = 0 Then o:+1 ; cnt1 = 0
  166.        
  167.                 ' add row to output
  168.                 out[o]:+FormatDay(d)
  169.        
  170.         Next
  171.        
  172.         ' month stops and it is not sunday?
  173.         If cnt1 <> 6 Then
  174.        
  175.                 ' next month
  176.                 mm2 = mm + 1
  177.                 If mm2 > 12 Then mm2 = 1
  178.                
  179.                 ' fill gaps
  180.                 For Local i:Int = 0 To cnt1
  181.                
  182.                         aft[0]:+"   "
  183.                
  184.                 Next
  185.        
  186.                 ' add next month days (aft)
  187.                 For Local d:Int = 1 To 6 - cnt1
  188.                
  189.                         aft[0]:+FormatDay(d)
  190.                         cnt2:+1
  191.                
  192.                 Next
  193.  
  194.         EndIf
  195.        
  196.         ' fill additional aft rows
  197.         If o < 9 Then
  198.                
  199.                 ' next month
  200.                 mm2 = mm + 1
  201.                 If mm2 > 12 Then mm2 = 1
  202.                                
  203.                 For Local i:Int = 0 To 8 - o
  204.                        
  205.                         ' add next month days (aft)
  206.                         For Local d:Int = cnt2 + cnt3 + 1 To cnt2 + cnt3 + 7
  207.                        
  208.                                 aft[1 + i]:+FormatDay(d)
  209.                                 cnt3:+1
  210.                        
  211.                         Next
  212.                        
  213.                         ' prepare next row (if short month like Feb. 1993)
  214.                         cnt3 = cnt2 + 7
  215.                        
  216.                 Next
  217.  
  218.         EndIf
  219.  
  220. End Function
  221.  
  222. ' output formatted day
  223. Function FormatDay:String(d:Int)
  224.  
  225.         Local day:String = d + " "
  226.         If d < 10 Then day = " " + d + " "
  227.        
  228.         Return day
  229.  
  230. End Function
  231.  
  232. ' get day of week for a given date (0-6, 0=Monday)
  233. Function GetWeekDay:Int(y:Int, m:Int, d:Int)
  234.  
  235.         Local t:Int[] = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]
  236.  
  237.         If m < 3 Then y:-1
  238.  
  239.         Return ((y + y / 4 - y / 100 + y / 400 + t[m - 1] + d) - 1) Mod 7
  240.  
  241. End Function
  242.  
  243. ' fix leap years in months array
  244. Function FixLeapYear:Int(year:Int)
  245.  
  246.         If (((year Mod 4 = 0) And (year Mod 100 <> 0)) Or (year Mod 400 = 0)) Then
  247.        
  248.                 days[2] = 29
  249.        
  250.         Else
  251.                
  252.                 days[2] = 28
  253.                
  254.         EndIf
  255.        
  256. End Function
  257.  
  258. ' returns formatted time string
  259. Function FTimestamp:String(timestamp:Int, format:String = "%Y-%m-%d %H:%M:%S")
  260.  
  261.         Local time:Int Ptr, buff:Byte[256]
  262.        
  263.         time = VarPtr(timestamp)
  264.         strftime_(buff, 256, format, localtime_(time))
  265.        
  266.         Return String.FromCString(buff)
  267.        
  268. End Function
  269.  
  270. ' get current UNIX timestamp from OS
  271. Function GetTimeStamp:Int()
  272.  
  273.         Local time:Int[256]
  274.         time_(time)
  275.         return time[0]
  276.  
  277. End Function
  278.  
  279. ' returns the exact! unix timestamp for given YEARS,MONTHS,DAYS,HOURS,MINUTES,SECONDS (not used in this example)
  280. Function GetUnixTimestamp:Int(yy:Int, mm:Int, dd:Int, hh:Int, ii:Int, ss:Int)
  281.  
  282.         Local days:Int[] = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]
  283.         Local years:Int = yy - 1970
  284.         Local leap:Int = ((yy - 1) - 1968) / 4 - ((yy - 1) - 1900) / 100 + ((yy - 1) - 1600) / 400
  285.        
  286.         Local unixtime:Int = ss + 60 * ii + 60 * 60 * hh + (days[mm - 1] + dd - 1) * 60 * 60 * 24 + (years * 365 + leap) * 60 * 60 * 24
  287.  
  288.         If ((mm > 2) And (yy Mod 4 = 0 And (yy Mod 100 <> 0 Or yy Mod 400 = 0))) Then
  289.        
  290.                 ' leap day
  291.                 unixtime:+(60 * 60 * 24)
  292.                
  293.         End If
  294.  
  295.   Return unixtime
  296.  
  297. End Function
Kind regards
Krischan

Windows 10 Pro | i7 9700K@ 3.6GHz | RTX 2080 8GB]
My Blitzbasic Archive | Extrasolar Project | My Github projects

Offline degac

  • Full Member
  • ***
  • Posts: 159
    • graphio.net
Re: [bmx] Calendar
« Reply #1 on: November 09, 2017, 06:47:58 PM »
Hi

I've collected & rearranged some 'temporal' functions about date & time! (I need for some apps I'm using at work!)
And - after many google's jump - I think I've found the 'right' functions about time conversion (tested the results with many 'time converter' online, so I'm quite sure they works well.

ps: there's a function 'Pad() that's is not defined in this 'library'... just use a simple string in case

pps: for MaxGUI I wrote (many years ago, with the help of Sebholl!) a 'calendar' gadget... that' mimics the OS one (! personal note I should check the temporal functions in it!) :D

Code: [Select]
Rem
Library Time Function

04.11.2017
Time Difference ! difference between two dates: 01.01.2017 and 01.01.2017 should be ZERO??

fixed: support for 2 date format (input) DDMMYYYY ir DD/MM/YEAR

*** main bug: Conversion to/from Julian was wrong!!
*** changed the Julian2 Gregorian function too...



---
ChangeDate()
GetDayOfTheWeek:INT( date) ... 0 Sunday...
IsLeap( date ) ... true or false
TimeDifference (type, date1, date2) where type="D" for days, "M" for month, "Y" for years
Conv_Date2Julian(date)
Conv_Julian2Date(julian_value,date value)

End Rem

Global _localized_month:String[]=["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"]
Function ChangeDate:String(mese:Int=1)
Return _localized_month[mese-1]
End Function


Function GetDayOfTheWeek:Int(_data$="")
Rem
return an INT 0 to 6
0 = sunday... 1 =monday 2=tuesday...
End Rem

Local year:Int,month:Int,day:Int
If _data="" Return -1
If _data.contains("/")=False
_data=_data[..2]+"/"+_data[2..4]+"/"+_data[4..]
End If
year=Int(_data[6..])
month=Int(_data[3..5])
day=Int(_data[..2])

Local A:Int,Y:Int,M:Int
Local D:Int
a = (14 - month) / 12
y = year - a
m = month + 12*a - 2

Return ((day + y + y/4 - y/100 + y/400 + (31*m)/12))Mod 7

End Function

Function IsLeap:Int(SomeDate:String)   ' Pass either just the year, or a "DD MMM YYYY" BlitzMax data string
Local Jaar:Int=Int(Right$(SomeDate,4))
If ((Jaar Mod 4) = 0 And (Jaar Mod 100) <> 0) Or ((Jaar Mod 4) = 0 And (Jaar Mod 400) = 0) Then
' Leap Year -- Any year divisible by 4, except the centuries unless they are multiples of 400
Return True
Else
' Not a Leap Year
Return False
End If
End Function

'------------------------------- temporal conversion ------------------------------


Function Conv_Date2Julian:Float(_data$="")
If _data="" Return -1
If _data.contains("/")=False
_data=_data[..2]+"/"+_data[2..4]+"/"+_data[4..]
End If

Local year:Int,month:Int,day:Int

year=Int(_data[6..])
month=Int(_data[3..5])
day=Int(_data[..2])
' Print "Date : "+_data+" : "+day+" "+month+" "+year

Local a:Int,b:Int,c:Int,d:Int
Local e:Int,f:Int,jd:Float

a=year/100
b=a/4
c=2-a+b
e=365.25*(year+4716)
f=30.6001*(month+1)
jd=Float(c+day+e+f-1524.5)
Return JD

End Function

Function old_Conv_Date2Julian:Int(_data$="")
'accept data format 15022017 or 15/02/2017
If _data="" Return -1
If _data.contains("/")=False
_data=_data[..2]+"/"+_data[2..4]+"/"+_data[4..]
End If

Local year:Int,month:Int,day:Int

year=Int(_data[6..])
month=Int(_data[3..5])
day=Int(_data[..2])

'Print "Date to convert: "+day+" "+month+" "+year

Local JulianDate:Int
' conversion taken from a website (lost link)
JulianDate = 367 * Year - ((7 * (Year + 5001 + ((Month - 9) / 7))) / 4) + ((275 * Month) / 9) + Day + 1729777

Return JulianDate
End Function

Function Conv_Julian2Date:Int(Jd:Float,date$ Var)

Local L:Float,N:Int,I:Int,K:Int,YEAR:Int,MONTH:Int,DAY:Int,J:Int
'Print "JD :"+(jd-Int(jd))
L= JD+68569
    N= 4*L/146097

    L= Int(L-(146097*N+3)/4)
    I= 4000*(L+1)/1461001
    L= L-1461*I/4+31
    J= 80*L/2447
    K= L-2447*J/80
    L= J/11
    J= J+2-12*L
    I= 100*(N-49)+I+L
   
YEAR= I
    MONTH= J
    DAY= K+(jd-Int(jd))

date=pad(day,"00",2)+"/"+pad(month,"00",2)+"/"+pad(year,"0000",4)

End Function


Function old_Conv_Julian2Date(pJulian:Int, date$ Var)
Local l:Int
Local k:Int
Local n:Int
Local i:Int
Local j:Int
Local day:Int,month:Int,year:Int

' conversion taken from a website (lost link)
j = pJulian + 1402
k = ((j - 1) / 1461)
l = j - 1461 * k
n = ((l - 1) / 365) - (l / 1461)
i = l - 365 * n + 30
j = ((80 * i) / 2447)
Day = i - ((2447 * j) / 80)
i = (j / 11)
Month = j + 2 - 12 * i
Year = 4 * k + n + i - 4716

date=pad(day,"00",2)+"/"+pad(month,"00",2)+"/"+pad(year,"0000",4)
End Function

Function TimeDifference:Int(pInterval$, date1$="",date2$="")
'date format 15/02/2017
Local i:Int
Local j:Int

If date1="" Or date2="" Return -1

pInterval=Upper(pinterval)

Local year1:Int,year2:Int
Local month1:Int,month2:Int
Local day1:Int,day2:Int

If date1.contains("/")=False
date1=date1[..2]+"/"+date1[2..4]+"/"+date1[4..]
End If

If date2.contains("/")=False
date2=date2[..2]+"/"+date2[2..4]+"/"+date2[4..]
End If



year1=Int(date1[6..])
month1=Int(date1[3..5])
day1=Int(date1[..2])

year2=Int(date2[6..])
month2=Int(date2[3..5])
day2=Int(date2[..2])



Select pInterval$
Case "Y" 'Year
i = Year1 - Year2
Case "M" 'Month
i = (Year2 - Year1) * 12 + (Month2 - Month1)
Case "D" 'Day
'Converts in julian to substract days
i = Conv_Date2Julian(Date2) - Conv_Date2Julian(Date1)'+1
End Select

Return i
End Function
If there's a problem, there's at least one solution.
www.blitzmax.org

Offline Derron

  • Hero Member
  • *****
  • Posts: 3237
Re: [bmx] Calendar
« Reply #2 on: November 09, 2017, 08:03:17 PM »

Quote from: degac
[/size]
Code: [Select]
   04.11.2017    Time Difference ! difference between two dates: 01.01.2017 and 01.01.2017 should be ZERO??[/size]

Of course it should. Substitute equal values with X ... so you ask: "difference between two dates: x and x should be ZERO??" - yes, as x-x = 0.This works also if you think about what the date means. Yes, there is no exact time given (hours, minutes...) but this is not needed as both dates are using your personal definition of either time or assumption. Means, if you only give a date, then the hours are not of importance. If they would be important, you would have mentioned them. Mathematically this means, that a given date without hour:minute:second:... should always assume the same "time of that day" (eg 0:00:00:...). And then calculation is possible without much hassle.


31.12.2016 23:50 to 01.01.2017 would then result in 10 minutes difference.byeRon

Offline degac

  • Full Member
  • ***
  • Posts: 159
    • graphio.net
Re: [bmx] Calendar
« Reply #3 on: November 09, 2017, 08:16:14 PM »
LOL!
Let me explain... is not a dumb question as it could be :)
As I'm said, I'm using these functions in some applications at work.
Some of these are needed to calculate stock's age... so this is a remark for me about how to consider (or not) in the calculation.... the function returns (mathematically correct) the 'zero' value (of course!) (see the returned value, there's still the '+1 commented out!)
If there's a problem, there's at least one solution.
www.blitzmax.org

Offline Derron

  • Hero Member
  • *****
  • Posts: 3237
Re: [bmx] Calendar
« Reply #4 on: November 09, 2017, 08:42:46 PM »
I fully understand what you are saying.


In may game I have similar issues: GetDaysGone() and GetOnDay().  The latter one adds the +1 ;-)
In your application (stocks...) you will also never say "age = 1 day" if it is "1.1.2017 12:00" and the stock was created on "1.1.2017". In that case "GetAgeInDays()" should always return 0 - while "GetAgeInHours()" could return 12.


And if you want to know something like "stock's 3rd day on the market..." then you will add +1 in that function (which is my "GetOnDay()" doing).




bye
Ron

Offline Krischan

  • Full Member
  • ***
  • Posts: 221
    • Krischan's Homepage
Re: [bmx] Calendar
« Reply #5 on: November 10, 2017, 03:53:26 PM »
Here is a version which displays the current day, too. I've cross-checked my calendar with various sources in the internet and it should work at least until 1600 AD, or even farther back in time. Before 1600 the calculations vary but I think we don't really need this (the most important function is to determine the weekday of a given date and to identify leap years or the calender will display a wrong sheet, I've used a slightly modified Sakamoto's algorithm as it was easy to implement and seemed to work best) ::)

Code: BlitzMax
  1. SuperStrict
  2.  
  3. Framework brl.glmax2d
  4. Import brl.retro
  5.  
  6. AppTitle = "Krischans Blitzmax Calendar"
  7.  
  8. ' input year/month: current date
  9. Local Scale:Float = 2
  10. Local border:Int = 10
  11. Local curdate:String = FTimestamp(GetTimeStamp(), "%Y%m%d")
  12. Global curyear:Int = Int(Mid(curdate, 1, 4))
  13. Global curmonth:Int = Int(Mid(curdate, 5, 2))
  14. Global curday:Int = Int(Mid(curdate, 7, 2))
  15.  
  16. ' number of days and month names
  17. Global days:Int[] = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
  18. Global months:String[] = ["", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
  19.  
  20. ' output
  21. Global out:String[10]
  22. Global header:String[4]
  23. Global pre:String
  24. Global aft:String[4]
  25. Global o:Int
  26.  
  27. ' next month / old month
  28. Global mm:Int
  29. Global om:Int = Null
  30.  
  31. ' next year / old year
  32. Global yy:Int
  33. Global oy:Int = Null
  34.  
  35. Global dd:Int
  36. Global highx:Int
  37. Global highy:Int
  38.  
  39. Graphics((160 * Scale) + (border * Scale * 2), (160 * Scale) + (border * Scale * 2), 0, 60)
  40.  
  41. ' selected month/year must match input
  42. dd = curday
  43. mm = curmonth
  44. yy = curyear
  45.  
  46. CreateCalendar()
  47.  
  48. While Not (KeyHit(KEY_ESCAPE) Or AppTerminate())
  49.  
  50.         Cls
  51.                
  52.         ' change month with LR arrows
  53.         mm:+(KeyHit(KEY_RIGHT) - KeyHit(KEY_LEFT))
  54.         If om <> mm Then
  55.        
  56.                 ' wrap months and years
  57.                 If mm < 1 Then mm = 12 ; yy:-1
  58.                 If mm > 12 Then mm = 1 ; yy:+1
  59.                
  60.                 om = mm
  61.                
  62.                 CreateCalendar()
  63.        
  64.         EndIf
  65.  
  66.         ' change year with UD arrows
  67.         yy:+(KeyHit(KEY_UP) - KeyHit(KEY_DOWN))
  68.         If oy <> yy Then
  69.        
  70.                 ' limit years
  71.                 If yy < 1 Then yy = 1
  72.                 If yy > 2100 Then yy = 2100
  73.                
  74.                 oy = yy
  75.                
  76.                 CreateCalendar()
  77.        
  78.         EndIf
  79.                                
  80.         ' output calendar
  81.         SetScale(Scale, Scale)
  82.         SetColor(255, 255, 255)
  83.         SetBlend ALPHABLEND
  84.  
  85.         ' current month days
  86.         SetAlpha(0.8)
  87.         For Local i:Int = 0 To o
  88.                
  89.                 DrawText out[i], (border * Scale), (border * Scale) + (i * (15 * Scale))
  90.                
  91.         Next
  92.        
  93.         ' days before and after to fill gaps
  94.         SetAlpha(0.25)
  95.         DrawText pre, (border * Scale), (border * Scale) + (4 * (15 * Scale))
  96.        
  97.         For Local i:Int = 0 To 2
  98.        
  99.                 DrawText aft[i], (border * Scale), (border * Scale) + ((o + i) * (15 * Scale))
  100.                
  101.         Next
  102.        
  103.         If highx And highy Then
  104.        
  105.                 SetColor(64, 64, 64)
  106.                 SetAlpha(1.0)
  107.                 Local x:Int = (border * Scale) + (highx * TextWidth("   ") * Scale)
  108.                 Local y:Int = (border * Scale) + (highy * 15 * Scale)
  109.                 Local w:Int = TextWidth(" ") * Scale
  110.                 Local h:Int = TextHeight(" ") / 2 * Scale
  111.                                
  112.                 DrawRect(x * w, y * h, w, h)
  113.                 SetColor(0, 255, 0)
  114.                 DrawText curday, x, y
  115.                
  116.         EndIf
  117.                        
  118.         Flip
  119.        
  120. Wend
  121.  
  122. End
  123.  
  124. ' creates the calendar
  125. Function CreateCalendar()
  126.  
  127.         Local cnt1:Int = 0
  128.         Local cnt2:Int = 0
  129.         Local cnt3:Int = 0
  130.         Local mm2:Int
  131.  
  132.         ' reset output
  133.         out = New String[10]
  134.         pre = ""
  135.         aft = New String[4]
  136.         o = 0
  137.         highx = 0
  138.         highy = 0
  139.  
  140.         ' fix leap days
  141.         FixLeapYear(yy)
  142.        
  143.         ' calculate weekday of given month
  144.         Local weekday:Int = GetWeekDay(yy, mm, 1) Mod 7
  145.        
  146.         ' calender header
  147.         out[0] = months[mm] + " " + yy
  148.         out[1] = ""
  149.         out[2] = "Mo Tu We Th Fr Sa Su"
  150.         out[3] = "===================="
  151.        
  152.         ' calendar whitespaces
  153.         If weekday > 0 Then
  154.        
  155.                 ' fill gaps if week doesn't start at monday
  156.                 For Local d:Int = 1 To weekday
  157.                        
  158.                         out[4]:+"   "
  159.                        
  160.                 Next
  161.                
  162.                 ' previous month
  163.                 mm2 = mm - 1
  164.                 If mm2 < 1 Then mm2 = 12
  165.                                                
  166.                 ' add previous month days (pre)
  167.                 For Local d:Int = days[mm2] - weekday + 1 To days[mm2]
  168.                
  169.                         pre:+FormatDay(d)
  170.                
  171.                 Next
  172.                
  173.                 o = 4
  174.                
  175.         Else
  176.        
  177.                 o = 3
  178.                
  179.         EndIf
  180.        
  181.         ' calendar days
  182.         For Local d:Int = 1 To days[mm]
  183.        
  184.                 ' count day on current row
  185.                 cnt1:+1
  186.                
  187.                 ' next row if sunday
  188.                 If (d + weekday - 1) Mod 7 = 0 Then o:+1 ; cnt1 = 0
  189.                
  190.                 If d = dd And mm = curmonth And yy = curyear Then
  191.                
  192.                         highx = cnt1
  193.                         highy = o
  194.                
  195.                 EndIf
  196.        
  197.                 ' add row to output
  198.                 out[o]:+FormatDay(d)
  199.        
  200.         Next
  201.        
  202.         ' month stops and it is not sunday?
  203.         If cnt1 <> 6 Then
  204.        
  205.                 ' next month
  206.                 mm2 = mm + 1
  207.                 If mm2 > 12 Then mm2 = 1
  208.                
  209.                 ' fill gaps
  210.                 For Local i:Int = 0 To cnt1
  211.                
  212.                         aft[0]:+"   "
  213.                
  214.                 Next
  215.        
  216.                 ' add next month days (aft)
  217.                 For Local d:Int = 1 To 6 - cnt1
  218.                
  219.                         aft[0]:+FormatDay(d)
  220.                         cnt2:+1
  221.                
  222.                 Next
  223.  
  224.         EndIf
  225.        
  226.         ' fill additional aft rows
  227.         If o < 9 Then
  228.                
  229.                 ' next month
  230.                 mm2 = mm + 1
  231.                 If mm2 > 12 Then mm2 = 1
  232.                                
  233.                 For Local i:Int = 0 To 8 - o
  234.                        
  235.                         ' add next month days (aft)
  236.                         For Local d:Int = cnt2 + cnt3 + 1 To cnt2 + cnt3 + 7
  237.                        
  238.                                 aft[1 + i]:+FormatDay(d)
  239.                                 cnt3:+1
  240.                        
  241.                         Next
  242.                        
  243.                         ' prepare next row (if short month like Feb. 1993)
  244.                         cnt3 = cnt2 + 7
  245.                        
  246.                 Next
  247.  
  248.         EndIf
  249.  
  250. End Function
  251.  
  252. ' output formatted day
  253. Function FormatDay:String(d:Int)
  254.  
  255.         Local day:String = d + " "
  256.         If d < 10 Then day = " " + d + " "
  257.        
  258.         Return day
  259.  
  260. End Function
  261.  
  262. ' get day of week for a given date (0-6, 0=Monday)
  263. Function GetWeekDay:Int(y:Int, m:Int, d:Int)
  264.  
  265.         Local t:Int[] = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]
  266.  
  267.         If m < 3 Then y:-1
  268.        
  269.         Return ((y + y / 4 - y / 100 + y / 400 + t[m - 1] + d) - 1) Mod 7
  270.        
  271. End Function
  272.  
  273. ' fix leap years in months array
  274. Function FixLeapYear:Int(year:Int)
  275.  
  276.         'If (((year Mod 4 = 0) And (year Mod 100 <> 0)) Or (year Mod 400 = 0)) Then
  277.        
  278.         If ((year Mod 4) = 0 And (year Mod 100) <> 0) Or ((year Mod 4) = 0 And (year Mod 400) = 0) Then
  279.        
  280.        
  281.                 days[2] = 29
  282.        
  283.         Else
  284.                
  285.                 days[2] = 28
  286.                
  287.         EndIf
  288.        
  289. End Function
  290.  
  291. ' returns formatted time string
  292. Function FTimestamp:String(timestamp:Int, format:String = "%Y-%m-%d %H:%M:%S")
  293.  
  294.         Local time:Int Ptr, buff:Byte[256]
  295.        
  296.         time = VarPtr(timestamp)
  297.         strftime_(buff, 256, format, localtime_(time))
  298.        
  299.         Return String.FromCString(buff)
  300.        
  301. End Function
  302.  
  303. ' get current UNIX timestamp from OS
  304. Function GetTimeStamp:Int()
  305.  
  306.         Local time:Int[256]
  307.         time_(time)
  308.         return time[0]
  309.  
  310. End Function
  311.  
  312. ' returns the exact! unix timestamp for given YEARS,MONTHS,DAYS,HOURS,MINUTES,SECONDS (not used in this example)
  313. Function GetUnixTimestamp:Int(yy:Int, mm:Int, dd:Int, hh:Int, ii:Int, ss:Int)
  314.  
  315.         Local days:Int[] = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]
  316.         Local years:Int = yy - 1970
  317.         Local leap:Int = ((yy - 1) - 1968) / 4 - ((yy - 1) - 1900) / 100 + ((yy - 1) - 1600) / 400
  318.        
  319.         Local unixtime:Int = ss + 60 * ii + 60 * 60 * hh + (days[mm - 1] + dd - 1) * 60 * 60 * 24 + (years * 365 + leap) * 60 * 60 * 24
  320.  
  321.         If ((mm > 2) And (yy Mod 4 = 0 And (yy Mod 100 <> 0 Or yy Mod 400 = 0))) Then
  322.        
  323.         ' leap day
  324.                 unixtime:+(60 * 60 * 24)
  325.                
  326.         End If
  327.  
  328.   Return unixtime
  329.  
  330. End Function
Kind regards
Krischan

Windows 10 Pro | i7 9700K@ 3.6GHz | RTX 2080 8GB]
My Blitzbasic Archive | Extrasolar Project | My Github projects

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal