David T. Lewis uploaded a new version of Chronology-Core to project The Trunk: http://source.squeak.org/trunk/Chronology-Core-dtl.85.mcz
==================== Summary ====================
Name: Chronology-Core-dtl.85 Author: dtl Time: 1 July 2023, 9:01:03.976799 pm UUID: bdd66b0f-97e1-4fd5-bca6-4194eaf60096 Ancestors: Chronology-Core-mt.82
Establish protocol for aTimeZone offsetAt: aDateAndTime. Let TimeZone be abstract and let FixedTimeZone implement the previous behavior with offset represented as a constant (no DST transition support). Other packages (e.g. TZ-Olson) may implement concrete TimeZone with DST support.
Save existing TimeZone instances in the package preamble and migrate them to FixedTimeZone in the postscript.
=============== Diff against Chronology-Core-mt.82 ===============
Item was added: + (PackageInfo named: 'Chronology-Core') preamble: '"below, add code to be run before the loading of this package" + + "Remember all instances of TimeZone. These will become FixedTimeZone in the postscript" + TimeZone instSize = 3 ifTrue: [ + Smalltalk at: #TimeZoneInstances put: + (Dictionary newFrom: ( + TimeZone allInstances collect: [:tz | + tz -> { tz offset . tz name . tz abbreviation }]))]. + '!
Item was changed: ----- Method: DateAndTime class>>localOffset: (in category 'squeak protocol') ----- localOffset: aDuration "Override the local time zone (for testing). This disables the #automaticTimezone: preference" + self localTimeZone: (FixedTimeZone offset: aDuration name: 'Local Time (override)' abbreviation: 'LTO'). - self localTimeZone: (TimeZone offset: aDuration name: 'Local Time (override)' abbreviation: 'LTO'). !
Item was changed: ----- Method: DateAndTime class>>now (in category 'ansi protocol') ----- now + "Answer time now as reported by #primitiveUtcWithOffset. If the automaticTimeZone + preference is false, use the offset provided by LocalTimeZone rather than the offset + provided by the primitive." - "Answer time now as reported by #primitiveUtcWithOffset. If the primitive is not - available, answer the Posix epoch GMT."
self automaticTimezone ifTrue: [ ^ self basicNew initializeFromPrimitive ] ifFalse: [ | timeArray | timeArray := Time posixMicrosecondClockWithOffset. ^ self utcMicroseconds: timeArray first offset: self localOffsetSeconds ] !
Item was added: + TimeZone subclass: #FixedTimeZone + instanceVariableNames: 'offset abbreviation name' + classVariableNames: '' + poolDictionaries: 'ChronologyConstants' + category: 'Chronology-Core'! + + !FixedTimeZone commentStamp: 'dtl 6/20/2023 08:07' prior: 0! + FixedTimeZone is a simple class to collect the information identifying a UTC time zone. It is typically used in unit tests to specify specific time zone offsets. + + offset - Duration - the time zone's offset from UTC + abbreviation - String - the abbreviated name for the time zone. + name - String - the name of the time zone. + + StaticTimeZone class >> #timeZones returns an array of the known time zones + StaticTimeZone class >> #default returns the default time zone (Greenwich Mean Time) + !
Item was added: + ----- Method: FixedTimeZone class>>allTimeZones (in category 'accessing') ----- + allTimeZones + + ^ self timeZones , self timeZonesDST!
Item was added: + ----- Method: FixedTimeZone class>>default (in category 'accessing') ----- + default + "Answer the default time zone - GMT" + + ^ self timeZones detect: [ :tz | tz offset = Duration zero ]!
Item was added: + ----- Method: FixedTimeZone class>>offset:name:abbreviation: (in category 'instance creation') ----- + offset: aDuration name: aName abbreviation: anAbbreviation + + ^ self new + offset: aDuration; + name: aName; + abbreviation: anAbbreviation; + yourself + !
Item was added: + ----- Method: FixedTimeZone class>>timeZones (in category 'accessing') ----- + timeZones + ^{ + self offset: 0 hours name: 'Universal Time' abbreviation: 'UTC'. + self offset: 0 hours name: 'Greenwich Mean Time' abbreviation: 'GMT'. + self offset: 1 hours name: 'Central European Time' abbreviation: 'CET'. + self offset: 2 hours name: 'South African Standard Time' abbreviation: 'SAST'. + self offset: -8 hours name: 'Pacific Standard Time' abbreviation: 'PST'. + self offset: -7 hours name: 'Mountain Standard Time' abbreviation: 'MST'. + self offset: -6 hours name: 'Central Standard Time' abbreviation: 'CST'. + self offset: -5 hours name: 'Eastern Standard Time' abbreviation: 'EST'. + }!
Item was added: + ----- Method: FixedTimeZone class>>timeZonesDST (in category 'accessing') ----- + timeZonesDST + ^{ + self offset: 1 hours name: 'British Summer Time' abbreviation: 'BST'. + self offset: 2 hours name: 'Central European Summer Time' abbreviation: 'CEST'. + self offset: -7 hours name: 'Pacific Daylight Time' abbreviation: 'PDT'. + self offset: -6 hours name: 'Mountain Daylight Time' abbreviation: 'MDT'. + self offset: -5 hours name: 'Central Daylight Time' abbreviation: 'CDT'. + self offset: -4 hours name: 'Eastern Daylight Time' abbreviation: 'EDT'. + }!
Item was added: + ----- Method: FixedTimeZone>>abbreviation (in category 'accessing') ----- + abbreviation + + ^ abbreviation!
Item was added: + ----- Method: FixedTimeZone>>abbreviation: (in category 'accessing') ----- + abbreviation: aString + + abbreviation := aString!
Item was added: + ----- Method: FixedTimeZone>>name (in category 'accessing') ----- + name + + ^ name!
Item was added: + ----- Method: FixedTimeZone>>name: (in category 'accessing') ----- + name: aString + + name := aString!
Item was added: + ----- Method: FixedTimeZone>>offset: (in category 'accessing') ----- + offset: aDuration + + offset := aDuration + !
Item was added: + ----- Method: FixedTimeZone>>offsetAt: (in category 'accessing') ----- + offsetAt: dateAndTime + "A FixedTimeZone has a constant offset, ignoring daylight savings time transitions" + + ^ offset + !
Item was added: + ----- Method: FixedTimeZone>>printOn: (in category 'private') ----- + printOn: aStream + + super printOn: aStream. + aStream + nextPut: $(; + nextPutAll: self abbreviation; + nextPut: $)!
Item was changed: Object subclass: #TimeZone + instanceVariableNames: '' - instanceVariableNames: 'offset abbreviation name' classVariableNames: '' poolDictionaries: 'ChronologyConstants' category: 'Chronology-Core'!
+ !TimeZone commentStamp: 'dtl 6/15/2023 22:27' prior: 0! + A TimeZone answers the UTC offset for a DateAndTime based on local rules for a geographic region. For each regional time zone, the UTC offset varies as a function of the DateAndTime, notably in support of daylight savings time changes. The UTC offset for a TimeZone also may change over time as local rules are updated for various regions and political jurisdictions. - !TimeZone commentStamp: 'dtl 7/11/2009 15:03' prior: 0! - TimeZone is a simple class to colect the information identifying a UTC time zone.
+ Concrete subclasses are expected to implement UTC offset rules. The simple case of FixedTimeZone implements a time zone with constant offset, which is useful for unit test support.! - offset - Duration - the time zone's offset from UTC - abbreviation - String - the abbreviated name for the time zone. - name - String - the name of the time zone. - - TimeZone class >> #timeZones returns an array of the known time zones - TimeZone class >> #default returns the default time zone (Grenwich Mean Time) - !
Item was added: + ----- Method: TimeZone class>>allForOffset: (in category 'accessing') ----- + allForOffset: aDuration + + ^ self allTimeZones select: [:ea | ea offset = aDuration]!
Item was added: + ----- Method: TimeZone class>>allTimeZones (in category 'accessing') ----- + allTimeZones + "Various concrete implementations may be available. These may include a + simple StaticTimeZone or e.g. the TZ-Olson time zone tables with daylight + savings time offset transitions." + + ^ self allSubclasses + inject: OrderedCollection new + into: [ :result :cls | + (cls class includesLocalSelector: #allTimeZones) + ifTrue: [result addAll: cls allTimeZones]. + result]. + !
Item was changed: ----- Method: TimeZone class>>default (in category 'accessing') ----- default "Answer the default time zone - GMT"
+ ^ FixedTimeZone default! - ^ self timeZones detect: [ :tz | tz offset = Duration zero ]!
Item was removed: - ----- Method: TimeZone class>>offset:name:abbreviation: (in category 'instance creation') ----- - offset: aDuration name: aName abbreviation: anAbbreviation - - ^ self new - offset: aDuration; - name: aName; - abbreviation: anAbbreviation; - yourself - !
Item was removed: - ----- Method: TimeZone class>>timeZones (in category 'accessing') ----- - timeZones - ^{ - self offset: 0 hours name: 'Universal Time' abbreviation: 'UTC'. - self offset: 0 hours name: 'Greenwich Mean Time' abbreviation: 'GMT'. - self offset: 1 hours name: 'Central European Time' abbreviation: 'CET'. - self offset: 2 hours name: 'South African Standard Time' abbreviation: 'SAST'. - self offset: -8 hours name: 'Pacific Standard Time' abbreviation: 'PST'. - self offset: -7 hours name: 'Mountain Standard Time' abbreviation: 'MST'. - self offset: -6 hours name: 'Central Standard Time' abbreviation: 'CST'. - self offset: -5 hours name: 'Eastern Standard Time' abbreviation: 'EST'. - }!
Item was removed: - ----- Method: TimeZone class>>timeZonesDST (in category 'accessing') ----- - timeZonesDST - ^{ - self offset: 1 hours name: 'British Summer Time' abbreviation: 'BST'. - self offset: 2 hours name: 'Central European Summer Time' abbreviation: 'CEST'. - self offset: -7 hours name: 'Pacific Daylight Time' abbreviation: 'PDT'. - self offset: -6 hours name: 'Mountain Daylight Time' abbreviation: 'MDT'. - self offset: -5 hours name: 'Central Daylight Time' abbreviation: 'CDT'. - self offset: -4 hours name: 'Eastern Daylight Time' abbreviation: 'EDT'. - }!
Item was changed: ----- Method: TimeZone>>abbreviation (in category 'accessing') ----- abbreviation
+ ^ self subclassResponsibility! - ^ abbreviation!
Item was removed: - ----- Method: TimeZone>>abbreviation: (in category 'accessing') ----- - abbreviation: aString - - abbreviation := aString!
Item was changed: ----- Method: TimeZone>>name (in category 'accessing') ----- name
+ ^ self subclassResponsibility! - ^ name!
Item was removed: - ----- Method: TimeZone>>name: (in category 'accessing') ----- - name: aString - - name := aString!
Item was changed: ----- Method: TimeZone>>offset (in category 'accessing') ----- offset + "Answer the current offset"
+ ^ self offsetAt: DateAndTime basicNew initializeFromPrimitive - ^ offset !
Item was removed: - ----- Method: TimeZone>>offset: (in category 'accessing') ----- - offset: aDuration - - offset := aDuration - !
Item was added: + ----- Method: TimeZone>>offsetAt: (in category 'accessing') ----- + offsetAt: dateAndTime + + ^ self subclassResponsibility + !
Item was removed: - ----- Method: TimeZone>>printOn: (in category 'private') ----- - printOn: aStream - - super printOn: aStream. - aStream - nextPut: $(; - nextPutAll: self abbreviation; - nextPut: $)!
Item was changed: + (PackageInfo named: 'Chronology-Core') postscript: '"Let all old instances of TimeZone become FixedTimeZone" + (Smalltalk globals removeKey: #TimeZoneInstances ifAbsent: []) + ifNotNil: [ :instanceData | + instanceData keysAndValuesDo: [ :instance :data | | newInstance | + newInstance := FixedTimeZone + offset: data first + name: data second + abbreviation: data third. + instance becomeForward: newInstance ]]. + '! - (PackageInfo named: 'Chronology-Core') postscript: 'Smalltalk removeFromStartUpList: DateAndTime'!
packages@lists.squeakfoundation.org