!=========================================================================
! Copyright (C) VMware, Inc. 1986-2011.  All Rights Reserved.
!
! $Id: obstimezone.gs,v 1.4 2008-01-09 22:50:13 stever Exp $
!
! Superclass Hierarchy:
!   ObsoleteTimeZone, Object.
!
!=========================================================================

removeallmethods ObsoleteTimeZone
removeallclassmethods ObsoleteTimeZone

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

| doc txt |
doc := GsClassDocumentation newForClass: self.

txt := (GsDocText new) details:
'A ObsoleteTimeZone represents the policy for converting Greenwich Mean Time to local
 time.'.
doc documentClassWith: txt.

txt := (GsDocText new) details:
'The offset from Greenwich Mean Time in seconds (SmallInteger). Time zones 
 east of the Greenwich meridian have positive values, those west of the 
 meridian have negative values'.
doc documentInstVar: #secondsFromGMT with: txt.

txt := (GsDocText new) details:
'The number of seconds for daylight savings correction (SmallInteger).
 If this is zero, there is no daylight savings in the time zone represented by 
 this instance of ObsoleteTimeZone.'.
doc documentInstVar: #secondsForDst with: txt.

txt := (GsDocText new) details:
'The number of seconds after midnight when daylight savings starts 
 (SmallInteger).'.
doc documentInstVar: #timeStartDst with: txt.

txt := (GsDocText new) details:
'The day of the week when daylight savings time starts (Symbol). Usually 
 #Sunday.'.
doc documentInstVar: #weekDayStartDst with: txt.

txt := (GsDocText new) details:
'The day of the year (SmallInteger) by which daylight savings should have 
 started. Daylight savings actually starts on the preceeding weekDayStartDst 
 (see above).'.
doc documentInstVar: #dayStartDst with: txt.

txt := (GsDocText new) details:
'The day of the year (SmallInteger) by which daylight savings should have 
 ended. Daylight savings actually ends on the preceeding weekDayStartDst
 (see above).'.
doc documentInstVar: #dayEndDst with: txt.

txt := (GsDocText new) details:
'The year in which daylight savings policy came into effect (SmallInteger).'.
doc documentInstVar: #yearStartDst with: txt.

txt := (GsDocText new) details:
'The string to be printed to identify the time zone when daylight savings 
 program is not in effect (String).'.
doc documentInstVar: #standardPrintString with: txt.

txt := (GsDocText new) details:
'The string to be printed to identify the time zone when daylight savings 
 program is in effect (String).'.
doc documentInstVar: #dstPrintString with: txt.

self description: doc.
%

category: 'Instance Creation'
classmethod: ObsoleteTimeZone
new

"Disallowed.  To create a new ObsoleteTimeZone, use another instance creation method."

self shouldNotImplement: #new
%

category: 'Instance Creation'
classmethod: ObsoleteTimeZone
migrateNew

"Override default migrateNew behavior with #_basicNew."

^ self _basicNew
%

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

"Disallowed.  To create a new ObsoleteTimeZone, use another instance creation method."

self shouldNotImplement: #new:
%

category: 'Instance Creation'
classmethod: ObsoleteTimeZone
timeDifferenceHrs: hours dstHrs: dstHrs atTimeHrs: startTimeHrs 
fromDayNum: startDay toDayNum: endDay on: nameOfDay beginning: startYear
stdPrintString: stdString dstPrintString: dstString

"Returns a new instance of ObsoleteTimeZone with the given parameters. The parameters
 are as follows:

	timeDifferenceHrs: time difference from GMT in hours. Regions east of
	Greenwich meridian have positive time differences values, those west 
	of the meridian  have negative values.

	dstHrs: daylight savings adjustment in hours.

	atTimeHrs: number of hours after midnight when daylight savings starts.
	E.g. 2 implies 2.00 AM.

        on: name of the day on which daylight savings starts. E.g. #Sunday.

	fromDayNum: daylight savings program should have started by this
        day. It actually starts on the preceeding nameOfDay (usually Sunday).

	toDayNum: daylight savings should have ended by this day. It actually
	ends on the preceeding nameOfDay (usually Sunday).

	beginning: The year in which daylight savings program started.

	stdPrintString: The string to be used for printing during standard
	time.

	dstString: The string to be used for printing during daylight savings
	time."

