Simplifying Date and Time classes

R. A. Harmon harmonra at webname.com
Thu May 25 12:14:51 UTC 2000


At 05:45 PM 5/23/00 +1200, Brent Pinkney wrote:
>I have attached a wee changeset which replaces the implementation of Date
>and Time.
>
>The Date class has been refactored to use the Julian Day Number
>representation internally. I recall the IBM Open Class L:ibrary for C++ did
>something similar. It makes manipulation of Dates a lot easier.
>
>I similarly refactored the Time class to store the time as the number of
>seconds elapses since midnight.
[snip]
>ANSI stuff:
>--------------
>I tried my changeset against My Harmon's ANSI SUnit tests and they failed
>miserably.

Thanks for testing against the ANSI stuff.


> The ANSI suite makes some assumptions about the Date class
>internals.

I changed RuleDate >> #basicUpdateForMonth:year: which directly accessed its
Date super class variables.

I also fixed bugs in the new Date >> #< (missing return) and #subtractDate:
(returned Date instead of Integer) methods.

The DateAndTime unit tests had a half dozen tests that didn't accommodate
daylight savings time well (ie DateAndTime >> #timeZoneName -> "Central
Standard Time" or "Central Daylight Time").  I'll figure out how I'll
address this after the Camp Smalltalk ANSI Tests are released.  I fixed them
to eliminate the warnings and marked them for further attention with "#todo".

I am not entirely sure about the proper use of DateAndTime >> #offset and
#offset:.

With these fixes the DateAndTime unit tests run without error.


>I believe that such a refactoring will make the implementation of the
>DatAndTime protocols easier.

I definitely think it can be improved.


I've attached a change set.

-------------- next part --------------
'From Squeak2.7 of 5 January 2000 [latest update: #1782] on 23 May 2000 at 2:41:54 pm'!

!Date methodsFor: 'arithmetic' stamp: 'RAH 5/23/2000 11:32'!
subtractDate: aDate 
	"Answer the number of days between the receiver and aDate."

	^self julianDayNumber - aDate asJulianDayNumber! !

!Date methodsFor: 'comparing' stamp: 'RAH 5/23/2000 11:04'!
< aDate 
	"Answer whether aDate precedes the date of the receiver." 

	^julianDayNumber < aDate asJulianDayNumber! !


!DateAndTimeANSITest methodsFor: 'testing' stamp: 'RAH 5/23/2000 14:31'!
testXequalityOp
	" <DateAndTime>#="
	| d19970426t8CST d19970426t7MST d19970426t7CST tmp1 tmp2 |
	'Date and Time' asSymbol.
	d19970426t8CST := DateAndTime
				year: 1997
				month: 4
				day: 26
				hour: 8
				minute: 0
				second: 0.
	"1997-04-26T08:00:00-06:00 CST"
	self
		value: [d19970426t8 = d19970426t8CST]
		should: [:r | r & (d19970426t8 hash = d19970426t8CST hash)]
		conformTo: #DateAndTime
		selector: #=.
	d19970426t8CST := DateAndTime
				year: 1997
				month: 4
				day: 26
				hour: 8
				minute: 0
				second: 0.
	"1997-04-26T08:00:00-06:00 CST"
	tmp1 := DateAndTime
				year: 1996
				month: 4
				day: 26
				hour: 5
				minute: 59
				second: 50
				offset: (Duration seconds: -10).
	tmp2 := DateAndTime
				year: 1996
				month: 4
				day: 26
				hour: 6
				minute: 0
				second: 10
				offset: (Duration seconds: 10).
	self
		value: [tmp1 = tmp2]
		should: [:r | r & (tmp1 hash = tmp2 hash)]
		conformTo: #DateAndTime
		selector: #=.
#todo."Falls within the daylight saving period, so need to figure out how to adjust."
	d19970426t7MST := DateAndTime
				year: 1997
				month: 4
				day: 26
				hour: 7
				minute: 0
				second: 0
				offset: (Duration
						days: 0
						hours: -7 + 1
						minutes: 0
						seconds: 0).
	"1997-04-26T07:00:00-07:00 MST"
	self
		value: [d19970426t8 = d19970426t7MST]
		should: [:r | r & (d19970426t8 hash = d19970426t7MST hash)]
		conformTo: #DateAndTime
		selector: #=.
	d19970426t7CST := DateAndTime
				year: 1996
				month: 4
				day: 27
				hour: 7
				minute: 0
				second: 0.
	"1997-04-26T07:00:00-07:00 MST"
	self
		value: [d19970426t8 = d19970426t7CST]
		shouldnt: [:r | r & (d19970426t8 hash = d19970426t7CST hash)]
		conformTo: #DateAndTime
		selector: #=! !

!DateAndTimeANSITest methodsFor: 'testing' stamp: 'RAH 5/23/2000 14:33'!
testXprintOnX
	" <Object>#printOn:"
	| aStream |
	'Date and Time' asSymbol.
	aStream := WriteStream on: (String new: 16).
	"CST"
#todo."Falls within the daylight saving period, so need to figure out how to adjust."
	self
		value: [d19970426t8 printOn: aStream]
		should: [:r | aStream contents = ' 1997-04-26T08:00:00-05:00']
		conformTo: #Object
		selector: #printOn:! !

!DateAndTimeANSITest methodsFor: 'testing' stamp: 'RAH 5/23/2000 14:37'!
testXtimeZoneAbbreviation
	" <DateAndTime>#timeZoneAbbreviation"
	| offTmp |
	'Date and Time' asSymbol.
	#testAnom.
	"???  
	offTmp := Duration days: 0 hours: -5 minutes: 0 seconds: 0.  
	  
	self value: [(d19970426t8 offset: offTmp) timeZoneAbbreviation]  
	should: [:r | r = 'EST']  
	conformTo: #'DateAndTime' selector: #'timeZoneAbbreviation'.  
	???"
	offTmp := Duration
				days: 0
				hours: -6
				minutes: 0
				seconds: 0.
#todo."Falls within the daylight saving period, so need to figure out how to adjust."
	self
		value: [(d19970426t8 offset: offTmp) timeZoneAbbreviation]
		should: [:r | r = 'CDT']
		conformTo: #DateAndTime
		selector: #timeZoneAbbreviation! !

!DateAndTimeANSITest methodsFor: 'testing' stamp: 'RAH 5/23/2000 14:38'!
testXtimeZoneName
	" <DateAndTime>#timeZoneName"
	| offTmp |
	'Date and Time' asSymbol.
	#testAnom.
	"???  
	offTmp := Duration days: 0 hours: -5 minutes: 0 seconds: 0.  
	self value: [(d19970426t8 offset: offTmp) timeZoneName]  
	should: [:r | r = 'EST']  
	conformTo: #'DateAndTime' selector: #'timeZoneName'.  
	???"
	offTmp := Duration
				days: 0
				hours: -6
				minutes: 0
				seconds: 0.
#todo."Falls within the daylight saving period, so need to figure out how to adjust."
	self
		value: [(d19970426t8 offset: offTmp) timeZoneName]
		should: [:r | r = 'Central Daylight Time']
		conformTo: #DateAndTime
		selector: #timeZoneName! !


!RuleDate methodsFor: 'private' stamp: 'RAH 5/23/2000 10:57'!
basicUpdateForMonth: mm year: yyyy 
	"Private - Answer the receiver after updating by applying the rule for 
	the month, mm, of year, yyyy."
	| dayByRule daysNamedInMonth firstDayNamed |
	firstDayNamed := self
				dayInMonth: mm
				year: yyyy
				ofFirstDayNamed: dayOfWeek.
	julianDayNumber := (Date
				newDay: firstDayNamed
				month: mm
				year: yyyy) julianDayNumber.
	daysNamedInMonth := (firstDayNamed to: (Date daysInMonth: mm forYear: yyyy) by: 7) asArray.
	dayByRule := self applyRuleTo: daysNamedInMonth.
	julianDayNumber := (Date
				newDay: dayByRule
				month: mm
				year: yyyy) julianDayNumber! !
-------------- next part --------------
--
Richard A. Harmon          "The only good zombie is a dead zombie"
harmonra at webname.com           E. G. McCarthy
Spencer, Iowa


More information about the Squeak-dev mailing list