"
COPYRIGHT (c) 1989 by Claus Gittinger
All Rights Reserved
This software is furnished under a license and may be used
only in accordance with the terms of that license and with the
inclusion of the above copyright notice. This software may not
be provided or otherwise made available to, or used by, any
other person. No title to or ownership of the software is
hereby transferred.
"
Magnitude subclass:#Date
instanceVariableNames:'dateEncoding'
classVariableNames:'DayNames MonthNames DayAbbrevs MonthAbbrevs
EnvironmentChange'
poolDictionaries:''
category:'Magnitude-General'
!
Date comment:'
COPYRIGHT (c) 1989 by Claus Gittinger
All Rights Reserved
$Header: /cvs/stx/stx/libbasic/Date.st,v 1.18 1995-04-11 14:49:00 claus Exp $
'!
!Date class methodsFor:'documentation'!
copyright
"
COPYRIGHT (c) 1989 by Claus Gittinger
All Rights Reserved
This software is furnished under a license and may be used
only in accordance with the terms of that license and with the
inclusion of the above copyright notice. This software may not
be provided or otherwise made available to, or used by, any
other person. No title to or ownership of the software is
hereby transferred.
"
!
version
"
$Header: /cvs/stx/stx/libbasic/Date.st,v 1.18 1995-04-11 14:49:00 claus Exp $
"
!
documentation
"
Instances of Date represent dates as year, month and day encoded in the
(private & hidden) instance dateEncoding. The value found there is
year*100*100 + month*100 + day (which makes magnitude-like comparison of
dates easy, but is not guaranteed for future versions).
The old representation used days since 1st Jan. 1901 internally -
with the new implementation, it is possible to reasonably represent almost
any Date. (which insurance companies will like, since they can now
represent even very old peoples birthday :-)
Notice: no correction for pre-Julian dates is done.
The printed representation of dates is controlled by resource definitions -
thus national variants are already supported (see file 'resources/Date.rs').
Compatibility notice:
due to some historic reasons, there are some methods found twice
with different names in this class. The old ST/X methods will vanish in
one of the next releases, and kept for a while to support existing
applications (the info on how these methods should be named came
somewhat late from the testers ..).
Please do not use methods marked as obsolete in their comment.
Most useful methods:
Date today
(Date today) addDays:
(Date today) subtractDays:
"
! !
!Date class methodsFor:'private'!
initNames
"read the language specific names"
|resources|
DayNames := #('monday'
'tuesday'
'wednesday'
'thursday'
'friday'
'saturday'
'sunday').
DayAbbrevs := #('mon'
'tue'
'wed'
'thu'
'fri'
'sat'
'sun').
MonthNames := #('january'
'february'
'march'
'april'
'may'
'june'
'july'
'august'
'september'
'october'
'november'
'december').
MonthAbbrevs := #('jan'
'feb'
'mar'
'apr'
'may'
'jun'
'jul'
'aug'
'sep'
'oct'
'nov'
'dec').
"check for case where Resource-classes are absent"
ResourcePack notNil ifTrue:[
resources := ResourcePack for:self.
DayNames := resources array:DayNames.
DayAbbrevs := resources array:DayAbbrevs.
MonthNames := resources array:MonthNames.
MonthAbbrevs := resources array:MonthAbbrevs.
].
EnvironmentChange := false
"Date initNames"
!
daysInMonthIndex: monthIndex forYear: yearInteger
"return the number of days in month monthIndex of
year yearInteger (modified GNU).
Return 0 for invalid month index.
This is the internal version of daysInMonth:forYear:"
|days|
(monthIndex between:1 and:12) ifFalse:[^ 0].
days := #(31 28 31 "Jan Feb Mar"
30 31 30 "Apr May Jun"
31 31 30 "Jul Aug Sep"
31 30 31 "Oct Nov Dec"
) at: monthIndex.
(monthIndex == 2) ifTrue:[
(self leapYear:yearInteger) ifTrue:[
^ days + 1
]
].
^ days
"
Date daysInMonthIndex:2 forYear:1994
Date daysInMonthIndex:2 forYear:1980
Date daysInMonthIndex:2 forYear:1981
"
! !
!Date class methodsFor:'handling language changes'!
initialize
"/ super initialize.
"check for case where Resource-classes are absent"
ResourcePack isNil ifTrue:[
self initNames
] ifFalse:[
Smalltalk addDependent:self.
EnvironmentChange := true
]
!
update:something
((something == #Language) or:[something == #LanguageTerritory]) ifTrue:[
"just remember change for next access"
EnvironmentChange := true
]
! !
!Date class methodsFor:'general queries'!
dateAndTimeNow
"return an array containing the date and time of now"
^ Time dateAndTimeNow
"
Date dateAndTimeNow
"
!
dayOfWeek:dayName
"given the name of a day (either string or symbol),
return the day-index (1 for monday; 7 for sunday).
Return 0 for invalid day name"
EnvironmentChange ifTrue:[
self initNames
].
^ DayNames indexOf:dayName
"
Date dayOfWeek:'wednesday'
"
!
nameOfDay:dayIndex
"given a day index (1..7), return the name of the day"
EnvironmentChange ifTrue:[
self initNames
].
^ DayNames at:dayIndex
"
Date nameOfDay:4
"
!
abbreviatedNameOfDay:dayIndex
"given a day index (1..7), return the abbreviated name
of the day"
EnvironmentChange ifTrue:[
self initNames
].
^ DayAbbrevs at:dayIndex
"
Date abbreviatedNameOfDay:4
"
!
indexOfMonth:aMonthString
"given the name of a month (either string or symbol),
return the month-index (1 for jan; 12 for december).
The given string may be a full or abbreviated name,
case is ignored.
Return 0 for invalid month name."
|idx name|
EnvironmentChange ifTrue:[
self initNames
].
name := aMonthString asLowercase.
idx := MonthAbbrevs indexOf:name.
idx ~~ 0 ifTrue:[^ idx].
idx := MonthNames indexOf:name.
idx ~~ 0 ifTrue:[^ idx].
name at:1 put:(name at:1) asUppercase.
idx := MonthAbbrevs indexOf:name.
idx ~~ 0 ifTrue:[^ idx].
idx := MonthNames indexOf:name.
idx ~~ 0 ifTrue:[^ idx].
^ idx
"
Date indexOfMonth:'jan'
Date indexOfMonth:'Jan'
Date indexOfMonth:'December'
"
!
nameOfMonth:monthIndex
"given a month index (1..12), return the name of the month"
EnvironmentChange ifTrue:[
self initNames
].
^ MonthNames at:monthIndex
"
Date nameOfMonth:11
Date nameOfMonth:12
Date nameOfMonth:4
"
!
abbreviatedNameOfMonth:monthIndex
"given a month index (1..12), return the abbreviated name
of the month"
EnvironmentChange ifTrue:[
self initNames
].
^ MonthAbbrevs at:monthIndex
"
Date abbreviatedNameOfMonth:11
Date abbreviatedNameOfMonth:12
"
!
daysInMonth:month forYear:yearInteger
"given the name of a month and a year, return the number
of days this month has (modified GNU).
return 0 if the month name was invalid.
For your convenience, month maybe an integer or name-string."
|monthIndex "{ Class: SmallInteger }"|
month isInteger ifTrue:[
monthIndex := month
] ifFalse:[
monthIndex := self indexOfMonth:month
].
^ self daysInMonthIndex:monthIndex forYear:yearInteger
"
Date daysInMonth:2 forYear:1980
Date daysInMonth:2 forYear:1981
Date daysInMonth:'feb' forYear:1981
"
!
daysUntilMonth:month forYear:yearInteger
"given the name of a month and a year, return the number
of days from 1st january to last of prev month of that year.
Return 0 if the month name/index is invalid or is january.
For your convenience, month maybe an integer or name-string."
|monthIndex "{ Class: SmallInteger }"
sumDays "{ Class: SmallInteger }" |
month isInteger ifTrue:[
monthIndex := month
] ifFalse:[
monthIndex := self indexOfMonth:month
].
(monthIndex between:1 and:12) ifFalse:[^ 0].
sumDays := 0.
1 to:monthIndex-1 do:[:m |
sumDays := sumDays + (self daysInMonthIndex:m forYear:yearInteger)
].
^ sumDays
"
Date daysUntilMonth:'feb' forYear:1993
Date daysUntilMonth:'jan' forYear:1993
"
!
monthAndDayFromDayInYear:aDayInYear forYear:yearInteger
"given a day-in-year (1..365) return an Array containing the
month index and the day-in-month. Return nil if the argument is invalid."
|restDays daysInMonth|
restDays := aDayInYear.
restDays < 1 ifTrue:[^ nil].
1 to:12 do:[:m |
daysInMonth := self daysInMonthIndex:m forYear:yearInteger.
restDays <= daysInMonth ifTrue:[
^ Array with:m with:restDays
].
restDays := restDays - daysInMonth
].
restDays > daysInMonth ifTrue:[^ nil].
^ Array with:12 with:restDays
"
Date monthAndDayFromDayInYear:66 forYear:1980
Date monthAndDayFromDayInYear:66 forYear:1981
"
!
daysInYear:yearInteger
"return the number of days in a year"
(self leapYear:yearInteger) ifTrue:[^ 366].
^ 365
"
Date daysInYear:1900
Date daysInYear:1901
Date daysInYear:1904
Date daysInYear:1980
Date daysInYear:1981
"
!
yearAsDays: yearInteger
"Returns the number of days since Jan 1, 1901. (GNU)
to the first Jan of the year, yearInteger.
For 1901 this is zero, for 1902 its 365.
Defined for years >= 1901"
|y "{ Class: SmallInteger }"|
y := yearInteger - 1900.
y := y - 1.
^ (y * 365)
+ (y // 4)
- (y // 100)
+ ((y + 300) // 400)
"
Date yearAsDays:1901
Date yearAsDays:1902
Date yearAsDays:1903
Date yearAsDays:1904
Date yearAsDays:1905
Date yearAsDays:1994
(Date yearAsDays:2001) - (Date yearAsDays:2000)
"
!
leapYear:yearInteger
"return true, if yearInteger is a leap year."
|y "{ Class: SmallInteger }"|
y := yearInteger.
(y \\ 4 == 0) ifTrue:[
(y \\ 100 ~~ 0) ifTrue:[^ true].
(y \\ 400 == 0) ifTrue:[^ true]
].
^ false
"
Date leapYear:1992
Date leapYear:1994
Date leapYear:1900
Date leapYear:2000
"
!
isLeapYear:yearInteger
"Return true, if a year is a leap year.
Obsolete:
Please use the ST-80 compatible #leapYear for new programs,
since this method will vanish."
^ self leapYear:yearInteger
! !
!Date class methodsFor:'instance creation'!
fromOSTime:osTime
"return a date, representing the date given by the operatingSystem time.
This somewhat clumsy implementation hides the OS's date representation
(i.e. makes this class independent of what the OS starts its time values with).
Dont use this method, the osTime representation is totally unportable."
^ self basicNew fromOSTime:osTime
"
Date fromOSTime:#(0 0) -> on UNIX: this should return 1st Jan 1970
thats where Unix time starts
On other systems, it may be something different.
Date fromOSTime:#(86400 0) -> on UNIX: the day after
"
!
today
"return a date, representing today"
^ self fromOSTime:OperatingSystem getTimeParts
"
Date today
"
!
fromDays:dayCount
"return a new Date, given the day-number starting with 0 at 1.Jan 1901;
(i.e. 'Date fromDays:0' returns 1st Jan. 1901).
Date asDays is the reverse operation.
for GNU/ST-80 compatibility"
|yr rest d|
"approx. year"
yr := (dayCount // 366) + 1901.
rest := dayCount - (self yearAsDays:yr) + 1. "+1 for ST-80 compatibility"
d := self daysInYear:yr.
(rest > d) ifTrue:[
"adjust"
yr := yr + 1.
rest := rest - d.
].
^ self day:rest year:yr
"
Date fromDays:0 -> 1 jan 1901
Date fromDays:365 -> 1 jan 1902
Date fromDays:730 -> 1 jan 1903
Date fromDays:1095 -> 1 jan 1903
Date fromDays:1460 ->31 dec 1904 since 1904 was a leap year
"
!
day:dayInYear year:year
"return a new Date, given the year and the day-in-year (starting at 1).
Obsolete:
use newDay:year: for ST-80 compatibility"
^ self newDay:dayInYear year:year
!
newDay:dayInYear year:year
"return a new Date, given the year and the day-in-year (starting at 1).
ST-80 compatibility"
|monthAndDay|
(dayInYear between:1 and:365) ifFalse:[
((dayInYear == 366) and:[self leapYear:year]) ifFalse:[
"
this error is triggered, when you try to create a
day from an invalid day-in-year;
for example, 366 in a non-leap year.
I dont know, if ST-80 wraps to the next year(s) in this case.
"
^ self error:'invalid date'
]
].
monthAndDay := self monthAndDayFromDayInYear:dayInYear forYear:year.
^ self day:(monthAndDay at:2) month:(monthAndDay at:1) year:year
"
Date newDay:150 year:1994
Date newDay:1 year:1994
Date newDay:1 year:1901
Date newDay:1 year:1902
Date newDay:365 year:1992
Date newDay:366 year:1992
Date newDay:365 year:1994
Date newDay:366 year:1994
"
!
day:day month:month year:year
"return a new Date, given the day, month and year.
Obsolete:
use newDay:month:year: for ST-80 compatibility"
^ self newDay:day month:month year:year
!
newDay:day month:month year:year
"return a new Date, given the day, month and year.
For your convenience, month may be either an integer
or the months name as a string.
Year may be the actual year (such as 1890, 2001) or the number
of years since 1900 (which is rubbish ST-80 compatibility:
it will be totally useless in a few years ...).
You better not use this short-year feature in your programs."
|monthIndex ok yr|
yr := year.
yr < 100 ifTrue:[
yr := yr + 1900.
].
month isInteger ifTrue:[
monthIndex := month
] ifFalse:[
monthIndex := self indexOfMonth:month
].
(monthIndex == 2 and:[day == 29]) ifTrue:[
ok := self leapYear:yr
] ifFalse:[
ok := day <= (self daysInMonth:month forYear:yr)
].
((day > 0) and:[ok]) ifTrue:[
^ self basicNew dateEncoding:(((yr * 100) + monthIndex) * 100) + day
].
"this error is triggered if you try to create a date from an
invalid year/month/day combination;
Such as 29-feb-year, where year is no leap year
"
self error:'invalid date'
"
Date newDay:8 month:'may' year:1993
Date newDay:8 month:5 year:1994
Date newDay:29 month:'feb' year:1994
Date newDay:29 month:'feb' year:1993
Date newDay:28 month:'feb' year:5
Date newDay:28 month:'feb' year:95
"
!
readFromString:aString onError:exceptionBlock
"return a new Date, reading a printed representation from aStream.
Notice, that this is not the storeString format and
is different from the format expected by readFrom:.
BUG:
This method assumes american format (i.e. month-day-year) instead
of the german/french and other day-month-year.
There ought to be a nationalized variant of this."
|month day year aStream|
aStream := ReadStream on:aString.
[aStream peek isLetterOrDigit] whileFalse:[aStream next].
(aStream peek isDigit) ifTrue:[
day := Integer readFrom:aStream onError:[^ exceptionBlock value]
].
[aStream peek isLetterOrDigit] whileFalse:[aStream next].
(aStream peek isLetter) ifTrue:[
month := aStream nextAlphaNumericWord.
day isNil ifTrue:[
[aStream peek isLetterOrDigit] whileFalse:[aStream next].
day := Integer readFrom:aStream onError:[^ exceptionBlock value].
]
] ifFalse:[
month := self nameOfMonth:day.
day := Integer readFrom:aStream onError:[^ exceptionBlock value]
].
[aStream peek isLetterOrDigit] whileFalse:[aStream next].
year := Integer readFrom:aStream onError:[^ exceptionBlock value].
^ self newDay:day month:month year:year
"
Date readFromString:'31 December 1992'
Date readFromString:'December, 5, 1992'
Date readFromString:'December, 5 1992'
Date readFromString:'3-jan-95'
Date readFromString:'12/31/1992'
Date readFromString:'15.4.1992' -> german; leads to an error
Date readFromString:'10.4.1992' -> german; leads to a wrong date
Date readFromString:'10.4.1992' onError:['wrong date']
"
! !
!Date class methodsFor:'private encoding'!
encodeYear:y month:m day:d
"the internal encoding is stricktly private,
and should not be used outside."
^ (((y * 100) + m) * 100) + d
! !
!Date methodsFor:'private accessing'!
dateEncoding
"the internal encoding is stricktly private,
and should not be used outside."
^ dateEncoding
!
dateEncoding:anInteger
"the internal encoding is stricktly private,
and should not be used outside."
dateEncoding := anInteger
!
fromOSTime:osTime
"set my dateEncoding from an OS time.
This somewhat clumsy implementation hides the OS's date representation
(i.e. makes this class independent of what the OS starts its time values with).
Dont use this method, the osTime representation is totally unportable."
OperatingSystem computeDatePartsOf:osTime
for:[:year :month :day |
dateEncoding := (((year * 100) + month) * 100) + day
]
! !
!Date methodsFor:'arithmetic'!
plusDays:days
"return a new date representing 'days' after the receiver.
The argument should be some kind of integer.
Obsolete:
Please dont use this method since it will vanish.
Use #addDays: instead for ST-80 compatibility."
^ self addDays:days
!
addDays:days
"return a new date representing 'days' after the receiver.
The argument should be some kind of integer.
For ST-80 compatibility."
^ self class fromDays:(self asDays + days)
"
Date today addDays:7
"
!
minusDays:days
"return a new date representing 'days' before the receiver.
The argument should be some kind of integer.
Obsolete:
Please dont use this method since it will vanish.
Use #subtractDays: instead for ST-80 compatibility."
^ self subtractDays:days
!
subtractDays:days
"return a new date representing 'days' before the receiver.
The argument should be some kind of integer.
For ST-80 compatibility"
^ self class fromDays:(self asDays - days)
"
Date today subtractDays:7
"
!
subtractDate:aDate
"return the number of days between the receiver and aDate"
^ self asDays - aDate asDays
"
(Date day:1 month:1 year:1995) subtractDate:(Date day:24 month:12 year:1994)
(Date day:1 month:3 year:1992) subtractDate:(Date day:1 month:2 year:1992)
(Date day:1 month:3 year:1994) subtractDate:(Date day:1 month:2 year:1994)
"
!
daysUntil:aDate
"return the number of days between the receiver and the argument,
aDate, whuch should be some kind of date"
^ aDate asDays - self asDays
"
(Date day:24 month:12 year:1994) daysUntil:(Date day:1 month:1 year:1995)
(Date day:1 month:2 year:1992) daysUntil:(Date day:1 month:3 year:1992)
(Date day:1 month:2 year:1994) daysUntil:(Date day:1 month:3 year:1994)
|delta|
delta := Date today
daysUntil:(Date day:25 month:12 year:Date today year).
Transcript show:'still ';
show:delta ;
showCr:' days till xmas'
"
! !
!Date methodsFor:'accessing'!
day
"return the day (1..31) of the receiver"
^ dateEncoding \\ 100
"
Date today day
"
!
month
"return the month (1..12) of the receiver"
^ (dateEncoding // 100) \\ 100
"
Date today month
"
!
year
"return the year (1..12) of the receiver"
^ dateEncoding // (100*100)
"
Date today year
"
!
leap
"return true, if the receivers year is a leap year"
^ Date leapYear:(self year)
"
Date today leap
(Date day:1 month:1 year:1992) leap
"
!
dayCount
"return the number of days since 1st. Jan. 1901;
starting with 0 for this date.
Date>>fromDays: is the reverse operation.
Obsolete:
please use asDays for ST-80 compatibility"
^ self asDays.
"
(Date day:1 month:1 year:1901) dayCount
Date fromDays:(Date day:1 month:1 year:1994) dayCount
Date today dayCount
"
!
asDays
"return the number of days elapsed since 01-Jan-1901
and the receiver's day; starts with 0 for 1-1-1901.
Date>>fromDays: is the reverse operation.
For ST-80 compatibility."
|yr|
yr := self year.
^ (self class yearAsDays:yr)
+ (self class daysUntilMonth:self month forYear:yr)
+ self day
- 1
"
(Date day: 5 month: 8 year: 1962) asDays -> should be 22496
(Date day: 1 month: 1 year: 1901) asDays -> 0
Date today asDays
Date fromDays:(Date today asDays + 7)
"
!
asSeconds
"return the seconds between 1.jan.1901 and the same time in the receivers
day. (i.e. midnight to midnight).
ST-80 compatibility."
^ 60*60*24 * self asDays
"
(Date day: 5 month: 8 year: 1962) asSeconds
(Date day: 1 month: 1 year: 1901) asSeconds
(Date today addDays:7) asSeconds - Date today asSeconds
"
!
dayOfMonth
"Answer the day of the month represented by me.
Same as day; for ST-80 compatibility."
^ self day
"
Date today dayOfMonth
"
!
daysInMonth
"return the number of days in the month of the receiver"
^ Date daysInMonth:(self month) forYear:(self year)
"
Date today daysInMonth
"
!
daysInYear
"return the number of days in the year of the receiver"
^ Date daysInYear:(self year)
"
Date today daysInYear
"
!
daysLeftInYear
"return the number of days left in the year of the receiver"
^ Date daysInYear:(self year) - self day
"
Date today daysLeftInYear
"
!
dayInWeek
"return the week-day of the receiver - 1 for monday, 7 for sunday"
^ (1 "know, that 1st Jan 1901 was a tuesday"
+ self asDays) \\ 7 + 1
"
Date today dayInWeek
(Date day:15 month:4 year:1959) dayInWeek
"
!
dayName
"return the week-day of the receiver as a string.
The returned string depends on the language setting.
Expect things like 'monday', 'tuesday' ...
Obsolete:
use #weekday for ST-80 compatibility"
^ self weekday
!
weekday
"return the week-day of the receiver as a string.
The returned string depends on the language setting.
Expect things like 'monday', 'tuesday' ...
For ST-80 compatibility"
^ self class nameOfDay:(self dayInWeek)
"
Date today weekday
(Date day:15 month:4 year:1959) weekday
"
!
abbreviatedDayName
"return the short week-day of the receiver as a string.
The returned string depends on the language setting.
Expect things like 'mon', 'tue' ..."
^ self class abbreviatedNameOfDay:(self dayInWeek)
"
Date today abbreviatedDayName
(Date day:15 month:4 year:1959) abbreviatedDayName
"
!
monthIndex
"return the index of the month (e.g. Feb.=2).
Same as month; for ST-80 compatibility."
^ self month
!
monthName
"return the month of the receiver as a string.
The returned string depends on the language setting.
Expect things like 'january', 'february' ..."
^ self class nameOfMonth:(self month)
"
Date today monthName
(Date day:15 month:4 year:1959) monthName
"
!
abbreviatedMonthName
"return the month of the receiver as a string.
The returned string depends on the language setting.
Expect things like 'jan', 'feb' ..."
^ self class abbreviatedNameOfMonth:(self month)
"
Date today abbreviatedMonthName
(Date day:15 month:4 year:1959) abbreviatedMonthName
"
! !
!Date methodsFor:'comparing'!
< aDate
"return true, if the date represented by the receiver
is before the argument, aDate"
(aDate isMemberOf:Date) ifTrue:[
^ dateEncoding < aDate dateEncoding
].
"the argument must understand year, month and day to be
comparable, whatever it is"
^ dateEncoding < (Date encodeYear:aDate year
month:aDate month
day:aDate day)
"Date today < (Date day:24 month:12 year:2000)"
"Date today < (Date day:24 month:12 year:1900)"
!
> aDate
"return true, if the date represented by the receiver
is after the argument, aDate"
(aDate isMemberOf:Date) ifTrue:[
^ dateEncoding > aDate dateEncoding
].
"the argument must understand year, month and day to be
comparable, whatever it is"
^ dateEncoding > (Date encodeYear:aDate year
month:aDate month
day:aDate day)
"Date today > (Date day:24 month:12 year:2000)"
"Date today > (Date day:24 month:12 year:1900)"
!
= aDate
"return true, if the date represented by the receiver
is the same as the one represented by argument, aDate"
(aDate isMemberOf:Date) ifFalse:[^ false].
^ dateEncoding = aDate dateEncoding
"the argument must understand year, month and day to be
comparable, whatever it is"
"
^ dateEncoding = (Date encodeYear:aDate year
month:aDate month
day:aDate day)
"
"Date today = ((Date today plusDays:7) minusDays:7)"
!
hash
"return an integer useful for hashing on dates"
^ dateEncoding
! !
!Date methodsFor:'printing & storing'!
storeOn:aStream
"append a representation to aStream, from which the receiver
can be reconstructed"
aStream nextPutAll:'('.
aStream nextPutAll:'Date day:'.
self day printOn:aStream.
aStream nextPutAll:' month:'.
self month printOn:aStream.
aStream nextPutAll:' year:'.
self year printOn:aStream.
aStream nextPutAll:')'
"Date today storeOn:Transcript"
!
printOn:aStream
"append a printed representation of the receiver to aStream"
self day printOn:aStream.
aStream nextPutAll:'-'.
(Date abbreviatedNameOfMonth:self month) printOn:aStream.
aStream nextPutAll:'-'.
self year printOn:aStream
"Date today printOn:Transcript"
"Date today printNL"
! !