^ self _timeDifferenceSec: hours * 3600 
    dstSec: dstHrs * 3600 
    atTimeSec: startTimeHrs * 3600
    fromDayNum: startDay toDayNum: endDay 
    on: nameOfDay beginning: startYear 
    stdPrintString: stdString dstPrintString: dstString
%

category: 'Instance Creation'
classmethod: ObsoleteTimeZone
_timeDifferenceSec: secs dstSec: dstSec atTimeSec: startTimeSec
fromDayNum: startDay toDayNum: endDay on: nameOfDay beginning: startYear
stdPrintString: stdString dstPrintString: dstString

| aTimeZone |

aTimeZone := super new.
aTimeZone secondsFromGmt: secs ;
          secondsForDst: dstSec ;
          timeStartDst: startTimeSec ;
	  weekDayStartDst: nameOfDay;
	  dayStartDst: startDay;
	  dayEndDst: endDay;
	  yearStartDst: startYear;
	  standardPrintString: stdString;
	  dstPrintString: dstString.

aTimeZone dstStartTimeList: (IntegerKeyValueDictionary new);
          dstEndTimeList: (IntegerKeyValueDictionary new).

^ aTimeZone.
%

category: 'Instance Creation'
classmethod: ObsoleteTimeZone
timeDifferenceMin: minutes dstMin: dstMins atTimeMin: startTimeMins 
fromDayNum: startDay toDayNum: endDay on: nameOfDay beginning: startYear
stdPrintString: stdString dstPrintString: dstString

"Returns a new instance of ObsoleteTimeZone with the given parameters. The parameters
 are as follows:

        timeDifferenceMin: time difference from GMT in minutes. Regions east of
        Greenwich meridian have positive time differences values, those west 
        of the meridian  have negative values.

        dstMin: daylight savings adjustment in minutes.

        atTimeMin: number of hours after midnight when daylight savings starts.
        E.g. 120 implies 2.00 AM.

        on: name of the day on which daylight savings starts. E.g. #Sunday.

	fromDayNum: daylight savings program should have started by this
        day. It actually starts on the preceeding nameOfDay (usually Sunday).

	toDayNum: daylight savings should have ended by this day. It actually
	ends on the preceeding nameOfDay (usually Sunday).

        beginning: The year in which daylight savings program started.

        stdPrintString: The string to be used for printing during standard
        time.

        dstString: The string to be used for printing during daylight savings
        time."

^ self _timeDifferenceSec: minutes * 60
    dstSec: dstMins * 60
    atTimeSec: startTimeMins * 60
    fromDayNum: startDay toDayNum: endDay 
    on: nameOfDay beginning: startYear 
    stdPrintString: stdString dstPrintString: dstString
%

category: 'Updating'
classmethod: ObsoleteTimeZone
for: aPlace put: aTimeZone

"Stores aTimeZone as the ObsoleteTimeZone object identified with a particular
 place. A single ObsoleteTimeZone can be associated with any number of places.
 E.g. ObsoleteTimeZone for: #Berlin put: aTimeZone; ObsoleteTimeZone for: #Germany
 put: aTimeZone. Returns aTimeZone."

^ TimeZones at: aPlace put: aTimeZone.
%

category: 'Accessing'
classmethod: ObsoleteTimeZone
for: aPlace

"Returns a ObsoleteTimeZone object for the specified place if it has been defined
 and stored in the class. Returns nil if it is not defined. 
 E.g. ObsoleteTimeZone for: #Montreal."

^ TimeZones at: aPlace otherwise: nil.
%

category: 'Accessing'
classmethod: ObsoleteTimeZone
default: aTimeZone

"Makes the specified time zone the default time zone. Returns aTimeZone.
 Must be SystemUser to do so."

aTimeZone _validateClass: ObsoleteTimeZone.
System myUserProfile userId = 'SystemUser' ifFalse:[
  self error:'instance only modifiable by SystemUser'.
  self _uncontinuableError .
].
Default := aTimeZone.
^ aTimeZone.
%

category: 'Updating'
classmethod: ObsoleteTimeZone
default

"Returns the system wide default ObsoleteTimeZone."

^ Default
%

