Date.st
author claus
Sat, 08 Jan 1994 17:12:00 +0100
changeset 29 b6577a9f8cee
parent 10 4f1f9a91e406
child 54 06dbdeeed4f9
permissions -rw-r--r--
*** empty log message ***

"
 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.


 ----------------------------------------------------------------
 For code marked as (GNU) the following applies:

 Copyright (C) 1988, 1989 Free Software Foundation, Inc.
 Written by Steve Byrne.

 This file is part of GNU Smalltalk.

 GNU Smalltalk is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the Free
 Software Foundation; either version 1, or (at your option) any later version.

 GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 details.

 You should have received a copy of the GNU General Public License along with
 GNU Smalltalk; see the file LICENSE.  If not, write to the Free Software
 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 ----------------------------------------------------------------
"

AbsoluteTime subclass:#Date
       instanceVariableNames:''
       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.6 1994-01-08 16:12:00 claus Exp $

written Spring 89 by claus
'!

!Date class methodsFor:'private'!

initNames
    "read the language specific names"

    |resources|

    resources := ResourcePack for:self.

    DayNames := resources array:#('monday'
                                  'tuesday'
                                  'wednesday'
                                  'thursday'
                                  'friday'
                                  'saturday'
                                  'sunday').

    DayAbbrevs := resources array:#('mon' 
                                    'tue' 
                                    'wed'
                                    'thu' 
                                    'fri' 
                                    'sat' 
                                    'sun').

    MonthNames := resources array:#('january'
                                    'february'
                                    'march'
                                    'april'
                                    'may'
                                    'june'
                                    'july'
                                    'august'
                                    'september'
                                    'october'
                                    'november'
                                    'december').

    MonthAbbrevs := resources array:#('jan'
                                      'feb'
                                      'mar'
                                      'apr'
                                      'may'
                                      'jun'
                                      'jul'
                                      'aug'
                                      'sep'
                                      'oct'
                                      'nov'
                                      'dec').

    EnvironmentChange := false

    "Date initNames"
! !

!Date class methodsFor:'handling language changes'!

initialize
    super initialize.
    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'!

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'"
!

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.
     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'"
!

nameOfDay:dayIndex
    "given a day index (1..7), return the name of the day 
     as a symbol"

    EnvironmentChange ifTrue:[
        self initNames
    ].
    ^ (DayNames at:dayIndex) asSymbol

    "Date nameOfDay:4"
!

nameOfMonth:monthIndex
    "given a month index (1..12), return the name of the month 
     as a symbol"

    EnvironmentChange ifTrue:[
        self initNames
    ].
    ^ (MonthNames at:monthIndex) asSymbol

    "Date nameOfMonth:11"
    "Date nameOfMonth:12"
    "Date nameOfMonth:4"
!

abbreviatedNameOfDay:dayIndex
    "given a day index (1..7), return the abbreviated name
     of the day as a symbol"

    EnvironmentChange ifTrue:[
        self initNames
    ].
    ^ (DayAbbrevs at:dayIndex) asSymbol
!

abbreviatedNameOfMonth:monthIndex
    "given a month index (1..12), return the abbreviated name
     of the month as a symbol"

    EnvironmentChange ifTrue:[
        self initNames
    ].
    ^ (MonthAbbrevs at:monthIndex) asSymbol
!

daysInMonth:monthName forYear:yearInteger
    "given the name of a minth and a year, return the number 
     of days this month has (modified GNU).
     return 0 if the month name was invalid."

    |monthIndex|

    monthIndex := self indexOfMonth:monthName.
    (monthIndex == 0) ifTrue:[
        ^ 0
    ].
    ^ self daysInMonthIndex:monthIndex forYear:yearInteger

    "Date daysInMonth:2 forYear:1980"
    "Date daysInMonth:2 forYear:1981"
!

