!=========================================================================
! Copyright (C) VMware, Inc. 1986-2011.  All Rights Reserved.
!
! $Id: obsdatetime.gs,v 1.6 2008-01-09 22:50:12 stever Exp $
!
! Superclass Hierarchy:
!   ObsoleteDateTime, Magnitude, Object.
!
!=========================================================================

removeallmethods ObsoleteDateTime
removeallclassmethods ObsoleteDateTime

category: 'For Documentation Installation only'
classmethod: ObsoleteDateTime
installDocumentation

| doc txt |
doc := GsClassDocumentation _newForObsoleteGsClass: self asOfGsVersion: '5.0'.

txt := (GsDocText new) details:
'Existing instances should be migrated to DateTime or otherwise processed as
 required, and then should be removed.

 Each instance of ObsoleteDateTime describes a moment in time, expressed in the
 local time zone, with one-second resolution.  Only dates after 1 March 1583
 can be represented faithfully.

 Each instance of ObsoleteDateTime is represented by two four-byte values.  The
 first four bytes represent the Julian Day of the instance (that is, the number
 of days since January 1, 4713 BC).  The second four bytes represent the number
 of seconds since midnight.  In each of these values, the least significant byte
 is stored first.'.
doc documentClassWith: txt.

txt := (GsDocText new) details:
'a LanguageDictionary; each key is a Symbol representing one of the native
 languages supported by GemStone, and each value is an Array of Strings (the
 names of the days of the week in the corresponding language).'.
doc documentClassVar: #WeekDayNames with: txt.

txt := (GsDocText new) details:
'a LanguageDictionary; each key is a Symbol representing one of the native
 languages supported by GemStone, and each value is an Array of Strings (the
 names of the months of the year in the corresponding language).'.
doc documentClassVar: #MonthNames with: txt.

self description: doc.
%

category: 'Instance Creation'
classmethod: ObsoleteDateTime
fromString: aString

"New instances cannot be created for obsolete classes."

^ self _error: #rtObsoleteClass.
%

category: 'Instance Creation'
classmethod: ObsoleteDateTime
fromStream: aStream

"New instances cannot be created for obsolete classes."

^ self _error: #rtObsoleteClass.
%

category: 'Instance Creation'
classmethod: ObsoleteDateTime
fromString: aString usingFormat: anArray

"New instances cannot be created for obsolete classes."

^ self _error: #rtObsoleteClass.
%

category: 'Instance Creation'
classmethod: ObsoleteDateTime
new

"Disallowed.  To create a new ObsoleteDateTime, use one of the other instance creation
 methods listed here."

self shouldNotImplement: #new
%

category: 'Instance Creation'
classmethod: ObsoleteDateTime
new: anInteger

"Disallowed.  To create a new ObsoleteDateTime, use one of the other instance creation
 methods listed here."

self shouldNotImplement: #new:
%

category: 'Instance Creation'
classmethod: ObsoleteDateTime
newWithYear: yearInt month: monthInt day: dayInt hours: hourInt
  minutes: minuteInt seconds: secondInt

"New instances cannot be created for obsolete classes."

^ self _error: #rtObsoleteClass.
%

category: 'Instance Creation'
classmethod: ObsoleteDateTime
_newWithYear: yearInt month: monthInt day: dayInt seconds: secondInt

"New instances cannot be created for obsolete classes."

^ self _error: #rtObsoleteClass.
%

category: 'Instance Creation'
classmethod: ObsoleteDateTime
_newJulianDay: anInteger second: anotherInteger

"New instances cannot be created for obsolete classes."

^ self _error: #rtObsoleteClass.
%

category: 'Instance Creation'
classmethod: ObsoleteDateTime
_checkFormat: anArray

""

"anArray is a format Array as documented in ObsoleteDateTime>>asStringUsingFormat:"

| v doTime |