category: 'Session Control'
method: ObsoleteTimeZone
installAsCurrentTimeZone

"Sets the receiver as the current session's current Timezone. Returns the
 receiver."

System _sessionStateAt: 17 put: self.
^ self.
%

category: 'Session Control'
classmethod: ObsoleteTimeZone
current

"Returns the current session's current ObsoleteTimeZone. E.g. ObsoleteTimeZone current."

^ System _sessionStateAt: 17.
%

category: 'Inquiries'
method: ObsoleteTimeZone
dateTimeClass

"Returns the class of DateTime objects that are to be created by the
 various methods in this class."

^ DateTime
%

category: 'Private'
method: ObsoleteTimeZone
startOfDstFor: aYear

| aDateTime theDay aDate |

"Check if the datetime object for the start of dst already exists."
aDateTime := dstStartTimeList at: aYear otherwise: nil.
(aDateTime ~~ nil)
  ifTrue: [ ^ aDateTime ].

"Adjust for leap year if necessary"
((dayStartDst > 60) and: [ Date isLeap: aYear ])
  ifTrue: [ theDay := dayStartDst + 1 ]
  ifFalse: [ theDay := dayStartDst ].

"If this falls on dayOfWeek, then the day has been found. Otherwise, find
 the previous dayOfWeek."
aDate := (Date newDay: theDay + 1 year: aYear) previous: weekDayStartDst.

"create a dateTime and store it the receiver for future accesses."
aDateTime := self dateTimeClass newGmtWithDate: aDate 
                  seconds: (timeStartDst - secondsFromGmt) 
                  timeZone: self.
dstStartTimeList at: aYear put: aDateTime .

^ aDateTime.
%

category: 'Private'
method: ObsoleteTimeZone
endOfDstFor: aYear

| aDateTime theDay aDate |

"Check if the datetime object for the start of dst already exists."
aDateTime := dstEndTimeList at: aYear otherwise: nil.
(aDateTime ~~ nil)
  ifTrue: [ ^ aDateTime ].


"Adjust for leap year if necessary"
((dayStartDst > 60) and: [ Date isLeap: aYear ])
  ifTrue: [ theDay := dayEndDst + 1 ]
  ifFalse: [ theDay := dayEndDst ].

"If this falls on dayOfWeek, then the day has been found. Otherwise, find
 the previous dayOfWeek."
aDate := (Date newDay: theDay + 1 year: aYear) previous: weekDayStartDst.

"create a dateTime and store it the receiver for future accesses."
aDateTime := self dateTimeClass newGmtWithDate: aDate
                  seconds: (timeStartDst - secondsForDst - secondsFromGmt) 
                  timeZone: self.
dstEndTimeList at: aYear put: aDateTime .

^ aDateTime.
%

category: 'Updating'
method: ObsoleteTimeZone
secondsFromGmt: aSmallInteger

"Sets the secondsFromGmt instance variable. Returns the receiver."

secondsFromGmt := aSmallInteger.
^ self
%

category: 'Updating'
method: ObsoleteTimeZone
secondsForDst: aSmallInteger

"Sets the secondsForDst instance variable. Returns the receiver."

secondsForDst := aSmallInteger.
^ self
%

category: 'Updating'
method: ObsoleteTimeZone
timeStartDst: aSmallInteger

"Sets the timeStartDst instance variable. Returns the receiver."

timeStartDst := aSmallInteger.
^ self
%

category: 'Updating'
method: ObsoleteTimeZone
weekDayStartDst: aSymbol

"Sets the weekDayStartDst instance variable. Returns the receiver."

weekDayStartDst := aSymbol.
^ self
%

category: 'Updating'
method: ObsoleteTimeZone
dayStartDst: aSmallInteger

"Sets the dayStartDst instance variable. Returns the receiver."

dayStartDst := aSmallInteger.
^ self
%

category: 'Updating'
method: ObsoleteTimeZone
dayEndDst: aSmallInteger

"Sets the dayEndDst instance variable. Returns the receiver."

dayEndDst := aSmallInteger.
^ self
%

category: 'Updating'
method: ObsoleteTimeZone
yearStartDst: aSmallInteger

"Sets the yearStartDst instance variable. Returns the receiver."

yearStartDst := aSmallInteger.
^ self
%

