Bug 36360

GemBuilder for Smalltalk

5.2.5, 5.2.4, 5.2.3, 5.2.2, 5.2.1, 5.2

VA

5.3, 5.2.6

Replicated DateTimes may adjust for DST a week early

GemStone Server DateTime instances are stored as GMT (UTC) values,
and when they are replicated to the client, they are adjusted to
local time based on the local TimeZone settings on the client
Smalltalk. Under VA, The local TimeZone settings are calculated
based on Windows operating system information.

You must have the Windows operating system patches installed, for
correct information to come from the OS:
  http://support.microsoft.com/kb/931836/

With the Windows patch applied, the data returned from the OS
exposes a bug in GBS.  Given the new OS data, GBS does not
correctly calculate the start or end of DST.  DateTimes in US and
Canadian time zones that are replicated from the server to GBS
during the week before DST begins according to the new rules, will
be incorrectly adjusted as if they were also in DST.

Workaround:

After installing the Windows OS patch, file in the methods below.
You must also execute
  GbsTimeZone current: nil
to allow reinitialization from the OS information.


!GbsTimeZone class publicMethods !

approximateStartDateFrom: aDate
     "given aDate which may be in a special form from MS, return a day from which
     we can later compute the actual start of standard time or the actual dst time by
     getting the previous day of the week (ie Sunday)"

     ^aDate wYear = 0
          ifFalse:
               [Date
                    newDay: aDate wDay
                    monthIndex: aDate wMonth
                    year: aDate wYear]
          ifTrue:
               ["special format "

               | fDate |
               fDate := Date
                              newDay: 1
                              monthIndex: aDate wMonth
                              year: Date today year.
               aDate wDay = 5
                    ifFalse: [fDate addDays: 6 + ((aDate wDay - 1) * 7)]
                    ifTrue: [fDate addDays: fDate daysLeftInMonth]     "per bug 36391-GbsTimeZone instantiates incorrectly on VA"]!

clientDefaultInstance

     "Return an instance of GbsTimeZone automatically initialized from the
      operating system.  If this isn't possible, return nil."

     | tz dst std hasNoDst dstDate stdDate dstWeekDay stdWeekDay |
     (self gbxResolve: #OSTimeZoneInformation) isNil ifTrue: [ ^nil ].
     [
          tz := (self gbxResolve: #OSTimeZoneInformation) new.
          tz getTimeZoneInformation.
          dst := tz DaylightDate.
          std := tz StandardDate.
     ] whenExceptionDo: [ ^nil ].
     hasNoDst := dst wDay = std wDay
          and: [ dst wMonth = std wMonth
          and: [ dst wYear = std wYear ]].
     hasNoDst ifTrue:
          [ ^ self
               secondsFromGMT: tz Bias * -60
               secondsForDST: 0
               dayOfYearForDST: 0
               dayOfWeekForDST: 0
               secondsBeginDST: 0
               dayOfYearForStandard: 0
               dayOfWeekForStandard: 0
               secondsBeginStandard: 0 ].

     "From MSDN : sometimes the timeZone info has a special format for its dates.  If wYear is 0,
     wDayOfWeek represents the day (0-Sunday to 6-Saturday), and wDay represents the week of
     the month (1 to 5 where 5 is always the last).
     ex: wYear = 0, wWeekday = 0, wDay = 5, wMonth = 10 mean the last Sunday of October."

     "Another problem is that for Win Sunday is 0 but it's 7 for others"
     dstWeekDay := dst wDayOfWeek = 0
                                        ifTrue: [7]
                                        ifFalse: [dst wDayOfWeek].
     stdWeekDay := std wDayOfWeek = 0
                                        ifTrue: [7]
                                        ifFalse: [std wDayOfWeek].
     dstDate := self approximateStartDateFrom: dst.
     stdDate := self approximateStartDateFrom: std.
                         
     ^self
          secondsFromGMT: tz Bias * -60
          secondsForDST: tz DaylightBias * -60
          dayOfYearForDST: dstDate dayOfYear - (Date leapYear: dstDate year)
          dayOfWeekForDST: dstWeekDay
          secondsBeginDST: (dst wHour * 60 * 60) + (dst wMinute * 60) + dst wSecond
          dayOfYearForStandard: stdDate dayOfYear - (Date leapYear: stdDate year)
          dayOfWeekForStandard: stdWeekDay
          secondsBeginStandard: (std wHour * 60 * 60) + (std wMinute * 60) + std wSecond
! !


Last updated: 3/7/07