## The function round(n*x)

## The function round(n*x)

(OP)

I'm not sure this merits a separate thread, but I would like to record my thoughts on the subject while they're still fresh in my mind.

Recall from Chris Miller's calendar thread that there are five different ranges of x which correspond to 11 month, 337 day calendars that differ only in the placement of the 30 day months. They are

30 13/22 <= x < 30 11/18 generates our actual calendar from March to January.

30 11/18 <= x < 30 5/8 generates a calendar with 30 days in April, June, September and December.

30 5/8 <= x < 30 9/14 generates a calendar with 30 days in April, July, September and December.

30 9/14 <= x < 30 13/20 generates a calendar with 30 days in April, July, October and December.

30 13/20 <= x < 30 15/22 generates a calendar with 30 days in April, July, October and January.

Furthermore, the transition points between these different calendars is always an exact fraction determined by when a 30 day month starts getting rounded up to 31 days. If the 30 day month is in position n on the calendar, then the fractional part of the transition point has denominator 2*n.

Recall from Chris Miller's calendar thread that there are five different ranges of x which correspond to 11 month, 337 day calendars that differ only in the placement of the 30 day months. They are

30 13/22 <= x < 30 11/18 generates our actual calendar from March to January.

30 11/18 <= x < 30 5/8 generates a calendar with 30 days in April, June, September and December.

30 5/8 <= x < 30 9/14 generates a calendar with 30 days in April, July, September and December.

30 9/14 <= x < 30 13/20 generates a calendar with 30 days in April, July, October and December.

30 13/20 <= x < 30 15/22 generates a calendar with 30 days in April, July, October and January.

Furthermore, the transition points between these different calendars is always an exact fraction determined by when a 30 day month starts getting rounded up to 31 days. If the 30 day month is in position n on the calendar, then the fractional part of the transition point has denominator 2*n.

## RE: The function round(n*x)

Restricted to the range 13/22 <= x <= 15/22, the Farey sequence of order 22 is

13/22, 3/5, 11/18, 8/13, 13/21, 5/8, 12/19, 7/11, 9/14, 11/17, 13/20, 2/3, 15/22

## RE: The function round(n*x)

I didn't know about the Farey sequence, now I even know how it can be related to our calendar.

I realize I knew Farey already, from Farey addition, which I know as Freshman addition.

Chriss

## RE: The function round(n*x)

In any case, we can see by inspection that the terms of the Farey sequence with even denominators form the boundary conditions for generating the five distinct calendars possible with round().

What about the other terms? 3/5, 7/11 and 2/3 also mark transitions - the whole number values where a month goes from rounding up to rounding down. Naturally, because of the way round() works, there are no changes to the calendar at these transitions.

## RE: The function round(n*x)

The terms of the Farey sequence of order 11 in the range 30 7/11 <= x < 30 8/11 are

7/11, 2/3, 7/10, 5/7, 8/11

Using int(n*x) to generate calendars, I got the following:

30 7/11 <= x < 30 2/3 generates a calendar with 30 days in March, May, August and November.

30 2/3 <= x < 30 7/10 generates a calendar with 30 days in March, June, September and December.

30 7/10 <= x < 30 5/7 generates a calendar with 30 days in March, June, September and January.

30 5/7 <= x < 30 8/11 generates a calendar with 30 days in March, June, October and January.

## RE: The function round(n*x)

The terms of the Farey sequence of order 11 in the range 30 6/11 < x <= 30 7/11 are

6/11, 5/9, 4/7, 3/5, 5/8, 7/11

Using ceiling(n*x) to generate calendars, I got the following:

30 6/11 < x <= 30 5/9 generates a calendar with 30 days in May, July, September and November.

30 5/9 < x <= 30 4/7 generates a calendar with 30 days in May, July, September and December.

30 4/7 < x <= 30 3/5 generates a calendar with 30 days in May, July, October and December.

30 3/5 < x <= 30 5/8 generates a calendar with 30 days in May, August, October and January.

30 5/8 < x <= 30 7/11 generates a calendar with 30 days in May, August, November and January.

## RE: The function round(n*x)

From the month names it's clear February actually was the last month of the year once, especially September-December point it out.

The paragraph "When was the first leap year" in https://www.rmg.co.uk/stories/topics/which-years-a... mentions the Egytians used twelve 30-day months and added 5 extra days to the end.

The modern leap year definition goes back to 1752 and I know not all countries introduced the Gregorian calendar in the same year.

