Great that Squeak will be in the position to calculate historical dates properly, so no objection at all.
Thank you for your careful analysis and a synthesis of an algorithm which corrects the problem. I assume you description will be in a class comment...
Hannes
On 6/25/12, David T. Lewis lewis@mail.msen.com wrote:
On Mon, Jun 25, 2012 at 01:54:08PM +0200, Bert Freudenberg wrote:
Squeak dates are based on the Julian Day Number:
http://en.wikipedia.org/wiki/Julian_day
This is defined as the number of days since January 1, 4713 BC in the Julian proleptic calendar.
Now, to my surprise,
Date julianDayNumber: 0
answers
24 November -4713
instead of
1 January -4712
Digging into this it is because Squeak uses the Fliegel-Van Flandern algorithm, which always results in a Gregorian date. Even for dates before the Gregorian calendar was introduced. If we were to use the algorithm by Jean Meeus, dates before 15 Nov 1582 would be converted to a Julian date.
Meeus is a floating point algorithm which we may not want to use. I added a correction to our method similar to Meeus, but converted to integers. So this is a mixed one, pasted below.
Would anyone be opposed to adopt this? The behavior will be unchanged for all dates more recent than 15 Nov 1582.
I can't think of any reason why this should cause problems, aside from the need to make a couple of trivial updates to the unit tests. Perhaps Brent can comment, but it looks to me like a good thing to do.
Dave
If so, we also would need an adjustment for the reverse part in year:month:day:hour:minute:second:nanoSecond:offset:. This is already covered by a test using the year 1200 BC (DateAndTimeTest>>testFromString). Anybody up for making that work?
I stumbled upon this because Etoys 5 has a new Calendar object which exposes the Julian Day Number, and setting it to 0 is a very convenient way of explaining what that means.
Thanks!
- Bert -
dayMonthYearDo: aBlock "Evaluate the block with three arguments: day month, year. Uses the Fliegel-Van Flandern algorithm, with adjustment for dates before 15 Nov 1582 as given by Jean Meeus. See http://mathforum.org/library/drmath/view/51907.html"
| a l n i j dd mm yyyy | a := jdn. a < 2299161 ifTrue: [ | alpha | alpha := (jdn * 4 - 7468865) // 146097. a := jdn - 1 - alpha + (alpha // 4)]. l := a + 68569. n := 4 * l // 146097. l := l - (146097 * n + 3 // 4). i := 4000 * (l + 1) // 1461001. l := l - (1461 * i // 4) + 31. j := 80 * l // 2447. dd := l - (2447 * j // 80). l := j // 11. mm := j + 2 - (12 * l). yyyy := 100 * (n - 49) + i + l.
^ aBlock value: dd value: mm value: yyyy