Where’s February 29th? or Does Xojo.Core.Date have problems with leap years?

I have to design a calendar window that displays dates for each days of a month much like iCal.
So I built a canvas subclass that takes a xojo.core.date as parameter and then calculates a few things to determine the sizes:

[code] dim startdate as new xojo.core.date(CurrentDate.Year, CurrentDate.Month, 1, xojo.core.timezone.Current) // 1st of the month
dim d1 as integer = startdate.germandayofmonth // day of month rotated one left – we start the weeks here with Monday. Need this later.
dim enddate as xojo.core.date = startdate + new xojo.Core.DateInterval(0, 1) // First of the next month
enddate = enddate - new xojo.Core.DateInterval(0, 0, 1) // and one day back to get the last day of the current month.
dim d2 as integer = enddate.germandayofmonth

dim dif as xojo.Core.DateInterval = enddate - startdate
dim weeks as integer = dif.Days/7 // how many weeks did we have in the month?
dim rest as integer = dif.days mod 7 // and is there a rest?
if rest > 0 then weeks = weeks + 1 // if so, we need to draw one more week line.[/code]

This all works nicely, except for this month. We have a leap year, so I expected enddate would be 2-29-2016. It’s not. Xojo tells me we have no leap year and jumps to the 28th.
Is there any way I can fix this? Thanks a lot!

Have you tried subtracting 86400 seconds instead, or even 24 hrs?

Can you show us what the GermanDayOfMonth function looks like?

For what it’s worth, when I take out your GermanDayOfMonth method, EndDate ends up being Feb 29th. I’m guessing that it’s screwing with the actual day.

That’s weird! But thanks, Greg! I’ll figure out something else then.
The method, anyway, does not change the date. It’s a very clumsy “calculation”:

Function GermanDayOfMonth(extends d as xojo.core.date) As Integer dim result as integer = d.DayOfWeek - 1 if result = 0 then result = 7 return result End Function

[quote=245698:@Ulrich Bogun]That’s weird! But thanks, Greg! I’ll figure out something else then.
The method, anyway, does not change the date. It’s a very clumsy “calculation”:

Function GermanDayOfMonth(extends d as xojo.core.date) As Integer dim result as integer = d.DayOfWeek - 1 if result = 0 then result = 7 return result End Function[/quote]

It seems like you should keep your actual data in the proper Xojo.Core.Date and leave adjusting by the day of the week to your app’s user interface layer?

Well it turned out Dateinterval wasn’t such a good idea. It is too smart - when I want to add another day to get the number of days in that month it tells me the interval is 0 days and 1 month :wink:
Instead, I just calculate enddate.day - startdate.day + 1 now. Still don’t know why the extension method messed up the calculation, but I see a February with 29 days now. Thanks a lot, both of you!

Hehe, had myself confused in the numberofDays. Seems to run fine now, but I found a discrepancy between OS X and Linux framework (64 bit, the latter one). See the screenshot of the same project on both platforms, with a draw event

[code]Sub Paint(g As Graphics, areas() As REALbasic.Rect)
dim daywidth as double = me.Width / 7
g.ClearRect 0,0,me.Width, me.Height
g.ForeColor = color.lightgray
g.DrawLine 0,me.headsection,me.Width, me.headsection
system.debuglog HeadSection.ToText
g.TextSize = 28
g.DrawString MonthName+" "+YearText, 10, 32
for q as integer = 1 to 6
g.DrawLine qdaywidth, HeadSection, qdaywidth, me.Height
next
dim startdate as new xojo.core.date(CurrentDate.Year, CurrentDate.Month, 1, xojo.core.timezone.Current)

dim days as integer =CurrentDate.daysinMonth
dim weeks as integer = Days/7
dim rest as integer = days mod 7
dim startday as integer = startdate.germandayofweek
if rest > 0 then weeks = weeks + 1
if startday - 1 + rest > 7 then weeks = weeks + 1
dim dayheigth as double = (me.Height - HeadSection)/weeks
for q as integer = 1 to weeks -1
g.DrawLine 0, HeadSection+qdayheigth, me.Width, HeadSection+qdayheigth
next
for q as integer = 1 to weeks
for p as integer = 1 to 7
dim curday as new xojo.core.date (currentdate.year, CurrentDate.month, (q-1) * 7 + (p-startdate.germandayofweek+1), xojo.core.timezone.current)
ShowDay (g, curday, (p-1) * daywidth, HeadSection+ ((q-1)dayheigth), daywidth, dayheigth, currentdate)
next
next
for q as integer = 1 to 6
g.ForeColor = color.lightgray
g.DrawLine q
daywidth, HeadSection, qdaywidth, me.Height
g.ForeColor = color.white
g.DrawLine q
daywidth-1, HeadSection, q*daywidth-1, me.Height
next
End Sub[/code]

where DaysInMonth is this unelegant, but working method:

[code]Function DaysInMonth(extends d as xojo.Core.Date) As Integer
// Trouble with Xojo.core.dateinterval not replying correctly when GermanDayOfWeek is used, therefore:

dim firstday as new xojo.core.date(d.Year, d.Month, 1, 0,0,0, xojo.core.TimeZone.Current)
for q as integer = 31 downto 28
dim lastday as new xojo.core.date (firstday.year, firstday.Month, q, 0,0,0, xojo.core.timezone.current)
if lastday.Month = firstday.month then return q
next
End Function[/code]

(I can of course compare to d.month only, firstday isn’t necessary).

This results in negative Days on Linux:

I am sure I can work around that, but I suspect the framework should give the same results on all platforms, or can’t it?

It should.

Thanks, Joe. <https://xojo.com/issue/42457>

Also wrong on Windows. :frowning: