[squeak-dev] The Inbox: Kernel-bf.700.mcz

commits at source.squeak.org commits at source.squeak.org
Thu Jun 28 17:35:52 UTC 2012


Bert Freudenberg uploaded a new version of Kernel to project The Inbox:
http://source.squeak.org/inbox/Kernel-bf.700.mcz

==================== Summary ====================

Name: Kernel-bf.700
Author: bf
Time: 28 June 2012, 7:34:28.085 pm
UUID: 019680d3-785f-43a5-bc2a-9fed7bade3bb
Ancestors: Kernel-fbs.699

Make DateAndTime use the Julian Calendar for dates earlier than 15 October 1582.

=============== Diff against Kernel-fbs.699 ===============

Item was changed:
  Magnitude subclass: #DateAndTime
  	instanceVariableNames: 'seconds offset jdn nanos'
  	classVariableNames: 'ClockProvider DaysSinceEpoch LastMilliSeconds LastTick LastTickSemaphore LocalTimeZone MilliSecondOffset OffsetsAreValid'
  	poolDictionaries: 'ChronologyConstants'
  	category: 'Kernel-Chronology'!
  
+ !DateAndTime commentStamp: 'bf 6/28/2012 19:09' prior: 0!
- !DateAndTime commentStamp: 'brp 5/13/2003 08:07' prior: 0!
  I represent a point in UTC time as defined by ISO 8601. I have zero duration.
  
+ In contrast to ISO 8601, which uses the Gregorian Proleptic Calendar exclusively, I use the Julian Proleptic Calendar for dates prior to 15 Oct 1582. However, for seriously dealing with multiple calendars, you should use a more thorough date package (e.g. Calendrica).
  
+ My implementation uses three SmallIntegers and a Duration:
- My implementation uses three SmallIntegers
-  and a Duration:
  jdn		- julian day number.
  seconds	- number of seconds since midnight.
  nanos	- the number of nanoseconds since the second.
- 
  offset	- duration from UTC.
  
  The nanosecond attribute is almost always zero but it defined for full ISO compliance and is suitable for timestamping.
  !

Item was added:
+ ----- Method: DateAndTime class>>gregorianYear:month:day:hour:minute:second:nanoSecond:offset: (in category 'squeak protocol') -----
+ gregorianYear: year month: month day: day hour: hour minute: minute second: second nanoSecond: nanoCount offset: offset
+ 	"Return a DateAndTime"
+ 
+ 	| daysInMonth p q r s julianDayNumber |
+ 	daysInMonth := Month
+ 		daysInMonth: month
+ 		forYear: year.
+ 	day < 1 ifTrue: [self error: 'day may not be zero or negative'].
+ 	day > daysInMonth ifTrue: [self error: 'day is after month ends']. 	
+ 	
+ 	p := (month - 14) quo: 12.
+ 	q := year + 4800 + p.
+ 	r := month - 2 - (12 * p).
+ 	s := (year + 4900 + p) quo: 100.
+ 
+ 	julianDayNumber :=
+  		( (1461 * q) quo: 4 ) +
+ 			( (367 * r) quo: 12 ) -
+  				( (3 * s) quo: 4 ) +
+  					( day - 32075 ).
+ 
+ 	^self basicNew
+ 		setJdn: julianDayNumber 
+ 		seconds: hour * 60 + minute * 60 + second
+ 		nano: nanoCount
+ 		offset: offset;
+ 		yourself!