anArray _validateClass: Array.
(anArray size < 8 _or:[ anArray size > 10])
  ifTrue:[ ObsoleteDateTime _error: #rtErrBadFormatSpec args: #[anArray] ].

"Check for a combination of the digits 1, 2, and 3"
((anArray at: 1) + (anArray at: 2) + (anArray at: 3) = 6 _and:
        [(anArray at: 1) * (anArray at: 2) * (anArray at: 3) = 6])
  ifFalse:[ ObsoleteDateTime _error: #rtErrBadFormatSpec args: #[anArray] ].

(anArray at: 4) _validateClass: AbstractCharacter.

((v := anArray at: 5) = 1 _or: [v = 2 _or: [v = 3]])
  ifFalse:[ ObsoleteDateTime _error: #rtErrBadFormatSpec args: #[anArray] ].

((anArray at: 6) = 1 _or: [(anArray at: 6) = 2])
  ifFalse:[ ObsoleteDateTime _error: #rtErrBadFormatSpec args: #[anArray] ].

(doTime := anArray at: 8) _validateClass: Boolean.
doTime ifTrue:[
  anArray size = 10 
    ifFalse:[ ObsoleteDateTime _error: #rtErrBadFormatSpec args: #[anArray] ].
  (anArray at: 7) _validateClass: AbstractCharacter.
  (anArray at: 9) _validateClass: Boolean.
  (anArray at: 10) _validateClass: Boolean.
  ]
%

category: 'Instance Creation'
classmethod: ObsoleteDateTime
_getMonthFrom: aCharCollection

"Reads a month name or abbreviation from aCharCollection and returns the
 integer corresponding to the month of the year."

| whichMonth monthArray argSize matchMonth |

monthArray := MonthNames value.
matchMonth:= [:monthStr | | strSize match i |
   i:= 1.
   match:= false.
   strSize:= monthStr size.
   [ ((i <= argSize) & (i <= strSize)) _and:
     [match:= (aCharCollection at: i) isEquivalent: (monthStr at: i)]]
   whileTrue: [
      i:= i + 1.
   ].
   match
].

   argSize:= aCharCollection size.
   whichMonth:= 1.
   [ (whichMonth <= 12) _and:
     [(matchMonth value: (monthArray at: whichMonth)) not]
   ]
   whileTrue:
      [whichMonth := whichMonth + 1].

   (whichMonth <= 12)
      ifTrue: [ ^whichMonth].
   ^ 0
%

category: 'Instance Creation'
classmethod: ObsoleteDateTime
now

"New instances cannot be created for obsolete classes."

^ self _error: #rtObsoleteClass.
%

category: 'Instance Creation'
classmethod: ObsoleteDateTime
fromStream: aStream usingFormat: anArray

"New instances cannot be created for obsolete classes."

^ self _error: #rtObsoleteClass.
%

category: 'Accessing'
method: ObsoleteDateTime
at: anIndex put: aValue

"Disallowed.  You may not change the value of a ObsoleteDateTime."

self shouldNotImplement: #at:put:
%

category: 'Accessing'
method: ObsoleteDateTime
dayOfMonth

"Returns the day of the month as a SmallInteger."

^  (self _yearMonthDay) at: 3
%

category: 'Accessing'
method: ObsoleteDateTime
dayOfWeek

"Returns the numeric index of the day of the week (1-7), where 1 = Sunday."

^ self julianDay - 2299295 - 1 \\ 7 + 1

  "the Julian day 2299298 is converted to the Gregorian"
  "date of March 1, 1583 by Communications of the ACM #199 algorithm"
  "was March 1, 1583 a Thursday?"
%

category: 'Accessing'
method: ObsoleteDateTime
dayOfYear

"Returns the day of the year as a SmallInteger."

|t y |

t := self _yearMonthDay.
y := 0.
1 to: ((t at: 2) - 1) do: [:month |
   ((month = 1) _or: [(month = 3) _or: [(month = 5) _or: [(month = 7) _or:
   [(month = 8) _or: [(month = 10) _or: [(month = 12)]]]]]])
      ifTrue: [y := y + 31].
   ((month = 4) _or: [(month = 6) _or: [(month = 9) _or: [(month = 11)]]])
      ifTrue: [y := y + 30].
   (month = 2)
      ifTrue:[(self leap)
         ifTrue: [y := y + 29]
         ifFalse: [y := y + 28]]].
^ y + (t at: 3)
%

category: 'Accessing'
method: ObsoleteDateTime
daysInMonth

"Returns the number of days in the month represented by the receiver."

|t month|

t := self _yearMonthDay.
month := t at: 2.
((month = 1) _or: [(month = 3) _or: [(month = 5) _or: [(month = 7) _or:
   [(month = 8) _or: [(month = 10) _or: [(month = 12)]]]]]])
   ifTrue: [^ 31].
((month = 4) _or: [(month = 6) _or: [(month = 9) _or: [(month = 11)]]])
   ifTrue: [^ 30].
(self leap)
   ifTrue: [^ 29].
^ 28
%

category: 'Accessing'
method: ObsoleteDateTime
daysInYear

"Returns the number of days in the year represented by the receiver."

(self leap)
   ifTrue: [^ 366].
^ 365
%

category: 'Accessing'
method: ObsoleteDateTime
hours

"Returns the hours since midnight (0-23)."

^ self julianSecond // 3600
%

category: 'Accessing'
method: ObsoleteDateTime
julianDay

"Returns the Julian Day, a SmallInteger representing the number of days since
 January 1, 4713 BC (as defined in Communications of the ACM algorithm #199)."

^ self asDateTime julianDay.
%

category: 'Accessing'
method: ObsoleteDateTime
julianSecond

"Returns a SmallInteger representing the number of seconds since midnight."

^ self asDateTime seconds
%

category: 'Accessing'
method: ObsoleteDateTime
leap

"Returns true if the receiver represents a leap year and false if it does not."

| yr |
  "a year is a leap year if: (it is evenly divisible by 4 and it is not a
   century year) or (it is a century year and evenly divisible by 400)"

yr := (self _yearMonthDay) at: 1.
((yr \\ 100) = 0)
   ifTrue: [^ ((yr \\ 400) = 0)].
^ ((yr \\ 4) = 0)
%

category: 'Accessing'
method: ObsoleteDateTime
minutes

"Returns the minutes since the hour (0-59)."

^ self julianSecond \\ 3600 // 60
%

category: 'Accessing'
method: ObsoleteDateTime
monthName

"Returns the name of the month (a String) in the user's native language."

^ MonthNames value at: ((self _yearMonthDay) at: 2)
%

category: 'Accessing'
method: ObsoleteDateTime
monthOfYear

"Returns the numeric index of the month (1-12)."

^ (self _yearMonthDay) at: 2
%

category: 'Accessing'
method: ObsoleteDateTime
seconds

"Returns the seconds since the minute (0-59)."

^ self julianSecond \\ 60
%

category: 'Accessing'
method: ObsoleteDateTime
size: anInteger

"Disallowed.  You may not change the size of a ObsoleteDateTime."

self shouldNotImplement: #size:
%

category: 'Accessing'
method: ObsoleteDateTime
timeAsSeconds

"Returns the number of seconds since midnight represented by the receiver."

^ self julianSecond
%

category: 'Accessing'
method: ObsoleteDateTime
weekDayName

"Returns the name of the day of the week (a String) in the user's native
 language."

^ WeekDayNames value at: (self dayOfWeek)
%

category: 'Accessing'
method: ObsoleteDateTime
year

"Returns the calendar year as an integer."

^ (self _yearMonthDay) at: 1
%

category: 'Accessing'
method: ObsoleteDateTime
_yearMonthDay

"Returns a three-element Array of SmallIntegers containing the year, index of
 the month, and the day of the month of the Gregorian calendar calculated from
 the Julian day of the receiver."

^ self asDateTime _yearMonthDay
%

category: 'Formatting'
method: ObsoleteDateTime
printOn: aStream

"Puts a displayable representation of the receiver on the given stream."

aStream nextPut: $' .
aStream nextPutAll: self asString .
aStream nextPut: $'
%

category: 'Formatting'
method: ObsoleteDateTime
asString

"Returns a String representing the receiver.  The String is in
 the format DD/MM/YYYY HH:MM:SS, with hours in military time."

| t julSec |

t := self _yearMonthDay.
julSec := self julianSecond.
^ (t at: 3) _digitsAsString
  addAll: '/';
  addAll: (t at: 2) _digitsAsString;
  addAll: '/';
  addAll: (t at: 1) _digitsAsString;
  addAll: ' ';
  addAll: (julSec // 3600) _digitsAsString;
  addAll: ':';
  addAll: (julSec \\ 3600 // 60) _digitsAsString;
  addAll: ':';
  addAll: (julSec \\ 60) _digitsAsString
%

!  bug 6135 fixed
category: 'Formatting'
method: ObsoleteDateTime
asStringUsingFormat: anArray

"Returns a String representing the receiver.  The format of the String is
 determined by anArray, whose elements are described in the following table.

 Generates an error if anArray does not contain all required elements or
 if the value of any Array element does not conform to the requirements set
 forth in the following table.  anArray must contain at least 8 elements if 
 time is not printed, and must contain 10 elements otherwise.

 ObsoleteDateTime String Format

 Element       Acceptable Value        Explanation

 1st,2nd,3rd   The integers 1, 2, 3,   Determines the position of day,
               in any order            month, year.  1 corresponds
                                       to day, 2=month, 3=year.

 4th           A separator Character   Separates year, month, and day.
               (preceded by $)

 5th           Month format            With asStringUsingFormat:
                                       1 = print as number
                                       2 = print 3-letter abbreviation
                                       3 = print entire name

                                       With fromStreamUsingFormat: or
                                       fromString:usingFormat:
                                       1 = decode a number to determine
                                           the month
                                       2 or 3 = decode a character string to
                                           determine the month

 6th           Year format             With asStringUsingFormat:
                                       1 = print entire year
                                       2 = print last 2 digits (year mod 100)

                                       With fromStreamUsingFormat: or
                                       fromString:usingFormat:
                                       1 = read entire year
                                       2 = read only the last 2 digits

 7th           A separator Character   Separates hours, minutes, and seconds.
               (preceded by $)

 8th           true or false           If true, print or read the time as
                                       indicated by the 7th, 9th and 10th
                                       elements.  If false, ignore those
                                       elements, and the 9th and 10th elements
                                       are optional.

 9th           true or false           Whether or not to print or read seconds.

 10th          true or false           true = print (read) time in 12-hour
                                       format, with am or pm (such as
                                       1:30:55 pm).  The space is required
                                       preceding the am or pm indicator.

                                       false = print (read) time in 24-hour
                                       format (such as 13:30:55)"

|t julSec dateSeparator timeSeparator monthName aString
 hour hourInt min sec day year|

t := self _yearMonthDay.
julSec := self julianSecond.

ObsoleteDateTime _checkFormat: anArray.

dateSeparator := (anArray at: 4) asString.

timeSeparator := (anArray at: 7) asString.

((anArray at: 5) = 2) "get the month name according to the format"
   ifTrue: [monthName := self _monthAbbrev: (t at: 2)]
   ifFalse: [((anArray at: 5) = 3) "month as number is default"
      ifTrue: [monthName := self _monthName: (t at: 2)]
      ifFalse: [monthName := (t at: 2) _digitsAsString]].

((anArray at: 6) = 2)
   ifTrue: [year := ((t at: 1) \\ 100) _digitsAsString]
   ifFalse: [year := (t at: 1) asString].  "YYYY is default"

day := (t at:3) _digitsAsString.
((anArray at: 1) = 2) "month first"
   ifTrue: [aString := monthName + dateSeparator]
   ifFalse: [((anArray at: 1) = 3) "year first"
      ifTrue: [aString := year + dateSeparator]
      ifFalse: [aString := day + dateSeparator]].  "day first is default"

((anArray at: 2) = 1) "day second"
   ifTrue: [aString addAll: day; addAll: dateSeparator] "year second"
   ifFalse: [((anArray at: 2) = 3) "month second is default"
      ifTrue: [aString addAll: year; addAll: dateSeparator]
      ifFalse: [aString addAll: monthName; addAll: dateSeparator]].

((anArray at: 3) = 1) "day third"
   ifTrue: [aString addAll: day]
   ifFalse: [((anArray at: 3) = 2) "month third"
      ifTrue: [aString addAll: monthName]
      ifFalse: [aString addAll: year]].  "year third is default"

hourInt := julSec // 3600.
hour := hourInt _digitsAsString.
min := (julSec \\ 3600 // 60) _digitsAsString.
sec := (julSec \\ 60) _digitsAsString.

(anArray at: 8) ifTrue: [ "print the time"
  aString add: $ .
  (anArray at: 10) ifTrue: [ "12-hour format"
    (hourInt > 12) ifTrue: [
      aString addAll: (hourInt - 12) _digitsAsString;
              addAll: timeSeparator;
              addAll: min.

      (anArray at: 9) ifTrue: [
        aString addAll: timeSeparator;
                addAll: sec
        ].
      ]
    ifFalse: [
      aString addAll: (hourInt = 0 ifTrue: ['12'] ifFalse: [hour]);
              addAll: timeSeparator;
              addAll: min.

      (anArray at: 9) ifTrue: [
        aString addAll: timeSeparator;
                addAll: sec.
        ].
      ].

    aString addAll: (hourInt >= 12 ifTrue: [' pm'] ifFalse: [' am']).
    ]
  ifFalse: [
    aString addAll: hour;
            addAll: timeSeparator;
            addAll: min.

    (anArray at: 9) ifTrue: [
      aString addAll: timeSeparator;
              addAll: sec.
      ].
    ].
  ].

^ aString
%

category: 'Formatting'
method: ObsoleteDateTime
_monthAbbrev: aMonthInt

"Given the month of the year as a SmallInteger, returns a three-letter string
 that is its abbreviation."

|theMonth itsAbbrev|

theMonth := self _monthName: aMonthInt.  "get its full name"
itsAbbrev := String new.
1 to: 3 do: "take the first three letters"
   [:aChar | itsAbbrev := itsAbbrev + (theMonth at: aChar)].
^ itsAbbrev
%

category: 'Formatting'
method: ObsoleteDateTime
_monthName: aMonthInt

"Given the month of the year as a SmallInteger, returns a String that is its
 full name."

^ (MonthNames value) at: aMonthInt
%

category: 'Converting'
method: ObsoleteDateTime
asParts

"Returns an Array of SmallIntegers (year month day hours minutes
 seconds) corresponding to the receiver."

| t |

t := self _yearMonthDay.  "year/month/day"
t addLast: self julianSecond // 3600.  "hours"
t addLast: self julianSecond \\ 3600 // 60.  "minutes"
t addLast: self julianSecond \\ 60.  "seconds"
^ t
%

category: 'Converting'
method: ObsoleteDateTime
asSeconds

"Returns an Integer representing the receiver in units of seconds
 since 1 March 1583."

^ self julianDay - 2299298 * 86400 + self julianSecond

  "86400 = seconds/24-hour day"
  "converts to March 1, 1583, Gregorian"
%

category: 'Comparing'
method: ObsoleteDateTime
< aObsoleteDateTime

"Returns true if the receiver represents a ObsoleteDateTime before the argument, false
 if it doesn't.  Generates an error if the argument is not a ObsoleteDateTime."

| t |

(self julianDay = (t := aObsoleteDateTime julianDay))
   ifTrue: [ ^ self julianSecond < aObsoleteDateTime julianSecond ].
^ self julianDay < t
%

category: 'Comparing'
method: ObsoleteDateTime
= aObsoleteDateTime

"Returns true if the receiver represents the same ObsoleteDateTime as the argument,
 false if it doesn't."

aObsoleteDateTime class == self class ifFalse: [ ^false ].
^ (self julianDay = aObsoleteDateTime julianDay) _and:
   [self julianSecond = aObsoleteDateTime julianSecond ]
%

category: 'Comparing'
method: ObsoleteDateTime
hash

"Returns an Integer hash code for the receiver."

^ ((self julianDay hash) bitShift: -1) bitXor: (self julianSecond hash)
%

category: 'Comparing'
method: ObsoleteDateTime
> aObsoleteDateTime

"Returns true if the receiver represents a ObsoleteDateTime after the argument, false
 if it doesn't.  Generates an error if the argument is not a ObsoleteDateTime."

| t |

(self julianDay = (t := aObsoleteDateTime julianDay))
   ifTrue: [ ^self julianSecond > aObsoleteDateTime julianSecond ].
^self julianDay > t
%

category: 'Arithmetic'
method: ObsoleteDateTime
addDays: anInteger

"Returns a ObsoleteDateTime anInteger days after the receiver."

^ (self class) _newJulianDay: (self julianDay + anInteger)
                      second: (self julianSecond)
%

category: 'Arithmetic'
method: ObsoleteDateTime
addHours: anInteger

"Returns a ObsoleteDateTime anInteger hours after the receiver."

^ self addSeconds: anInteger * 3600
%

category: 'Arithmetic'
method: ObsoleteDateTime
addMinutes: anInteger

"Returns a ObsoleteDateTime anInteger minutes after the receiver."

^ self addSeconds: anInteger * 60
%

! fix bug 9360
category: 'Arithmetic'
method: ObsoleteDateTime
addMonths: anInteger

"Returns a ObsoleteDateTime anInteger months after the receiver.  This method attempts
 to keep the day of the month the same.  If the new month has fewer days than
 the receiver's original month, the method will truncate to the last day of the
 new month."

| t newMonth newYear |

t := self _yearMonthDay.
newMonth := ((t at: 2) + anInteger) .
newYear := (t at: 1) .
(newMonth == 0) ifTrue:[ newYear := newYear - 1 ].
^ (self class) _newWithYear: newYear
               month: newMonth
               day: (t at: 3)
               seconds: (self julianSecond)
%

category: 'Arithmetic'
method: ObsoleteDateTime
addSeconds: anInteger

"Returns a ObsoleteDateTime anInteger seconds after the receiver."

^ (self class) _newJulianDay: (self julianDay)
                      second: (self julianSecond + anInteger)
%

category: 'Arithmetic'
method: ObsoleteDateTime
addWeeks: anInteger

"Returns a ObsoleteDateTime anInteger weeks after the receiver."

^ self addDays: anInteger * 7
%

category: 'Arithmetic'
method: ObsoleteDateTime
addYears: anInteger

"Returns a ObsoleteDateTime anInteger years after the receiver."

| t |

t := self _yearMonthDay.
^ (self class) _newWithYear: ((t at: 1) + anInteger)
                  month: (t at: 2)
                    day: (t at: 3)
                seconds: (self julianSecond)
%

category: 'Arithmetic'
method: ObsoleteDateTime
subtractDate: aObsoleteDateTime

"Returns the number of days between the receiver and aObsoleteDateTime."

^ (self julianDay - aObsoleteDateTime julianDay) abs
%

category: 'Arithmetic'
method: ObsoleteDateTime
subtractDays: anInteger

"Returns a ObsoleteDateTime anInteger days before the receiver."

^ self addDays: anInteger negated
%

category: 'Arithmetic'
method: ObsoleteDateTime
subtractHours: anInteger

"Returns a ObsoleteDateTime anInteger hours before the receiver."

^ self addSeconds: anInteger * 3600 negated
%

category: 'Arithmetic'
method: ObsoleteDateTime
subtractMinutes: anInteger

"Returns a ObsoleteDateTime anInteger minutes before the receiver."

^ self addSeconds: anInteger * 60 negated
%

category: 'Arithmetic'
method: ObsoleteDateTime
subtractMonths: anInteger

"Returns a ObsoleteDateTime anInteger months before the receiver.  As with addMonths:,
 this method attempts to keep the day of the month the same.  If the new month
 has fewer days than the receiver's original month, the method will truncate to
 the last day of the new month."

^ self addMonths: anInteger negated
%

category: 'Arithmetic'
method: ObsoleteDateTime
subtractSeconds: anInteger

"Returns a ObsoleteDateTime anInteger seconds before the receiver."

^ self addSeconds: anInteger negated
%

category: 'Arithmetic'
method: ObsoleteDateTime
subtractWeeks: anInteger

"Returns a ObsoleteDateTime anInteger weeks before the receiver."

^ self addDays: anInteger * 7 negated
%

category: 'Arithmetic'
method: ObsoleteDateTime
subtractYears: anInteger

"Returns a ObsoleteDateTime anInteger years before the receiver."

^ self addYears: anInteger negated
%

category: 'Formatting'
method: ObsoleteDateTime
US12HrFormat

"Returns a string representation of the receiver in the form `m/d/y hh:mm'
 with 12-hour time representation."

^self asStringUsingFormat: #(2 1 3 $/ 1 2 $: true false true)
%

category: 'Formatting'
method: ObsoleteDateTime
US24HrFormat

"Returns a string representation of the receiver in the form `m/d/y hh:mm'
 with 24-hour time representation."

^self asStringUsingFormat: #(2 1 3 $/ 1 2 $: true false false)
%

category: 'Formatting'
method: ObsoleteDateTime
USDateFormat

"Returns a string representation of the receiver in the form `m/d/y'."

^self asStringUsingFormat: #(2 1 3 $/ 1 2 $: false )
%

category: 'Arithmetic'
method: ObsoleteDateTime
subtractTime: adate

"Subtracts the given ObsoleteDateTime's hours/minutes/seconds from the
 receiver's and returns the result in an Array of #[hours, minutes, seconds]."

| parts h m s |
parts := self asParts.
h := parts at: 4.
m := parts at: 5.
s := parts at: 6.
parts := adate asParts.
s := s - (parts at: 6).
m := m - (parts at: 5).
h := h - (parts at: 4).
s < 0 ifTrue: [
  s := s + 60.
  m := m - 1
].
s > 60 ifTrue: [
  s := s - 60.
  m := m + 1
].
m < 0 ifTrue: [
  m := m + 60.
  h := h - 1
].
m > 60 ifTrue: [
  m := m - 60.
  h := h + 1
].
^#[h, m, s]
%

category: 'Storing and Loading'
classmethod: ObsoleteDateTime
loadFrom: passiveObj

"Reads from passiveObj the passive form of an object with named instance
 variable format.  Converts the object to its active form by loading the
 information into a new instance of the receiver.  Returns the new instance."

^ DateTime loadFrom: passiveObj
%

category: 'Storing and Loading'
method: ObsoleteDateTime
writeTo: passiveObj

"Converts the receiver to its passive form and writes that information on
 passiveObj."

passiveObj writeClass: self class.
self _yearMonthDay do: [:each |  each writeTo: passiveObj].
self julianSecond writeTo: passiveObj.
passiveObj space
%

category: 'Converting'
method: ObsoleteDateTime
asDateTime

"Returns an instance of DateTime with the date and time contained in 
 the receiver."

| aDateTime aTimeZone |

aTimeZone := TimeZone current.
aDateTime := (self transformIntoDateTime) subtractSeconds: (aTimeZone secondsFromGmt).

(aDateTime isDstIn: aTimeZone)
  ifTrue:  [ ^ aDateTime subtractSeconds: (aTimeZone secondsForDst)]
  ifFalse: [ ^ aDateTime ].
%

category: 'Repository Conversion'
method: ObsoleteDateTime
convertToDateTime

"Converts an instance of ObsoleteDateTime (GemStone 4.1 and earlier) to an
 instance of current DateTime.  The object identity is left the same.
 Returns the receiver.

 The receiver is assumed to represent a date and time in the local time
 zone and is converted to a DateTime in Greenwich Mean Time."

| newDt |

newDt := self asDateTime.
newDt become: self.
^ self.
%

category: 'Private'
method: ObsoleteDateTime
transformIntoDateTime

"Returns an instance of DateTime with the date and time contained in 
 the receiver."

^ self transformIntoDateTime: (TimeZone current).
%

! category: 'Private'
! method: ObsoleteDateTime
! transformIntoDateTime: timeZone
! 
! "Returns an instance of DateTime with the date and time contained in 
! the receiver."
! 
! < primitive: 471 >
! self _primitiveFailed: #transformIntoDateTime:
! %

category: 'Repository Conversion'
classmethod: ObsoleteDateTime
_correspondingNewClass

"The class all instances of receiver are converted to during conversion."

(self == ObsoleteDateTime)
  ifTrue: [ ^ DateTime ].

^ self.
%

category: 'New Indexing Comparison'
method: ObsoleteDateTime
_classSortOrdinal

^ 59
%
