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.
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
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
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
If you need to calculates dates in different calendars, the reference is Nachum Dershowitz, Edward M. Reingold 'Calendrical Calculations' [1]. But beware of what you mean with 'historical' conversions: Gregorian calendar was adopted at different times in different countries...
I have a literate programming based implementation in Python (an original Lisp code of tge book side by side) at [2].
A Smaltalk implenentation is available at [3].
HTH Bye Enrico
[1] http://emr.cs.iit.edu/home/reingold/calendar-book/third-edition/index.html [2] http://code.google.com/p/pycalcal/ [3] http://www.squeaksource.com/Calendrica.html On Jun 26, 2012 7:07 PM, "H. Hirzel" hannes.hirzel@gmail.com wrote:
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
Hi Enrico,
The Chronology package in Squeak takes a simple point of view in that only one calender algorithm is in effect. Based on your experience with this topic, would you say that the algorithm that Bert has proposed is a good choice?
It seems to me that it is an improvement because it produces the expected results for a wide range of users, and it does not break any existing assumptions in the system.
Thanks Dave
On Tue, Jun 26, 2012 at 10:18:56PM +0200, Enrico Spinielli wrote:
If you need to calculates dates in different calendars, the reference is Nachum Dershowitz, Edward M. Reingold 'Calendrical Calculations' [1]. But beware of what you mean with 'historical' conversions: Gregorian calendar was adopted at different times in different countries...
I have a literate programming based implementation in Python (an original Lisp code of tge book side by side) at [2].
A Smaltalk implenentation is available at [3].
HTH Bye Enrico
[1] http://emr.cs.iit.edu/home/reingold/calendar-book/third-edition/index.html [2] http://code.google.com/p/pycalcal/ [3] http://www.squeaksource.com/Calendrica.html On Jun 26, 2012 7:07 PM, "H. Hirzel" hannes.hirzel@gmail.com wrote:
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
I personally think that the initial confusion comes from the fact that we name a GregorianDate as Date. Once that is made explicit there is no surprise in writing: GregorianDate julianDayNumber: 0 and obtain 24 November -4713 (GregorianDate) instead of 1 January -4712 (JulianDate)
In my little Calendrica project I made that distinction explicit but the implicit convention of understanding Date being GregorianDate is equally valid. It just needs a little bit more of text in the class comment.
HTH Ciao On Jun 26, 2012 10:39 PM, "David T. Lewis" lewis@mail.msen.com wrote:
Hi Enrico,
The Chronology package in Squeak takes a simple point of view in that only one calender algorithm is in effect. Based on your experience with this topic, would you say that the algorithm that Bert has proposed is a good choice?
It seems to me that it is an improvement because it produces the expected results for a wide range of users, and it does not break any existing assumptions in the system.
Thanks Dave
On Tue, Jun 26, 2012 at 10:18:56PM +0200, Enrico Spinielli wrote:
If you need to calculates dates in different calendars, the reference is Nachum Dershowitz, Edward M. Reingold 'Calendrical Calculations' [1]. But beware of what you mean with 'historical' conversions: Gregorian calendar was adopted at different times in different countries...
I have a literate programming based implementation in Python (an original Lisp code of tge book side by side) at [2].
A Smaltalk implenentation is available at [3].
HTH Bye Enrico
[1]
http://emr.cs.iit.edu/home/reingold/calendar-book/third-edition/index.html
[2] http://code.google.com/p/pycalcal/ [3] http://www.squeaksource.com/Calendrica.html On Jun 26, 2012 7:07 PM, "H. Hirzel" hannes.hirzel@gmail.com wrote:
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
squeak-dev@lists.squeakfoundation.org