category: 'Updating'
method: ObsoleteTimeZone
standardPrintString: aString

"Sets the standardPrintString instance variable. Returns the receiver."

standardPrintString := aString.
^ self
%

category: 'Updating'
method: ObsoleteTimeZone
dstPrintString: aString

"Sets the dstPrintString instance variable. Returns the receiver."

dstPrintString := aString.
^ self
%

category: 'Updating'
method: ObsoleteTimeZone
dstStartTimeList: aDictionary

"Sets the dstStartTimeList instance variable. Returns the receiver."

dstStartTimeList := aDictionary.
^ self
%

category: 'Updating'
method: ObsoleteTimeZone
dstEndTimeList: aDictionary

"Sets the dstEndTimeList instance variable. Returns the receiver."

dstEndTimeList := aDictionary.
^ self
%

category: 'Accessing'
method: ObsoleteTimeZone
secondsFromGmt

"Returns the secondsFromGmt instance variable." 

^ secondsFromGmt 
%

category: 'Accessing'
method: ObsoleteTimeZone
secondsForDst

"Returns the secondsForDst instance variable." 

^ secondsForDst 
%

category: 'Accessing'
method: ObsoleteTimeZone
timeStartDst

"Returns the timeStartDst instance variable." 

^ timeStartDst 
%

category: 'Accessing'
method: ObsoleteTimeZone
weekDayStartDst

"Returns the weekDayStartDst instance variable." 

^ weekDayStartDst 
%

category: 'Accessing'
method: ObsoleteTimeZone
dayStartDst

"Returns the dayStartDst instance variable." 

^ dayStartDst 
%

category: 'Accessing'
method: ObsoleteTimeZone
dayEndDst

"Returns the dayEndDst instance variable." 

^ dayEndDst 
%

category: 'Accessing'
method: ObsoleteTimeZone
yearStartDst

"Returns the yearStartDst instance variable." 

^ yearStartDst 
%

category: 'Accessing'
method: ObsoleteTimeZone
standardPrintString

"Returns the standardPrintString instance variable." 

^ standardPrintString 
%

category: 'Accessing'
method: ObsoleteTimeZone
dstPrintString

"Returns the dstPrintString instance variable." 

^ dstPrintString 
%

category: 'Accessing'
method: ObsoleteTimeZone
dstStartTimeList

"Returns the dstStartTimeList instance variable." 

^ dstStartTimeList 
%

category: 'Accessing'
method: ObsoleteTimeZone
dstEndTimeList

"Returns the dstEndTimeList instance variable." 

^ dstEndTimeList 
%

category: 'Storing and Loading'
method: ObsoleteTimeZone
shouldWriteInstVar: instVarName
 
"Returns whether the given instance variable should be written out."

"exclude the ditionaries"

instVarName == #dstStartTimeList ifTrue:[ ^ false ].
instVarName == #dstEndTimeList ifTrue:[ ^ false ].
^ true
%

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

"(R) Creates and returns an active instance of the receiver from the passive 
 form of the object."

| inst secFromGmt secForDst timeStartDst weekDayStart dayStart 
  dayEnd yearStart stdPrint dstPrint marker |

marker := passiveObj objectPositionMarker.

passiveObj readNamedIV.
secFromGmt := passiveObj ivValue.
passiveObj readNamedIV.
secForDst := passiveObj ivValue.
passiveObj readNamedIV.
timeStartDst := passiveObj ivValue.
passiveObj readNamedIV.
weekDayStart := passiveObj ivValue.
passiveObj readNamedIV.
dayStart := passiveObj ivValue.
passiveObj readNamedIV.
dayEnd := passiveObj ivValue.
passiveObj readNamedIV.
yearStart := passiveObj ivValue.
passiveObj readNamedIV.
stdPrint := passiveObj ivValue.
passiveObj readNamedIV.
dstPrint := passiveObj ivValue.

passiveObj skipNamedInstVars.

inst := self _timeDifferenceSec: secFromGmt
    dstSec: secForDst
    atTimeSec: timeStartDst
    fromDayNum: dayStart toDayNum: dayEnd 
    on: weekDayStart beginning: yearStart
    stdPrintString: stdPrint dstPrintString: dstPrint .

passiveObj hasRead: inst marker: marker .
^inst.
%