The 455 day long year of confusion mentioned, was the year before the Julian calendar was introduced on January 1sr 45 BC (of course there never were BC years at their time, 753 BC was the founding of rome. and so the introduction was 1st January 709 AUC. It didn't have the leap year every 400 years, but that was its only difference from ours.

I wonder if the Julian calendar that also was changing the first month of the calendar, maybe the 455 days point to that shift of momths? 455 days would be about 15 months. But when the calender previous to the Julian calendar had Maarch as first month, this would shift the begin of the year from March to June, not to January. I think you have to dig deeper into calendar history to find out.

You rarely will find a PC calendar correctly going from Gregorian to Julian calendar prior to the year of adaption, which differs from country to country, they all extrapolate the calendar back. Using the signed int or signed long int with the middle at midnigth 1st Jan 1970 you get invalid dates for 1752 and before and surely for 45 BC.

Chriss

## RE: The function round(n*x)

I don't know how authoritative the Wikipedia article on the Roman calendar is, but it addresses most of the issues you bring up: https://en.wikipedia.org/wiki/Roman_calendar

In brief, the calendar that preceded the Julian calendar alternated between years that were much shorter than 365 days and years that were much longer. Wikipedia says that the intent was to create a 24 year cycle of thirteen 355 day years, seven 377 day years and four 378 day years, with an average length of 365.25 days per year over the entire 24 year cycle. The so-called "year of confusion" in 46 B.C. wasn't really confusing at all by the standards of the time - it was just an unusually large adjustment. Switching the beginning of the year to January was an earlier change that had nothing to do with the adoption of the Julian calendar.

The Julian calendar very wisely preserved the average length of the year at 365.25 days by distributing 10 extra days to the short 355 day year and giving February an extra day every four years. So we have the creators of the Julian calendar to thank for our current "30 days hath September..." pattern of 30 and 31 day months. The calculations I made earlier in this thread show that they made very good choices in distributing the 30 day months in a balanced manner - not the only way to balance things, but there's no clearly superior method.

You are right that a lot of commercial software products do a very poor job with date calculations. I personally became aware of a really ugly bug in Oracle when I used it to do some research on the Mayan calendar. See thread1177-1346513: Mayan calendar and Oracle date bug

## RE: The function round(n*x)

I also think you would need better historical reference about calendar reforms to proof. At least Google doesn't present any random blog or homepage about the topics. The britannica says January replaced Marchas first month, indeed. https://www.britannica.com/story/why-does-the-new-... ends in stating there is evidence it was not offical until 153 BCE. But without referring to the evidence.

Chriss

## RE: The function round(n*x)

(11*10*9*8)/(1*2*3*4) = 330

ways to distribute four 30 day months in an 11 month calendar and only 14/330 or about 4.2% of them can be generated in a plausible way through multiples of step functions.

I no longer feel, however, that our current calendar being one of the 14 is a "remarkable" coincidence. If anything, I would now call it more likely than not. All of these 14 calendars balance the occurrences of the 30 day months, so that there are never too many 31 day months before a 30 day month follows. This sort of balance is clearly something the inventors of the Julian calendar would have tried to achieve.

If I may make an editorial comment, if I had been Julius Caesar and had to choose among these 14 options, the only choice I would seriously consider over the one that was actually adopted is the one generated by ceiling() which has 30 day months in May, July, September and November. It is the only option which doesn't contain any three month sequence of less than 90 days. This improves on our current calendar in which February, March and April usually have only 89 days.

## RE: The function round(n*x)

Note: My calculations for 11 month calendars all began with March as the first month. For the 12 month calendars I began with January.

Using round(n*x) on a 12 month 367 day calendar, I got the following.

30 13/24 <= x < 30 11/20 generates a calendar with 30 days in February, April, June, August and October.

30 11/20 <= x < 30 9/16 generates a calendar with 30 days in February, April, June, August and November.

30 9/16 <= x < 30 7/12 generates a calendar with 30 days in February, April, June, September and November.

30 7/12 <= x < 30 13/22 generates a calendar with 30 days in February, April, July, September and November.

30 13/22 <= x < 30 11/18 generates a calendar with 30 days in February, April, July, September and December.

30 11/18 <= x < 30 5/8 generates a calendar with 30 days in February, April, July, October and December.

Our current calendar can be obtained from the 30 9/16 <= x < 30 7/12 entry by subtracting two days (one day in a leap year) from February.

## RE: The function round(n*x)

round (n * 30 9/16) - 2 * int((n+10)/12)

produces a 28 day February while leaving the length of the other months unchanged.

## RE: The function round(n*x)

My calculations indicate that this can be done. One expression that works is

round ((n * 30 9/16) - 2 * int((n+10)/12) + 1/4 * int(n/12) + int((n+10)/48) - int((n+10)/1200) + int((n+10)/4800))

This expression is unfortunately nowhere near as elegant as round(n*x), but each additional term has, I believe, a clear purpose which makes it easy to understand:

-2 * int((n+10)/12) produces a 28 day February.

1/4 * int(n/12) is a numerical adjustment so that the math produces regular years of exactly 365 days and leap years of exactly 366 days.

int((n+10)/48) produces a leap year every four years.

-int((n+10)/1200) takes away the leap year every hundred years.

int((n+10)/4800) adds back the leap year every 400 years.

## RE: The function round(n*x)

On the other side, it's fine to have a simple formula for a full year, it'll be able to check a date for being valid, but the universal thing about converting a date to a number is to be able to calculate differences, you can also check a date if you have the reverse calculation and then get back to the same date. Say someone enters 29th of February 2022, which doesn't exist, you compute a day number and then reverse it to the date 1st March 2022 and see the date is wrong.

Chriss

## RE: The function round(n*x)

round ((n * 30 9/16) + 1/4 * int(n/12))

- 2 * int((n+10)/12) + int((n+10)/48) - int((n+10)/1200) + int((n+10)/4800)

## RE: The function round(n*x)

https://en.wikipedia.org/wiki/Darian_calendar

Unsurprisingly, this layout can be generated with step functions, specifically ceiling(n*x) in the range

27 19/23 < x <= 27 5/6

## RE: The function round(n*x)

But I found another reason for the month lengths that also explains the factor 30.6: Starting in March up to September, a 5 months period (like March to July, April to August,..., and September to January), sums to 153 days, which is exactly 5*30.6.

In October that's broken, because 5 months starting with October include February. Or said the other way around: (Almost) every period of 5 months including February doesn't sum to 153. Periods containing a leap year February total to 152,152,153,152, and 152 (there you have the exception). Periods including a normal February are, of course, one day shorter.

It seems a bit oddly balanced, since it better fits into leap years than into normal years. I also found calculations using 30.6001, which addresses floating point imprecisions. Maybe with single precision floats. I also get the right sequence with a factor 30.59375 using doubles, which is even lower than 30.6 - to state the obvious.

I thought I mention the 153 day fact for you contemplating about a another reason the simple step function succeeds covering the lengths of 11 months. Pardon me if you already observed that and I overlooked it. I think somewhere here or there you mentioned the product is exact. It's now easy to spot, both 153 and 306 are in the number series.

Chriss

## RE: The function round(n*x)

## RE: The function round(n*x)

So the natural thing to do is look at the other whole number transitions - 7/11 and 2/3. 7/11 doesn't work, but 2/3 does. Round(n*(30 2/3)) generates an 11 month calendar with 30 day months in April, July, October and January. Every three months sequence (except the ones including February) using this calendar contains exactly 92 days. Very interesting, but the creators of the Julian calendar apparently didn't prioritize having the maximum number of 92 day, three month stretches.

## RE: The function round(n*x)

I faintly remember some economists once proposed the fluctuation of month lengths are a problem and a calendar reform could optimize that. The idea of a 13 month calender with 4 week months each, plus some extra days, would still keep the concept of quarters as they would simple be three 4 week months and a week, in short 13 weeks quarters. Quite easy to see because a quarter of each month would be 1 week, so a quarter of a 13 month year with this (almost) constant month length is 13 weeks.

The other idea behind this is that you will hardly be able to break the 7 day week cycle, but straightening the month length could be a real benefit.

My major intention rather is a more complete calendar implementation, including more calendars in use around the world. https://www.worldatlas.com/articles/calendars-used...

Simply the fact new Date(year, month, day) in JS works with a 0 based month index 0-11 instead of the usual 1-12 bugs me. I'm not against 0 based counting, but then why only the month and not the days? And who named the method returning the day datepart as getDate(). I understand that's because getDay() is reserved to return a week day number 0-6 for Sunday to Saturday.

I think it's no wonder many JS libraries about the topic of calendars exist.

Chriss