daysUntilMonth:monthName forYear:yearInteger
    "given the name of a month and a year, return the number 
     of days from 1st of january to last of prev month.
     return 0 if the month name was invalid."

    |monthIndex sumDays|

    monthIndex := self indexOfMonth:monthName.
    (monthIndex == 0) ifTrue:[
        ^ 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"
!

daysInYear:yearInteger
    "return the number of days in a year"

    (self isLeapYear:yearInteger) ifTrue:[^ 366].
    ^ 365

    "Date daysInYear:1980"
    "Date daysInYear:1981"
!

yearAsDays: yearInteger
    "Returns the number of days since Jan 1, 1901. (GNU)"

    |y|

    y := yearInteger - 1900.
    ^ (y - 1) * 365
        + (y // 4)
        - (y // 100)
        + (y // 400)
!

isLeapYear:yearInteger
    "return true, if a year is a leap year"

    (yearInteger \\ 4 == 0) ifTrue:[
        (yearInteger \\ 100 ~~ 0) ifTrue:[^ true].
        (yearInteger \\ 400 == 0) ifTrue:[^ true]
    ].
    ^ false
!

daysInMonthIndex: monthIndex forYear: yearInteger
    "return the number of days in month monthIndex of
     year yearInteger (GNU)"

    |days|

    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 isLeapYear:yearInteger) ifTrue:[
            ^ days + 1
        ]
    ].
    ^ days
! !

!Date class methodsFor:'instance creation'!

today
    "return a date, representing today"

    ^ self basicNew setSecondsLow:(OperatingSystem getTimeLow)
                              and:(OperatingSystem getTimeHi)
!

fromDays:dayCount
    ^ self new setDays:dayCount
!

newDay:dayCount year:yearInteger
    ^ self new setDays:(dayCount + self yearAsDays:yearInteger)
!

newDay:day month:monthName year:yearInteger
    ^self new setDays:
        (day + (self daysUntilMonth: monthName forYear: yearInteger)
             + (self yearAsDays: yearInteger))

    "Date newDay:8 month:'may' year:1993"
! !

!Date methodsFor:'comparing'!

< aDate
    "return true, if the date represented by the receiver
     is before the argument, aDate"

    |other|

    (aDate isMemberOf:Date) ifTrue:[
        OperatingSystem computeDatePartsOf:secondsLow and:secondsHi
                                       for:[:year :month :day |
            other := aDate year.
            (year < other) ifTrue:[^ true].
            (year > other) ifTrue:[^ false].
            other := aDate month.
            (month < other) ifTrue:[^ true].
            (month > other) ifTrue:[^ false].
            ^ day < aDate day
        ].
    ].
    ^ super < aDate 
!

> aDate
    "return true, if the date represented by the receiver
     is after the argument, aDate"

    |other|

    (aDate isMemberOf:Date) ifTrue:[
        OperatingSystem computeDatePartsOf:secondsLow and:secondsHi
                                       for:[:year :month :day |
            other := aDate year.
            (year > other) ifTrue:[^ true].
            (year < other) ifTrue:[^ false].
            other := aDate month.
            (month > other) ifTrue:[^ true].
            (month < other) ifTrue:[^ false].
            ^ day > aDate day
        ].
    ].
    ^ super > aDate 
!

= aDate
    "return true, if the date represented by the receiver
     is the same as the one represented by argument, aDate"

    (aDate isMemberOf:Date) ifTrue:[
        OperatingSystem computeDatePartsOf:secondsLow and:secondsHi
                                       for:[:year :month :day |
            (year ~~ aDate year) ifTrue:[^ false].
            (month ~~ aDate month) ifTrue:[^ false].
            ^ (day == aDate day)
        ]
    ].
    ^ super = aDate 
! !

!Date methodsFor:'printing'!

printString
    |string|

    OperatingSystem computeDatePartsOf:secondsLow and:secondsHi
                                   for:[:year :month :day |
        string :=   day printString
                  , '-' 
                  , (Date abbreviatedNameOfMonth:month)
                  , '-' 
                  , year printString
    ].
    ^ string
! !