Item was added:
+ ----- Method: DateAndTime class>>julianYear:month:day:hour:minute:second:nanoSecond:offset: (in category 'squeak protocol') -----
+ julianYear: year month: month day: day hour: hour minute: minute second: second nanoSecond: nanoCount offset: offset
+ 	"Return a DateAndTime"
+ 
+ 	| days |
+ 	days :=
+ 		(365 * (year - 1)) +					"years since epoch"
+ 		((year - 1) // 4) +					"leap days since epoch"
+ 		(((367 * month) - 362) // 12) +		"30/31 day months since newyear"
+ 		day.
+ 	month > 2 ifTrue: [ "we counted this February as 30 days; correct to 29 or 28"
+ 		days := days - ((Year isJulianLeapYear: year) ifTrue: [1] ifFalse: [2])].
+ 	^self basicNew
+ 		setJdn:  1721423 + days
+ 		seconds: hour * 60 + minute * 60 + second
+ 		nano: nanoCount
+ 		offset: offset;
+ 		yourself!

Item was changed:
  ----- Method: DateAndTime class>>year:month:day:hour:minute:second:nanoSecond:offset: (in category 'squeak protocol') -----
  year: year month: month day: day hour: hour minute: minute second: second nanoSecond: nanoCount offset: offset
+ 	"Return a DateAndTime. If date is after 15 Oct 1582, use Gregorian calendar, otherwise the Julian calendar"
- 	"Return a DateAndTime"
  
+ 	| monthIndex |
- 	| monthIndex daysInMonth p q r s julianDayNumber |
- 
  	monthIndex := month isInteger ifTrue: [month] ifFalse: [Month indexOfMonth: month].
+ 	^(year > 1582 or: [year = 1582 and: [monthIndex > 10 or: [monthIndex = 10 and: [day >= 15]]]])
+ 		ifTrue: [self gregorianYear: year month: monthIndex day: day hour: hour minute: minute second: second nanoSecond: nanoCount offset: offset]
+ 		ifFalse: [self julianYear: year month: monthIndex day: day hour: hour minute: minute second: second nanoSecond: nanoCount offset: offset]
+ !
- 	daysInMonth := Month
- 		daysInMonth: monthIndex
- 		forYear: year.
- 	day < 1 ifTrue: [self error: 'day may not be zero or negative'].
- 	day > daysInMonth ifTrue: [self error: 'day is after month ends']. 	
- 	
- 	p := (monthIndex - 14) quo: 12.
- 	q := year + 4800 + p.
- 	r := monthIndex - 2 - (12 * p).
- 	s := (year + 4900 + p) quo: 100.
- 
- 	julianDayNumber :=
-  		( (1461 * q) quo: 4 ) +
- 			( (367 * r) quo: 12 ) -
-  				( (3 * s) quo: 4 ) +
-  					( day - 32075 ).
- 
- 	^self basicNew
- 		setJdn: julianDayNumber 
- 		seconds: hour * 60 + minute * 60 + second
- 		nano: nanoCount
- 		offset: offset;
- 		yourself!

Item was changed:
  ----- Method: DateAndTime>>dayMonthYearDo: (in category 'squeak protocol') -----
  dayMonthYearDo: aBlock
+ 	"Evaluate the block with three arguments: day, month, year.
+ 	For dates since 15 Oct 1582 use Gregorian calendar, before that, the Julian calendar"
- 	"Evaluation the block with three arguments: day month, year."
  
+ 	^jdn < 2299161
+ 		ifTrue: [self julianDayMonthYearDo: aBlock]
+ 		ifFalse: [self gregorianDayMonthYearDo: aBlock]!
- 	| l n i j dd mm yyyy |
- 	l := jdn + 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!

Item was added:
+ ----- Method: DateAndTime>>gregorianDayMonthYearDo: (in category 'squeak protocol') -----
+ gregorianDayMonthYearDo: aBlock
+ 	"Evaluate the block with three arguments: day, month, year."
+ 
+ 	| l n i j dd mm yyyy |
+ 	l := jdn + 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!

Item was added:
+ ----- Method: DateAndTime>>julianDayMonthYearDo: (in category 'squeak protocol') -----
+ julianDayMonthYearDo: aBlock
+ 	"Evaluate the block with three arguments: day, month, year"
+ 
+ 	| totalDays day month year daysSinceNewYear fakeDaysSinceNewYear daysToFirstOfMonth fakeDaysToFirstOfMonth fakeAmount |
+ 	totalDays := jdn - 1721424.	"days since epoch 1 January 1"
+ 	year := (4 * totalDays + 1464) // 1461.
+ 	daysSinceNewYear := totalDays
+ 		- (365 * (year - 1))			"years since epoch"
+ 		- ((year - 1) // 4)	.			"leap days since epoch"
+ 	"after Feb 28, make Feb look like it was a 30-day month"
+ 	fakeAmount := daysSinceNewYear <= 58
+ 		ifTrue: [0]
+ 		ifFalse: [(Year isJulianLeapYear: year) ifTrue: [1] ifFalse: [2]].
+ 	fakeDaysSinceNewYear := daysSinceNewYear + fakeAmount.
+ 	"month formulas assume 30/31 day months"
+ 	month := ((12 * fakeDaysSinceNewYear) + 373) // 367.
+ 	fakeDaysToFirstOfMonth := ((367 * month) - 362) // 12.
+ 	daysToFirstOfMonth := month > 2
+ 		ifTrue: [fakeDaysToFirstOfMonth - fakeAmount]
+ 		ifFalse: [fakeDaysToFirstOfMonth].
+ 	day := daysSinceNewYear - daysToFirstOfMonth + 1.
+ 	^ aBlock
+ 		value: day
+ 		value: month
+ 		value: year!

Item was changed:
  ----- Method: Year class>>daysInYear: (in category 'smalltalk-80') -----
  daysInYear: yearInteger
  
+ 	^ 365 + (self leapYear: yearInteger)
- 	^ 365 + ((self isLeapYear: yearInteger) ifTrue: [1] ifFalse: [0]).
  !

Item was added:
+ ----- Method: Year class>>isGregorianLeapYear: (in category 'squeak protocol') -----
+ isGregorianLeapYear: aYearInteger
+ 	| adjustedYear |
+ 	adjustedYear := aYearInteger > 0
+ 		ifTrue: [aYearInteger]
+ 		ifFalse: [(aYearInteger + 1) negated].
+ 	"There was no year 0"
+ 	^ ((adjustedYear \\ 4 ~= 0) or: [(adjustedYear \\ 100 = 0) and: [adjustedYear \\ 400 ~= 0]]) not!

Item was added:
+ ----- Method: Year class>>isJulianLeapYear: (in category 'squeak protocol') -----
+ isJulianLeapYear: aYearInteger
+ 	^ aYearInteger \\ 4 = 0!

Item was changed:
  ----- Method: Year class>>isLeapYear: (in category 'squeak protocol') -----
  isLeapYear: aYearInteger
  
+ 	^ aYearInteger >= 1582
+ 		ifTrue: [self isGregorianLeapYear: aYearInteger]
+ 		ifFalse: [self isJulianLeapYear: aYearInteger]
+ !
- 
- 	| adjustedYear |
- 	adjustedYear := aYearInteger > 0
- 		ifTrue: [aYearInteger]
- 		ifFalse: [(aYearInteger + 1) negated].
- 
- 	"There was no year 0"
- 	^ ((adjustedYear \\ 4 ~= 0) or: [(adjustedYear \\ 100 = 0) and: [adjustedYear \\ 400 ~= 0]]) not!



More information about the Squeak-dev mailing list