Levente Uzonyi uploaded a new version of Chronology-Core to project The Trunk: http://source.squeak.org/trunk/Chronology-Core-ul.55.mcz
==================== Summary ====================
Name: Chronology-Core-ul.55 Author: ul Time: 31 May 2020, 12:10:20.250221 am UUID: ea36b609-177c-405a-b64e-9988deb3d26e Ancestors: Chronology-Core-nice.52
Automatically update the time zone cached by the VM every 30 minutes: - copied and modified Eliot's accessor to primitive 243 to do the actual updating (Time class >> #primitiveUpdateTimeZone) - update happens when Time class >> #posixMicrosecondClockWithOffset or Time class >> #posixMicrosecondClockWithOffset: are sent. Other low-level accessors of the VM time zone are not updating the cached time zone value (e.g. Time class >> #localMicrosecondClockPrimitive) - actual update happens in Time class >> #updateTimeZoneCacheAt: - postscript activates the update mechanism which can be turned off by evaluating [ Time classPool at: #UpdateVMTimeZoneCacheAt put: nil ]
Other changes: - do not send Time class >> #initialize from DateAndTime class >> #startUp:. Let Time have its own #startUp: method instead. Postscript adds Time to the startUpList before DateAndTime. - do not send super initialize from DateAndTime class >> #initialize - do not send #automaticTimezone to DateAndTime on startup, because that's just an accessor with no side effects - do not overwrite set variables in Time class >> #initialize - assert that the value passed to Time class >> #clockPolicy: is one of the known values
=============== Diff against Chronology-Core-nice.52 ===============
Item was changed: ----- Method: DateAndTime class>>initialize (in category 'initialize-release') ----- initialize
- super initialize. - ClockProvider := Time. PosixEpochJulianDays := 2440588. InitializeFromPrimitive := self canInitializeFromPrimitive. Smalltalk addToStartUpList: self. self startUp: true !
Item was changed: ----- Method: DateAndTime class>>startUp: (in category 'system startup') ----- startUp: startingAfresh "Set local timezone" startingAfresh ifTrue: [InitializeFromPrimitive := self canInitializeFromPrimitive. Time initialize. "set LastClockTick to 0". + self now]! - self now. - self automaticTimezone]!
Item was changed: Magnitude subclass: #Time instanceVariableNames: 'seconds nanos' + classVariableNames: 'ClockPolicy HighResClockTicksPerMillisecond LastClockTick UpdateVMTimeZoneCacheAt UseHighResClockForTiming' - classVariableNames: 'ClockPolicy HighResClockTicksPerMillisecond LastClockTick UseHighResClockForTiming' poolDictionaries: 'ChronologyConstants' category: 'Chronology-Core'!
!Time commentStamp: 'dew 10/23/2004 17:58' prior: 0! This represents a particular point in time during any given day. For example, '5:19:45 pm'.
If you need a point in time on a particular day, use DateAndTime. If you need a duration of time, use Duration. !
Item was changed: ----- Method: Time class>>clockPolicy: (in category 'class initialization') ----- clockPolicy: aSymbol "When sequencial calls are made to DateAndTime now, it may be desirable to force the system clock to be monotonic, and it may be desirable for the clock to appear to be strictly increasing with no repeat values. The ClockPolicy identifies which of several possible strategies to use.
Allowable values are #acceptPlatformTime #monotonicAllowDuplicates #monotonicForceMicrosecondIncrement #monotonicForceNanosecondIncrement "
+ self assert: ( + #( + acceptPlatformTime + monotonicAllowDuplicates + monotonicForceMicrosecondIncrement + monotonicForceNanosecondIncrement) includes: aSymbol). ClockPolicy := aSymbol!
Item was changed: ----- Method: Time class>>initialize (in category 'class initialization') ----- initialize + " self initialize " - "Time initialize"
+ LastClockTick ifNil: [ LastClockTick := 0 ]. - "Initialize at startup time to protect for the case of an image saved with bad LastClockTick" - LastClockTick := 0. + HighResClockTicksPerMillisecond ifNil: [ HighResClockTicksPerMillisecond := 0 ]. - HighResClockTicksPerMillisecond := 0.
+ ClockPolicy ifNil: [ + "self clockPolicy: #acceptPlatformTime." + self clockPolicy: #monotonicAllowDuplicates. + "self clockPolicy: #monotonicForceMicrosecondIncrement." + "self clockPolicy: #monotonicForceNanosecondIncrement." ]! - "self clockPolicy: #acceptPlatformTime." - self clockPolicy: #monotonicAllowDuplicates. - "self clockPolicy: #monotonicForceMicrosecondIncrement." - "self clockPolicy: #monotonicForceNanosecondIncrement." - !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset (in category 'clock') ----- posixMicrosecondClockWithOffset "Answer an array with local microseconds since the Posix epoch and the current seconds offset from GMT in the local time zone."
+ | array posixUtcValue | - | array utcValue | array := self primPosixMicrosecondClockWithOffset. + posixUtcValue := array at: 1. + (self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time zone may have changed: fetch again." + self primPosixMicrosecondClockWithOffset: array. + posixUtcValue := array at: 1 ]. ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ array] . [#monotonicAllowDuplicates] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := array at: 1. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [array at: 1 put: LastClockTick]] . [#monotonicForceMicrosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := array at: 1. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + 1. "add one microsecond" array at: 1 put: LastClockTick]] . [#monotonicForceNanosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := array at: 1. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + (1 / 1000). "add one nanosecond" array at: 1 put: LastClockTick]] } otherwise: []. + ^array! - ^array - - !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset: (in category 'clock') ----- posixMicrosecondClockWithOffset: aDateAndTime "Initialize aDateAndTime initialized with local microseconds since the Posix epoch and the current seconds offset from GMT in the local time zone."
+ | posixUtcValue | - - | utcValue | self primPosixMicrosecondClockWithOffset: aDateAndTime. + posixUtcValue := aDateAndTime utcMicroseconds. + (self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time zone may have changed: fetch again." + self primPosixMicrosecondClockWithOffset: aDateAndTime . + posixUtcValue := aDateAndTime utcMicroseconds ]. ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ aDateAndTime] . [#monotonicAllowDuplicates] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := aDateAndTime utcMicroseconds. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [aDateAndTime utcMicroseconds: LastClockTick]] . [#monotonicForceMicrosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := aDateAndTime utcMicroseconds. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + 1. "add one microsecond" aDateAndTime utcMicroseconds: LastClockTick]] . [#monotonicForceNanosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := aDateAndTime utcMicroseconds. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + (1 / 1000). "add one nanosecond" aDateAndTime utcMicroseconds: LastClockTick]] } otherwise: []. + ^aDateAndTime! - ^aDateAndTime - !
Item was added: + ----- Method: Time class>>primitiveUpdateTimeZone (in category 'clock') ----- + primitiveUpdateTimeZone + "Update the VMs notion of the current time zone. The VM sets its notion + of the time zone once at start-up. If one wants the VM to keep its notion + up-to-date arrange to invoke this primitive periodically." + + <primitive: 243> + ^nil "Return nil instead of self to indicate that the primitive failed."!
Item was added: + ----- Method: Time class>>startUp: (in category 'system startup') ----- + startUp: resuming + + resuming ifTrue: [ + LastClockTick := 0 ]!
Item was added: + ----- Method: Time class>>updateTimeZoneCacheAt: (in category 'clock') ----- + updateTimeZoneCacheAt: posixUtcMicrosecondClock + "Tell the VM to update its cached time zone value if the POSIX UTC time reached the valute stored in UpdateVMTimeZoneCacheAt has been reached. Assume that posixUtcMicrosecondClock is an integer with the current POSIX UTC microsecond clock value. Return true when the cache was updated to indicate that the time zone may have changed." + + | updateInterval | + UpdateVMTimeZoneCacheAt ifNil: [ + "Automatic update is disabled." + ^false ]. + posixUtcMicrosecondClock < UpdateVMTimeZoneCacheAt ifTrue: [ ^false ]. + self primitiveUpdateTimeZone ifNil: [ + "The primitive failed." + ^false ]. + updateInterval := 1800000000. "This could be a preference but 30 minutes matches all upcoming DST change times." + UpdateVMTimeZoneCacheAt := posixUtcMicrosecondClock // updateInterval + 1 * updateInterval "Round up posixUtcMicrosecondClock to the next multiple of updateInterval.". + ^true!
Item was changed: + (PackageInfo named: 'Chronology-Core') postscript: '"Make sure UpdateVMTimeZoneCacheAt of Time is initialized." + Time classPool at: #UpdateVMTimeZoneCacheAt put: 0. + "Separated Time''s startup duties from DateAndTime." + Smalltalk addToStartUpList: Time before: DateAndTime'! - (PackageInfo named: 'Chronology-Core') postscript: 'DateAndTime startUp: true. - HashedCollection rehashAll. - '!
Hi Levente,
Automatically update the time zone cached by the VM every 30 minutes
In which scenario is a clock helpful that takes half an hour to set itself correctly?
Best, Christoph
________________________________ Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von commits@source.squeak.org commits@source.squeak.org Gesendet: Sonntag, 31. Mai 2020 00:12:42 An: squeak-dev@lists.squeakfoundation.org; packages@lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Chronology-Core-ul.55.mcz
Levente Uzonyi uploaded a new version of Chronology-Core to project The Trunk: http://source.squeak.org/trunk/Chronology-Core-ul.55.mcz
==================== Summary ====================
Name: Chronology-Core-ul.55 Author: ul Time: 31 May 2020, 12:10:20.250221 am UUID: ea36b609-177c-405a-b64e-9988deb3d26e Ancestors: Chronology-Core-nice.52
Automatically update the time zone cached by the VM every 30 minutes: - copied and modified Eliot's accessor to primitive 243 to do the actual updating (Time class >> #primitiveUpdateTimeZone) - update happens when Time class >> #posixMicrosecondClockWithOffset or Time class >> #posixMicrosecondClockWithOffset: are sent. Other low-level accessors of the VM time zone are not updating the cached time zone value (e.g. Time class >> #localMicrosecondClockPrimitive) - actual update happens in Time class >> #updateTimeZoneCacheAt: - postscript activates the update mechanism which can be turned off by evaluating [ Time classPool at: #UpdateVMTimeZoneCacheAt put: nil ]
Other changes: - do not send Time class >> #initialize from DateAndTime class >> #startUp:. Let Time have its own #startUp: method instead. Postscript adds Time to the startUpList before DateAndTime. - do not send super initialize from DateAndTime class >> #initialize - do not send #automaticTimezone to DateAndTime on startup, because that's just an accessor with no side effects - do not overwrite set variables in Time class >> #initialize - assert that the value passed to Time class >> #clockPolicy: is one of the known values
=============== Diff against Chronology-Core-nice.52 ===============
Item was changed: ----- Method: DateAndTime class>>initialize (in category 'initialize-release') ----- initialize
- super initialize. - ClockProvider := Time. PosixEpochJulianDays := 2440588. InitializeFromPrimitive := self canInitializeFromPrimitive. Smalltalk addToStartUpList: self. self startUp: true !
Item was changed: ----- Method: DateAndTime class>>startUp: (in category 'system startup') ----- startUp: startingAfresh "Set local timezone" startingAfresh ifTrue: [InitializeFromPrimitive := self canInitializeFromPrimitive. Time initialize. "set LastClockTick to 0". + self now]! - self now. - self automaticTimezone]!
Item was changed: Magnitude subclass: #Time instanceVariableNames: 'seconds nanos' + classVariableNames: 'ClockPolicy HighResClockTicksPerMillisecond LastClockTick UpdateVMTimeZoneCacheAt UseHighResClockForTiming' - classVariableNames: 'ClockPolicy HighResClockTicksPerMillisecond LastClockTick UseHighResClockForTiming' poolDictionaries: 'ChronologyConstants' category: 'Chronology-Core'!
!Time commentStamp: 'dew 10/23/2004 17:58' prior: 0! This represents a particular point in time during any given day. For example, '5:19:45 pm'.
If you need a point in time on a particular day, use DateAndTime. If you need a duration of time, use Duration. !
Item was changed: ----- Method: Time class>>clockPolicy: (in category 'class initialization') ----- clockPolicy: aSymbol "When sequencial calls are made to DateAndTime now, it may be desirable to force the system clock to be monotonic, and it may be desirable for the clock to appear to be strictly increasing with no repeat values. The ClockPolicy identifies which of several possible strategies to use.
Allowable values are #acceptPlatformTime #monotonicAllowDuplicates #monotonicForceMicrosecondIncrement #monotonicForceNanosecondIncrement "
+ self assert: ( + #( + acceptPlatformTime + monotonicAllowDuplicates + monotonicForceMicrosecondIncrement + monotonicForceNanosecondIncrement) includes: aSymbol). ClockPolicy := aSymbol!
Item was changed: ----- Method: Time class>>initialize (in category 'class initialization') ----- initialize + " self initialize " - "Time initialize"
+ LastClockTick ifNil: [ LastClockTick := 0 ]. - "Initialize at startup time to protect for the case of an image saved with bad LastClockTick" - LastClockTick := 0.
+ HighResClockTicksPerMillisecond ifNil: [ HighResClockTicksPerMillisecond := 0 ]. - HighResClockTicksPerMillisecond := 0.
+ ClockPolicy ifNil: [ + "self clockPolicy: #acceptPlatformTime." + self clockPolicy: #monotonicAllowDuplicates. + "self clockPolicy: #monotonicForceMicrosecondIncrement." + "self clockPolicy: #monotonicForceNanosecondIncrement." ]! - "self clockPolicy: #acceptPlatformTime." - self clockPolicy: #monotonicAllowDuplicates. - "self clockPolicy: #monotonicForceMicrosecondIncrement." - "self clockPolicy: #monotonicForceNanosecondIncrement." - !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset (in category 'clock') ----- posixMicrosecondClockWithOffset "Answer an array with local microseconds since the Posix epoch and the current seconds offset from GMT in the local time zone."
+ | array posixUtcValue | - | array utcValue | array := self primPosixMicrosecondClockWithOffset. + posixUtcValue := array at: 1. + (self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time zone may have changed: fetch again." + self primPosixMicrosecondClockWithOffset: array. + posixUtcValue := array at: 1 ]. ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ array] . [#monotonicAllowDuplicates] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := array at: 1. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [array at: 1 put: LastClockTick]] . [#monotonicForceMicrosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := array at: 1. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + 1. "add one microsecond" array at: 1 put: LastClockTick]] . [#monotonicForceNanosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := array at: 1. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + (1 / 1000). "add one nanosecond" array at: 1 put: LastClockTick]] } otherwise: []. + ^array! - ^array - - !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset: (in category 'clock') ----- posixMicrosecondClockWithOffset: aDateAndTime "Initialize aDateAndTime initialized with local microseconds since the Posix epoch and the current seconds offset from GMT in the local time zone."
+ | posixUtcValue | - - | utcValue | self primPosixMicrosecondClockWithOffset: aDateAndTime. + posixUtcValue := aDateAndTime utcMicroseconds. + (self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time zone may have changed: fetch again." + self primPosixMicrosecondClockWithOffset: aDateAndTime . + posixUtcValue := aDateAndTime utcMicroseconds ]. ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ aDateAndTime] . [#monotonicAllowDuplicates] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := aDateAndTime utcMicroseconds. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [aDateAndTime utcMicroseconds: LastClockTick]] . [#monotonicForceMicrosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := aDateAndTime utcMicroseconds. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + 1. "add one microsecond" aDateAndTime utcMicroseconds: LastClockTick]] . [#monotonicForceNanosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := aDateAndTime utcMicroseconds. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + (1 / 1000). "add one nanosecond" aDateAndTime utcMicroseconds: LastClockTick]] } otherwise: []. + ^aDateAndTime! - ^aDateAndTime - !
Item was added: + ----- Method: Time class>>primitiveUpdateTimeZone (in category 'clock') ----- + primitiveUpdateTimeZone + "Update the VMs notion of the current time zone. The VM sets its notion + of the time zone once at start-up. If one wants the VM to keep its notion + up-to-date arrange to invoke this primitive periodically." + + <primitive: 243> + ^nil "Return nil instead of self to indicate that the primitive failed."!
Item was added: + ----- Method: Time class>>startUp: (in category 'system startup') ----- + startUp: resuming + + resuming ifTrue: [ + LastClockTick := 0 ]!
Item was added: + ----- Method: Time class>>updateTimeZoneCacheAt: (in category 'clock') ----- + updateTimeZoneCacheAt: posixUtcMicrosecondClock + "Tell the VM to update its cached time zone value if the POSIX UTC time reached the valute stored in UpdateVMTimeZoneCacheAt has been reached. Assume that posixUtcMicrosecondClock is an integer with the current POSIX UTC microsecond clock value. Return true when the cache was updated to indicate that the time zone may have changed." + + | updateInterval | + UpdateVMTimeZoneCacheAt ifNil: [ + "Automatic update is disabled." + ^false ]. + posixUtcMicrosecondClock < UpdateVMTimeZoneCacheAt ifTrue: [ ^false ]. + self primitiveUpdateTimeZone ifNil: [ + "The primitive failed." + ^false ]. + updateInterval := 1800000000. "This could be a preference but 30 minutes matches all upcoming DST change times." + UpdateVMTimeZoneCacheAt := posixUtcMicrosecondClock // updateInterval + 1 * updateInterval "Round up posixUtcMicrosecondClock to the next multiple of updateInterval.". + ^true!
Item was changed: + (PackageInfo named: 'Chronology-Core') postscript: '"Make sure UpdateVMTimeZoneCacheAt of Time is initialized." + Time classPool at: #UpdateVMTimeZoneCacheAt put: 0. + "Separated Time''s startup duties from DateAndTime." + Smalltalk addToStartUpList: Time before: DateAndTime'! - (PackageInfo named: 'Chronology-Core') postscript: 'DateAndTime startUp: true. - HashedCollection rehashAll. - '!
Hi Christoph,
On Fri, 5 Jun 2020, Thiede, Christoph wrote:
Hi Levente,
Automatically update the time zone cached by the VM every 30 minutes
In which scenario is a clock helpful that takes half an hour to set itself correctly?
What's your use case where doing it more often would be beneficial?
Levente
Best, Christoph
Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von commits@source.squeak.org commits@source.squeak.org Gesendet: Sonntag, 31. Mai 2020 00:12:42 An: squeak-dev@lists.squeakfoundation.org; packages@lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Chronology-Core-ul.55.mcz Levente Uzonyi uploaded a new version of Chronology-Core to project The Trunk: http://source.squeak.org/trunk/Chronology-Core-ul.55.mcz
==================== Summary ====================
Name: Chronology-Core-ul.55 Author: ul Time: 31 May 2020, 12:10:20.250221 am UUID: ea36b609-177c-405a-b64e-9988deb3d26e Ancestors: Chronology-Core-nice.52
Automatically update the time zone cached by the VM every 30 minutes:
- copied and modified Eliot's accessor to primitive 243 to do the actual updating (Time class >> #primitiveUpdateTimeZone)
- update happens when Time class >> #posixMicrosecondClockWithOffset or Time class >> #posixMicrosecondClockWithOffset: are sent. Other low-level accessors of the VM time zone are not updating the cached time zone value (e.g.
Time class >> #localMicrosecondClockPrimitive)
- actual update happens in Time class >> #updateTimeZoneCacheAt:
- postscript activates the update mechanism which can be turned off by evaluating [ Time classPool at: #UpdateVMTimeZoneCacheAt put: nil ]
Other changes:
- do not send Time class >> #initialize from DateAndTime class >> #startUp:. Let Time have its own #startUp: method instead. Postscript adds Time to the startUpList before DateAndTime.
- do not send super initialize from DateAndTime class >> #initialize
- do not send #automaticTimezone to DateAndTime on startup, because that's just an accessor with no side effects
- do not overwrite set variables in Time class >> #initialize
- assert that the value passed to Time class >> #clockPolicy: is one of the known values
=============== Diff against Chronology-Core-nice.52 ===============
Item was changed: ----- Method: DateAndTime class>>initialize (in category 'initialize-release') ----- initialize - super initialize.
ClockProvider := Time. PosixEpochJulianDays := 2440588. InitializeFromPrimitive := self canInitializeFromPrimitive. Smalltalk addToStartUpList: self. self startUp: true !
Item was changed: ----- Method: DateAndTime class>>startUp: (in category 'system startup') ----- startUp: startingAfresh "Set local timezone" startingAfresh ifTrue: [InitializeFromPrimitive := self canInitializeFromPrimitive. Time initialize. "set LastClockTick to 0". + self now]! - self now. - self automaticTimezone]!
Item was changed: Magnitude subclass: #Time instanceVariableNames: 'seconds nanos' + classVariableNames: 'ClockPolicy HighResClockTicksPerMillisecond LastClockTick UpdateVMTimeZoneCacheAt UseHighResClockForTiming' - classVariableNames: 'ClockPolicy HighResClockTicksPerMillisecond LastClockTick UseHighResClockForTiming' poolDictionaries: 'ChronologyConstants' category: 'Chronology-Core'! !Time commentStamp: 'dew 10/23/2004 17:58' prior: 0! This represents a particular point in time during any given day. For example, '5:19:45 pm'. If you need a point in time on a particular day, use DateAndTime. If you need a duration of time, use Duration. !
Item was changed: ----- Method: Time class>>clockPolicy: (in category 'class initialization') ----- clockPolicy: aSymbol "When sequencial calls are made to DateAndTime now, it may be desirable to force the system clock to be monotonic, and it may be desirable for the clock to appear to be strictly increasing with no repeat values. The ClockPolicy identifies which of several possible strategies to use. Allowable values are #acceptPlatformTime #monotonicAllowDuplicates #monotonicForceMicrosecondIncrement #monotonicForceNanosecondIncrement " + self assert: ( + #( + acceptPlatformTime + monotonicAllowDuplicates + monotonicForceMicrosecondIncrement + monotonicForceNanosecondIncrement) includes: aSymbol). ClockPolicy := aSymbol!
Item was changed: ----- Method: Time class>>initialize (in category 'class initialization') ----- initialize + " self initialize " - "Time initialize" + LastClockTick ifNil: [ LastClockTick := 0 ]. - "Initialize at startup time to protect for the case of an image saved with bad LastClockTick" - LastClockTick := 0. + HighResClockTicksPerMillisecond ifNil: [ HighResClockTicksPerMillisecond := 0 ]. - HighResClockTicksPerMillisecond := 0. + ClockPolicy ifNil: [ + "self clockPolicy: #acceptPlatformTime." + self clockPolicy: #monotonicAllowDuplicates. + "self clockPolicy: #monotonicForceMicrosecondIncrement." + "self clockPolicy: #monotonicForceNanosecondIncrement." ]! - "self clockPolicy: #acceptPlatformTime." - self clockPolicy: #monotonicAllowDuplicates. - "self clockPolicy: #monotonicForceMicrosecondIncrement." - "self clockPolicy: #monotonicForceNanosecondIncrement."
- !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset (in category 'clock') ----- posixMicrosecondClockWithOffset "Answer an array with local microseconds since the Posix epoch and the current seconds offset from GMT in the local time zone." + | array posixUtcValue | - | array utcValue | array := self primPosixMicrosecondClockWithOffset. + posixUtcValue := array at: 1. + (self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time zone may have changed: fetch again." + self primPosixMicrosecondClockWithOffset: array. + posixUtcValue := array at: 1 ]. ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ array] . [#monotonicAllowDuplicates] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := array at: 1. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [array at: 1 put: LastClockTick]] . [#monotonicForceMicrosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := array at: 1. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + 1. "add one microsecond" array at: 1 put: LastClockTick]] . [#monotonicForceNanosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := array at: 1. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + (1 / 1000). "add one nanosecond" array at: 1 put: LastClockTick]] } otherwise: []. + ^array! - ^array
- !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset: (in category 'clock') ----- posixMicrosecondClockWithOffset: aDateAndTime "Initialize aDateAndTime initialized with local microseconds since the Posix epoch and the current seconds offset from GMT in the local time zone." + | posixUtcValue |
- | utcValue | self primPosixMicrosecondClockWithOffset: aDateAndTime. + posixUtcValue := aDateAndTime utcMicroseconds. + (self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time zone may have changed: fetch again." + self primPosixMicrosecondClockWithOffset: aDateAndTime . + posixUtcValue := aDateAndTime utcMicroseconds ]. ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ aDateAndTime] . [#monotonicAllowDuplicates] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := aDateAndTime utcMicroseconds. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [aDateAndTime utcMicroseconds: LastClockTick]] . [#monotonicForceMicrosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := aDateAndTime utcMicroseconds. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + 1. "add one microsecond" aDateAndTime utcMicroseconds: LastClockTick]] . [#monotonicForceNanosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := aDateAndTime utcMicroseconds. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + (1 / 1000). "add one nanosecond" aDateAndTime utcMicroseconds: LastClockTick]] } otherwise: []. + ^aDateAndTime! - ^aDateAndTime
- !
Item was added:
- ----- Method: Time class>>primitiveUpdateTimeZone (in category 'clock') -----
- primitiveUpdateTimeZone
+ "Update the VMs notion of the current time zone. The VM sets its notion + of the time zone once at start-up. If one wants the VM to keep its notion + up-to-date arrange to invoke this primitive periodically." + + <primitive: 243> + ^nil "Return nil instead of self to indicate that the primitive failed."!
Item was added:
- ----- Method: Time class>>startUp: (in category 'system startup') -----
- startUp: resuming
+ resuming ifTrue: [ + LastClockTick := 0 ]!
Item was added:
- ----- Method: Time class>>updateTimeZoneCacheAt: (in category 'clock') -----
- updateTimeZoneCacheAt: posixUtcMicrosecondClock
+ "Tell the VM to update its cached time zone value if the POSIX UTC time reached the valute stored in UpdateVMTimeZoneCacheAt has been reached. Assume that posixUtcMicrosecondClock is an integer with the current POSIX UTC microsecond clock value. Return true when the cache was updated to indicate that the time zone may have changed."
+ | updateInterval | + UpdateVMTimeZoneCacheAt ifNil: [ + "Automatic update is disabled." + ^false ]. + posixUtcMicrosecondClock < UpdateVMTimeZoneCacheAt ifTrue: [ ^false ]. + self primitiveUpdateTimeZone ifNil: [ + "The primitive failed." + ^false ]. + updateInterval := 1800000000. "This could be a preference but 30 minutes matches all upcoming DST change times." + UpdateVMTimeZoneCacheAt := posixUtcMicrosecondClock // updateInterval + 1 * updateInterval "Round up posixUtcMicrosecondClock to the next multiple of updateInterval.". + ^true!
Item was changed:
- (PackageInfo named: 'Chronology-Core') postscript: '"Make sure UpdateVMTimeZoneCacheAt of Time is initialized."
- Time classPool at: #UpdateVMTimeZoneCacheAt put: 0.
- "Separated Time''s startup duties from DateAndTime."
- Smalltalk addToStartUpList: Time before: DateAndTime'!
- (PackageInfo named: 'Chronology-Core') postscript: 'DateAndTime startUp: true.
- HashedCollection rehashAll.
- '!
Hi Levente,
What's your use case where doing it more often would be beneficial?
When I travel into another timezone, I would not suspect my image to take 30 minutes to show the right time again. My android clock updates within seconds. http://www.hpi.de/
Best, Christoph ________________________________ Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Levente Uzonyi leves@caesar.elte.hu Gesendet: Freitag, 5. Juni 2020 13:56:37 An: The general-purpose Squeak developers list Cc: packages@lists.squeakfoundation.org Betreff: Re: [squeak-dev] The Trunk: Chronology-Core-ul.55.mcz
Hi Christoph,
On Fri, 5 Jun 2020, Thiede, Christoph wrote:
Hi Levente,
Automatically update the time zone cached by the VM every 30 minutes
In which scenario is a clock helpful that takes half an hour to set itself correctly?
What's your use case where doing it more often would be beneficial?
Levente
Best, Christoph
Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von commits@source.squeak.org commits@source.squeak.org Gesendet: Sonntag, 31. Mai 2020 00:12:42 An: squeak-dev@lists.squeakfoundation.org; packages@lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Chronology-Core-ul.55.mcz Levente Uzonyi uploaded a new version of Chronology-Core to project The Trunk: http://source.squeak.org/trunk/Chronology-Core-ul.55.mcz
==================== Summary ====================
Name: Chronology-Core-ul.55 Author: ul Time: 31 May 2020, 12:10:20.250221 am UUID: ea36b609-177c-405a-b64e-9988deb3d26e Ancestors: Chronology-Core-nice.52
Automatically update the time zone cached by the VM every 30 minutes:
- copied and modified Eliot's accessor to primitive 243 to do the actual updating (Time class >> #primitiveUpdateTimeZone)
- update happens when Time class >> #posixMicrosecondClockWithOffset or Time class >> #posixMicrosecondClockWithOffset: are sent. Other low-level accessors of the VM time zone are not updating the cached time zone value (e.g.
Time class >> #localMicrosecondClockPrimitive)
- actual update happens in Time class >> #updateTimeZoneCacheAt:
- postscript activates the update mechanism which can be turned off by evaluating [ Time classPool at: #UpdateVMTimeZoneCacheAt put: nil ]
Other changes:
- do not send Time class >> #initialize from DateAndTime class >> #startUp:. Let Time have its own #startUp: method instead. Postscript adds Time to the startUpList before DateAndTime.
- do not send super initialize from DateAndTime class >> #initialize
- do not send #automaticTimezone to DateAndTime on startup, because that's just an accessor with no side effects
- do not overwrite set variables in Time class >> #initialize
- assert that the value passed to Time class >> #clockPolicy: is one of the known values
=============== Diff against Chronology-Core-nice.52 ===============
Item was changed: ----- Method: DateAndTime class>>initialize (in category 'initialize-release') ----- initialize
super initialize.
!ClockProvider := Time. PosixEpochJulianDays := 2440588. InitializeFromPrimitive := self canInitializeFromPrimitive. Smalltalk addToStartUpList: self. self startUp: true
Item was changed: ----- Method: DateAndTime class>>startUp: (in category 'system startup') ----- startUp: startingAfresh "Set local timezone" startingAfresh ifTrue: [InitializeFromPrimitive := self canInitializeFromPrimitive. Time initialize. "set LastClockTick to 0".
self now]!
self now.
self automaticTimezone]!
Item was changed: Magnitude subclass: #Time instanceVariableNames: 'seconds nanos'
classVariableNames: 'ClockPolicy HighResClockTicksPerMillisecond LastClockTick UpdateVMTimeZoneCacheAt UseHighResClockForTiming'
classVariableNames: 'ClockPolicy HighResClockTicksPerMillisecond LastClockTick UseHighResClockForTiming' poolDictionaries: 'ChronologyConstants' category: 'Chronology-Core'!
!Time commentStamp: 'dew 10/23/2004 17:58' prior: 0! This represents a particular point in time during any given day. For example, '5:19:45 pm'.
If you need a point in time on a particular day, use DateAndTime. If you need a duration of time, use Duration. !
Item was changed: ----- Method: Time class>>clockPolicy: (in category 'class initialization') ----- clockPolicy: aSymbol "When sequencial calls are made to DateAndTime now, it may be desirable to force the system clock to be monotonic, and it may be desirable for the clock to appear to be strictly increasing with no repeat values. The ClockPolicy identifies which of several possible strategies to use.
Allowable values are #acceptPlatformTime #monotonicAllowDuplicates #monotonicForceMicrosecondIncrement #monotonicForceNanosecondIncrement "
self assert: (
#(
acceptPlatformTime
monotonicAllowDuplicates
monotonicForceMicrosecondIncrement
monotonicForceNanosecondIncrement) includes: aSymbol). ClockPolicy := aSymbol!
Item was changed: ----- Method: Time class>>initialize (in category 'class initialization') ----- initialize
" self initialize "
"Time initialize"
LastClockTick ifNil: [ LastClockTick := 0 ].
"Initialize at startup time to protect for the case of an image saved with bad LastClockTick"
LastClockTick := 0.
HighResClockTicksPerMillisecond ifNil: [ HighResClockTicksPerMillisecond := 0 ].
HighResClockTicksPerMillisecond := 0.
ClockPolicy ifNil: [
"self clockPolicy: #acceptPlatformTime."
self clockPolicy: #monotonicAllowDuplicates.
"self clockPolicy: #monotonicForceMicrosecondIncrement."
"self clockPolicy: #monotonicForceNanosecondIncrement." ]!
"self clockPolicy: #acceptPlatformTime."
self clockPolicy: #monotonicAllowDuplicates.
"self clockPolicy: #monotonicForceMicrosecondIncrement."
"self clockPolicy: #monotonicForceNanosecondIncrement."
- !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset (in category 'clock') ----- posixMicrosecondClockWithOffset "Answer an array with local microseconds since the Posix epoch and the current seconds offset from GMT in the local time zone."
| array posixUtcValue |
| array utcValue | array := self primPosixMicrosecondClockWithOffset.
posixUtcValue := array at: 1.
(self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time zone may have changed: fetch again."
self primPosixMicrosecondClockWithOffset: array.
posixUtcValue := array at: 1 ]. ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ array] . [#monotonicAllowDuplicates] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick := posixUtcValue]
utcValue := array at: 1.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [array at: 1 put: LastClockTick]] . [#monotonicForceMicrosecondIncrement] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick := posixUtcValue]
utcValue := array at: 1.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + 1. "add one microsecond" array at: 1 put: LastClockTick]] . [#monotonicForceNanosecondIncrement] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick := posixUtcValue]
utcValue := array at: 1.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + (1 / 1000). "add one nanosecond" array at: 1 put: LastClockTick]] } otherwise: [].
^array!
^array
- !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset: (in category 'clock') ----- posixMicrosecondClockWithOffset: aDateAndTime "Initialize aDateAndTime initialized with local microseconds since the Posix epoch and the current seconds offset from GMT in the local time zone."
| posixUtcValue |
| utcValue | self primPosixMicrosecondClockWithOffset: aDateAndTime.
posixUtcValue := aDateAndTime utcMicroseconds.
(self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time zone may have changed: fetch again."
self primPosixMicrosecondClockWithOffset: aDateAndTime .
posixUtcValue := aDateAndTime utcMicroseconds ]. ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ aDateAndTime] . [#monotonicAllowDuplicates] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick := posixUtcValue]
utcValue := aDateAndTime utcMicroseconds.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [aDateAndTime utcMicroseconds: LastClockTick]] . [#monotonicForceMicrosecondIncrement] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick := posixUtcValue]
utcValue := aDateAndTime utcMicroseconds.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + 1. "add one microsecond" aDateAndTime utcMicroseconds: LastClockTick]] . [#monotonicForceNanosecondIncrement] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick := posixUtcValue]
utcValue := aDateAndTime utcMicroseconds.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + (1 / 1000). "add one nanosecond" aDateAndTime utcMicroseconds: LastClockTick]] } otherwise: [].
^aDateAndTime!
^aDateAndTime
- !
Item was added:
- ----- Method: Time class>>primitiveUpdateTimeZone (in category 'clock') -----
- primitiveUpdateTimeZone
"Update the VMs notion of the current time zone. The VM sets its notion
of the time zone once at start-up. If one wants the VM to keep its notion
up-to-date arrange to invoke this primitive periodically."
<primitive: 243>
^nil "Return nil instead of self to indicate that the primitive failed."!
Item was added:
- ----- Method: Time class>>startUp: (in category 'system startup') -----
- startUp: resuming
resuming ifTrue: [
LastClockTick := 0 ]!
Item was added:
- ----- Method: Time class>>updateTimeZoneCacheAt: (in category 'clock') -----
- updateTimeZoneCacheAt: posixUtcMicrosecondClock
"Tell the VM to update its cached time zone value if the POSIX UTC time reached the valute stored in UpdateVMTimeZoneCacheAt has been reached. Assume that posixUtcMicrosecondClock is an integer with the current POSIX
UTC microsecond clock value. Return true when the cache was updated to indicate that the time zone may have changed."
| updateInterval |
UpdateVMTimeZoneCacheAt ifNil: [
"Automatic update is disabled."
^false ].
posixUtcMicrosecondClock < UpdateVMTimeZoneCacheAt ifTrue: [ ^false ].
self primitiveUpdateTimeZone ifNil: [
"The primitive failed."
^false ].
updateInterval := 1800000000. "This could be a preference but 30 minutes matches all upcoming DST change times."
UpdateVMTimeZoneCacheAt := posixUtcMicrosecondClock // updateInterval + 1 * updateInterval "Round up posixUtcMicrosecondClock to the next multiple of updateInterval.".
^true!
Item was changed:
- (PackageInfo named: 'Chronology-Core') postscript: '"Make sure UpdateVMTimeZoneCacheAt of Time is initialized."
- Time classPool at: #UpdateVMTimeZoneCacheAt put: 0.
- "Separated Time''s startup duties from DateAndTime."
- Smalltalk addToStartUpList: Time before: DateAndTime'!
- (PackageInfo named: 'Chronology-Core') postscript: 'DateAndTime startUp: true.
- HashedCollection rehashAll.
- '!
Hi Christoph,
On Fri, 5 Jun 2020, Thiede, Christoph wrote:
Hi Levente,
What's your use case where doing it more often would be beneficial?
When I travel into another timezone, I would not suspect my image to take 30 minutes to show the right time again. My android clock updates within seconds.
While the change makes it possible to support that use case, my intention was to make images detect DST changes. By reducing updateInterval to a few seconds, that use case can be supported as well. However, the smaller the value is, the larger the overhead is. But it may still be insignificant.
Levente
Best, Christoph
Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Levente Uzonyi leves@caesar.elte.hu Gesendet: Freitag, 5. Juni 2020 13:56:37 An: The general-purpose Squeak developers list Cc: packages@lists.squeakfoundation.org Betreff: Re: [squeak-dev] The Trunk: Chronology-Core-ul.55.mcz Hi Christoph,
On Fri, 5 Jun 2020, Thiede, Christoph wrote:
Hi Levente,
Automatically update the time zone cached by the VM every 30 minutes
In which scenario is a clock helpful that takes half an hour to set itself correctly?
What's your use case where doing it more often would be beneficial?
Levente
Best, Christoph
Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von commits@source.squeak.org commits@source.squeak.org Gesendet: Sonntag, 31. Mai 2020 00:12:42 An: squeak-dev@lists.squeakfoundation.org; packages@lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Chronology-Core-ul.55.mcz Levente Uzonyi uploaded a new version of Chronology-Core to project The Trunk: http://source.squeak.org/trunk/Chronology-Core-ul.55.mcz
==================== Summary ====================
Name: Chronology-Core-ul.55 Author: ul Time: 31 May 2020, 12:10:20.250221 am UUID: ea36b609-177c-405a-b64e-9988deb3d26e Ancestors: Chronology-Core-nice.52
Automatically update the time zone cached by the VM every 30 minutes:
- copied and modified Eliot's accessor to primitive 243 to do the actual updating (Time class >> #primitiveUpdateTimeZone)
- update happens when Time class >> #posixMicrosecondClockWithOffset or Time class >> #posixMicrosecondClockWithOffset: are sent. Other low-level accessors of the VM time zone are not updating the cached time zone value (e.g.
Time class >> #localMicrosecondClockPrimitive)
- actual update happens in Time class >> #updateTimeZoneCacheAt:
- postscript activates the update mechanism which can be turned off by evaluating [ Time classPool at: #UpdateVMTimeZoneCacheAt put: nil ]
Other changes:
- do not send Time class >> #initialize from DateAndTime class >> #startUp:. Let Time have its own #startUp: method instead. Postscript adds Time to the startUpList before DateAndTime.
- do not send super initialize from DateAndTime class >> #initialize
- do not send #automaticTimezone to DateAndTime on startup, because that's just an accessor with no side effects
- do not overwrite set variables in Time class >> #initialize
- assert that the value passed to Time class >> #clockPolicy: is one of the known values
=============== Diff against Chronology-Core-nice.52 ===============
Item was changed: ----- Method: DateAndTime class>>initialize (in category 'initialize-release') ----- initialize - super initialize.
ClockProvider := Time. PosixEpochJulianDays := 2440588. InitializeFromPrimitive := self canInitializeFromPrimitive. Smalltalk addToStartUpList: self. self startUp: true !
Item was changed: ----- Method: DateAndTime class>>startUp: (in category 'system startup') ----- startUp: startingAfresh "Set local timezone" startingAfresh ifTrue: [InitializeFromPrimitive := self canInitializeFromPrimitive. Time initialize. "set LastClockTick to 0". + self now]! - self now. - self automaticTimezone]!
Item was changed: Magnitude subclass: #Time instanceVariableNames: 'seconds nanos' + classVariableNames: 'ClockPolicy HighResClockTicksPerMillisecond LastClockTick UpdateVMTimeZoneCacheAt UseHighResClockForTiming' - classVariableNames: 'ClockPolicy HighResClockTicksPerMillisecond LastClockTick UseHighResClockForTiming' poolDictionaries: 'ChronologyConstants' category: 'Chronology-Core'! !Time commentStamp: 'dew 10/23/2004 17:58' prior: 0! This represents a particular point in time during any given day. For example, '5:19:45 pm'. If you need a point in time on a particular day, use DateAndTime. If you need a duration of time, use Duration. !
Item was changed: ----- Method: Time class>>clockPolicy: (in category 'class initialization') ----- clockPolicy: aSymbol "When sequencial calls are made to DateAndTime now, it may be desirable to force the system clock to be monotonic, and it may be desirable for the clock to appear to be strictly increasing with no repeat values. The ClockPolicy identifies which of several possible strategies to use. Allowable values are #acceptPlatformTime #monotonicAllowDuplicates #monotonicForceMicrosecondIncrement #monotonicForceNanosecondIncrement " + self assert: ( + #( + acceptPlatformTime + monotonicAllowDuplicates + monotonicForceMicrosecondIncrement + monotonicForceNanosecondIncrement) includes: aSymbol). ClockPolicy := aSymbol!
Item was changed: ----- Method: Time class>>initialize (in category 'class initialization') ----- initialize + " self initialize " - "Time initialize" + LastClockTick ifNil: [ LastClockTick := 0 ]. - "Initialize at startup time to protect for the case of an image saved with bad LastClockTick" - LastClockTick := 0. + HighResClockTicksPerMillisecond ifNil: [ HighResClockTicksPerMillisecond := 0 ]. - HighResClockTicksPerMillisecond := 0. + ClockPolicy ifNil: [ + "self clockPolicy: #acceptPlatformTime." + self clockPolicy: #monotonicAllowDuplicates. + "self clockPolicy: #monotonicForceMicrosecondIncrement." + "self clockPolicy: #monotonicForceNanosecondIncrement." ]! - "self clockPolicy: #acceptPlatformTime." - self clockPolicy: #monotonicAllowDuplicates. - "self clockPolicy: #monotonicForceMicrosecondIncrement." - "self clockPolicy: #monotonicForceNanosecondIncrement."
- !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset (in category 'clock') ----- posixMicrosecondClockWithOffset "Answer an array with local microseconds since the Posix epoch and the current seconds offset from GMT in the local time zone." + | array posixUtcValue | - | array utcValue | array := self primPosixMicrosecondClockWithOffset. + posixUtcValue := array at: 1. + (self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time zone may have changed: fetch again." + self primPosixMicrosecondClockWithOffset: array. + posixUtcValue := array at: 1 ]. ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ array] . [#monotonicAllowDuplicates] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := array at: 1. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [array at: 1 put: LastClockTick]] . [#monotonicForceMicrosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := array at: 1. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + 1. "add one microsecond" array at: 1 put: LastClockTick]] . [#monotonicForceNanosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := array at: 1. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + (1 / 1000). "add one nanosecond" array at: 1 put: LastClockTick]] } otherwise: []. + ^array! - ^array
- !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset: (in category 'clock') ----- posixMicrosecondClockWithOffset: aDateAndTime "Initialize aDateAndTime initialized with local microseconds since the Posix epoch and the current seconds offset from GMT in the local time zone." + | posixUtcValue |
- | utcValue | self primPosixMicrosecondClockWithOffset: aDateAndTime. + posixUtcValue := aDateAndTime utcMicroseconds. + (self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time zone may have changed: fetch again." + self primPosixMicrosecondClockWithOffset: aDateAndTime . + posixUtcValue := aDateAndTime utcMicroseconds ]. ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ aDateAndTime] . [#monotonicAllowDuplicates] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := aDateAndTime utcMicroseconds. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [aDateAndTime utcMicroseconds: LastClockTick]] . [#monotonicForceMicrosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := aDateAndTime utcMicroseconds. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + 1. "add one microsecond" aDateAndTime utcMicroseconds: LastClockTick]] . [#monotonicForceNanosecondIncrement] -> [ + posixUtcValue > LastClockTick + ifTrue: [LastClockTick := posixUtcValue] - utcValue := aDateAndTime utcMicroseconds. - utcValue > LastClockTick - ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + (1 / 1000). "add one nanosecond" aDateAndTime utcMicroseconds: LastClockTick]] } otherwise: []. + ^aDateAndTime! - ^aDateAndTime
- !
Item was added:
- ----- Method: Time class>>primitiveUpdateTimeZone (in category 'clock') -----
- primitiveUpdateTimeZone
+ "Update the VMs notion of the current time zone. The VM sets its notion + of the time zone once at start-up. If one wants the VM to keep its notion + up-to-date arrange to invoke this primitive periodically." + + <primitive: 243> + ^nil "Return nil instead of self to indicate that the primitive failed."!
Item was added:
- ----- Method: Time class>>startUp: (in category 'system startup') -----
- startUp: resuming
+ resuming ifTrue: [ + LastClockTick := 0 ]!
Item was added:
- ----- Method: Time class>>updateTimeZoneCacheAt: (in category 'clock') -----
- updateTimeZoneCacheAt: posixUtcMicrosecondClock
+ "Tell the VM to update its cached time zone value if the POSIX UTC time reached the valute stored in UpdateVMTimeZoneCacheAt has been reached. Assume that posixUtcMicrosecondClock is an integer with the current POSIX UTC microsecond clock value. Return true when the cache was updated to indicate that the time zone may have changed."
+ | updateInterval | + UpdateVMTimeZoneCacheAt ifNil: [ + "Automatic update is disabled." + ^false ]. + posixUtcMicrosecondClock < UpdateVMTimeZoneCacheAt ifTrue: [ ^false ]. + self primitiveUpdateTimeZone ifNil: [ + "The primitive failed." + ^false ]. + updateInterval := 1800000000. "This could be a preference but 30 minutes matches all upcoming DST change times." + UpdateVMTimeZoneCacheAt := posixUtcMicrosecondClock // updateInterval + 1 * updateInterval "Round up posixUtcMicrosecondClock to the next multiple of updateInterval.". + ^true!
Item was changed:
- (PackageInfo named: 'Chronology-Core') postscript: '"Make sure UpdateVMTimeZoneCacheAt of Time is initialized."
- Time classPool at: #UpdateVMTimeZoneCacheAt put: 0.
- "Separated Time''s startup duties from DateAndTime."
- Smalltalk addToStartUpList: Time before: DateAndTime'!
- (PackageInfo named: 'Chronology-Core') postscript: 'DateAndTime startUp: true.
- HashedCollection rehashAll.
- '!
Did anyone try that out in practice? I think am going to create an event in my calendar for 2020-10-25T03:00:00+0001 (time changeover in Germany ...) and will watch the Squeak watch :D
Best,
Christoph
________________________________ Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Levente Uzonyi leves@caesar.elte.hu Gesendet: Freitag, 5. Juni 2020 17:52:18 An: The general-purpose Squeak developers list Cc: packages@lists.squeakfoundation.org Betreff: Re: [squeak-dev] The Trunk: Chronology-Core-ul.55.mcz
Hi Christoph,
On Fri, 5 Jun 2020, Thiede, Christoph wrote:
Hi Levente,
What's your use case where doing it more often would be beneficial?
When I travel into another timezone, I would not suspect my image to take 30 minutes to show the right time again. My android clock updates within seconds.
While the change makes it possible to support that use case, my intention was to make images detect DST changes. By reducing updateInterval to a few seconds, that use case can be supported as well. However, the smaller the value is, the larger the overhead is. But it may still be insignificant.
Levente
Best, Christoph
Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Levente Uzonyi leves@caesar.elte.hu Gesendet: Freitag, 5. Juni 2020 13:56:37 An: The general-purpose Squeak developers list Cc: packages@lists.squeakfoundation.org Betreff: Re: [squeak-dev] The Trunk: Chronology-Core-ul.55.mcz Hi Christoph,
On Fri, 5 Jun 2020, Thiede, Christoph wrote:
Hi Levente,
Automatically update the time zone cached by the VM every 30 minutes
In which scenario is a clock helpful that takes half an hour to set itself correctly?
What's your use case where doing it more often would be beneficial?
Levente
Best, Christoph
Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von commits@source.squeak.org commits@source.squeak.org Gesendet: Sonntag, 31. Mai 2020 00:12:42 An: squeak-dev@lists.squeakfoundation.org; packages@lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Chronology-Core-ul.55.mcz Levente Uzonyi uploaded a new version of Chronology-Core to project The Trunk: http://source.squeak.org/trunk/Chronology-Core-ul.55.mcz
==================== Summary ====================
Name: Chronology-Core-ul.55 Author: ul Time: 31 May 2020, 12:10:20.250221 am UUID: ea36b609-177c-405a-b64e-9988deb3d26e Ancestors: Chronology-Core-nice.52
Automatically update the time zone cached by the VM every 30 minutes:
- copied and modified Eliot's accessor to primitive 243 to do the actual updating (Time class >> #primitiveUpdateTimeZone)
- update happens when Time class >> #posixMicrosecondClockWithOffset or Time class >> #posixMicrosecondClockWithOffset: are sent. Other low-level accessors of the VM time zone are not updating the cached time zone value (e.g.
Time class >> #localMicrosecondClockPrimitive)
- actual update happens in Time class >> #updateTimeZoneCacheAt:
- postscript activates the update mechanism which can be turned off by evaluating [ Time classPool at: #UpdateVMTimeZoneCacheAt put: nil ]
Other changes:
- do not send Time class >> #initialize from DateAndTime class >> #startUp:. Let Time have its own #startUp: method instead. Postscript adds Time to the startUpList before DateAndTime.
- do not send super initialize from DateAndTime class >> #initialize
- do not send #automaticTimezone to DateAndTime on startup, because that's just an accessor with no side effects
- do not overwrite set variables in Time class >> #initialize
- assert that the value passed to Time class >> #clockPolicy: is one of the known values
=============== Diff against Chronology-Core-nice.52 ===============
Item was changed: ----- Method: DateAndTime class>>initialize (in category 'initialize-release') ----- initialize
super initialize.
!ClockProvider := Time. PosixEpochJulianDays := 2440588. InitializeFromPrimitive := self canInitializeFromPrimitive. Smalltalk addToStartUpList: self. self startUp: true
Item was changed: ----- Method: DateAndTime class>>startUp: (in category 'system startup') ----- startUp: startingAfresh "Set local timezone" startingAfresh ifTrue: [InitializeFromPrimitive := self canInitializeFromPrimitive. Time initialize. "set LastClockTick to 0".
self now]!
self now.
self automaticTimezone]!
Item was changed: Magnitude subclass: #Time instanceVariableNames: 'seconds nanos'
classVariableNames: 'ClockPolicy HighResClockTicksPerMillisecond LastClockTick UpdateVMTimeZoneCacheAt UseHighResClockForTiming'
classVariableNames: 'ClockPolicy HighResClockTicksPerMillisecond LastClockTick UseHighResClockForTiming' poolDictionaries: 'ChronologyConstants' category: 'Chronology-Core'!
!Time commentStamp: 'dew 10/23/2004 17:58' prior: 0! This represents a particular point in time during any given day. For example, '5:19:45 pm'.
If you need a point in time on a particular day, use DateAndTime. If you need a duration of time, use Duration. !
Item was changed: ----- Method: Time class>>clockPolicy: (in category 'class initialization') ----- clockPolicy: aSymbol "When sequencial calls are made to DateAndTime now, it may be desirable to force the system clock to be monotonic, and it may be desirable for the clock to appear to be strictly increasing with no repeat values. The ClockPolicy identifies which of several possible strategies to use.
Allowable values are #acceptPlatformTime #monotonicAllowDuplicates #monotonicForceMicrosecondIncrement #monotonicForceNanosecondIncrement "
self assert: (
#(
acceptPlatformTime
monotonicAllowDuplicates
monotonicForceMicrosecondIncrement
monotonicForceNanosecondIncrement) includes: aSymbol). ClockPolicy := aSymbol!
Item was changed: ----- Method: Time class>>initialize (in category 'class initialization') ----- initialize
" self initialize "
"Time initialize"
LastClockTick ifNil: [ LastClockTick := 0 ].
"Initialize at startup time to protect for the case of an image saved with bad LastClockTick"
LastClockTick := 0.
HighResClockTicksPerMillisecond ifNil: [ HighResClockTicksPerMillisecond := 0 ].
HighResClockTicksPerMillisecond := 0.
ClockPolicy ifNil: [
"self clockPolicy: #acceptPlatformTime."
self clockPolicy: #monotonicAllowDuplicates.
"self clockPolicy: #monotonicForceMicrosecondIncrement."
"self clockPolicy: #monotonicForceNanosecondIncrement." ]!
"self clockPolicy: #acceptPlatformTime."
self clockPolicy: #monotonicAllowDuplicates.
"self clockPolicy: #monotonicForceMicrosecondIncrement."
"self clockPolicy: #monotonicForceNanosecondIncrement."
- !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset (in category 'clock') ----- posixMicrosecondClockWithOffset "Answer an array with local microseconds since the Posix epoch and the current seconds offset from GMT in the local time zone."
| array posixUtcValue |
| array utcValue | array := self primPosixMicrosecondClockWithOffset.
posixUtcValue := array at: 1.
(self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time zone may have changed: fetch again."
self primPosixMicrosecondClockWithOffset: array.
posixUtcValue := array at: 1 ]. ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ array] . [#monotonicAllowDuplicates] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick := posixUtcValue]
utcValue := array at: 1.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [array at: 1 put: LastClockTick]] . [#monotonicForceMicrosecondIncrement] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick := posixUtcValue]
utcValue := array at: 1.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + 1. "add one microsecond" array at: 1 put: LastClockTick]] . [#monotonicForceNanosecondIncrement] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick := posixUtcValue]
utcValue := array at: 1.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + (1 / 1000). "add one nanosecond" array at: 1 put: LastClockTick]] } otherwise: [].
^array!
^array
- !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset: (in category 'clock') ----- posixMicrosecondClockWithOffset: aDateAndTime "Initialize aDateAndTime initialized with local microseconds since the Posix epoch and the current seconds offset from GMT in the local time zone."
| posixUtcValue |
| utcValue | self primPosixMicrosecondClockWithOffset: aDateAndTime.
posixUtcValue := aDateAndTime utcMicroseconds.
(self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time zone may have changed: fetch again."
self primPosixMicrosecondClockWithOffset: aDateAndTime .
posixUtcValue := aDateAndTime utcMicroseconds ]. ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ aDateAndTime] . [#monotonicAllowDuplicates] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick := posixUtcValue]
utcValue := aDateAndTime utcMicroseconds.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [aDateAndTime utcMicroseconds: LastClockTick]] . [#monotonicForceMicrosecondIncrement] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick := posixUtcValue]
utcValue := aDateAndTime utcMicroseconds.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + 1. "add one microsecond" aDateAndTime utcMicroseconds: LastClockTick]] . [#monotonicForceNanosecondIncrement] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick := posixUtcValue]
utcValue := aDateAndTime utcMicroseconds.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick := LastClockTick + (1 / 1000). "add one nanosecond" aDateAndTime utcMicroseconds: LastClockTick]] } otherwise: [].
^aDateAndTime!
^aDateAndTime
- !
Item was added:
- ----- Method: Time class>>primitiveUpdateTimeZone (in category 'clock') -----
- primitiveUpdateTimeZone
"Update the VMs notion of the current time zone. The VM sets its notion
of the time zone once at start-up. If one wants the VM to keep its notion
up-to-date arrange to invoke this primitive periodically."
<primitive: 243>
^nil "Return nil instead of self to indicate that the primitive failed."!
Item was added:
- ----- Method: Time class>>startUp: (in category 'system startup') -----
- startUp: resuming
resuming ifTrue: [
LastClockTick := 0 ]!
Item was added:
- ----- Method: Time class>>updateTimeZoneCacheAt: (in category 'clock') -----
- updateTimeZoneCacheAt: posixUtcMicrosecondClock
"Tell the VM to update its cached time zone value if the POSIX UTC time reached the valute stored in UpdateVMTimeZoneCacheAt has been reached. Assume that posixUtcMicrosecondClock is an integer with the current POSIX
UTC microsecond clock value. Return true when the cache was updated to indicate that the time zone may have changed."
| updateInterval |
UpdateVMTimeZoneCacheAt ifNil: [
"Automatic update is disabled."
^false ].
posixUtcMicrosecondClock < UpdateVMTimeZoneCacheAt ifTrue: [ ^false ].
self primitiveUpdateTimeZone ifNil: [
"The primitive failed."
^false ].
updateInterval := 1800000000. "This could be a preference but 30 minutes matches all upcoming DST change times."
UpdateVMTimeZoneCacheAt := posixUtcMicrosecondClock // updateInterval + 1 * updateInterval "Round up posixUtcMicrosecondClock to the next multiple of updateInterval.".
^true!
Item was changed:
- (PackageInfo named: 'Chronology-Core') postscript: '"Make sure UpdateVMTimeZoneCacheAt of Time is initialized."
- Time classPool at: #UpdateVMTimeZoneCacheAt put: 0.
- "Separated Time''s startup duties from DateAndTime."
- Smalltalk addToStartUpList: Time before: DateAndTime'!
- (PackageInfo named: 'Chronology-Core') postscript: 'DateAndTime startUp: true.
- HashedCollection rehashAll.
- '!
On Fri, Jun 5, 2020 at 7:30 PM Thiede, Christoph < Christoph.Thiede@student.hpi.uni-potsdam.de> wrote:
Did anyone try that out in practice? I think am going to create an event in my calendar for 2020-10-25T03:00:00+0001 (time changeover in Germany ...) and will watch the Squeak watch :D
Clock watching party :-D
Cheers, Karl
Best,
Christoph
*Von:* Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im Auftrag von Levente Uzonyi leves@caesar.elte.hu *Gesendet:* Freitag, 5. Juni 2020 17:52:18 *An:* The general-purpose Squeak developers list *Cc:* packages@lists.squeakfoundation.org *Betreff:* Re: [squeak-dev] The Trunk: Chronology-Core-ul.55.mcz
Hi Christoph,
On Fri, 5 Jun 2020, Thiede, Christoph wrote:
Hi Levente,
What's your use case where doing it more often would be beneficial?
When I travel into another timezone, I would not suspect my image to
take 30 minutes to show the right time again. My android clock updates within seconds.
While the change makes it possible to support that use case, my intention was to make images detect DST changes. By reducing updateInterval to a few seconds, that use case can be supported as well. However, the smaller the value is, the larger the overhead is. But it may still be insignificant.
Levente
Best, Christoph
Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im
Auftrag von Levente Uzonyi leves@caesar.elte.hu
Gesendet: Freitag, 5. Juni 2020 13:56:37 An: The general-purpose Squeak developers list Cc: packages@lists.squeakfoundation.org Betreff: Re: [squeak-dev] The Trunk: Chronology-Core-ul.55.mcz Hi Christoph,
On Fri, 5 Jun 2020, Thiede, Christoph wrote:
Hi Levente,
Automatically update the time zone cached by the VM every 30 minutes
In which scenario is a clock helpful that takes half an hour to set
itself correctly?
What's your use case where doing it more often would be beneficial?
Levente
Best, Christoph
Von: Squeak-dev squeak-dev-bounces@lists.squeakfoundation.org im
Auftrag von commits@source.squeak.org commits@source.squeak.org
Gesendet: Sonntag, 31. Mai 2020 00:12:42 An: squeak-dev@lists.squeakfoundation.org;
packages@lists.squeakfoundation.org
Betreff: [squeak-dev] The Trunk: Chronology-Core-ul.55.mcz Levente Uzonyi uploaded a new version of Chronology-Core to project
The Trunk:
http://source.squeak.org/trunk/Chronology-Core-ul.55.mcz
==================== Summary ====================
Name: Chronology-Core-ul.55 Author: ul Time: 31 May 2020, 12:10:20.250221 am UUID: ea36b609-177c-405a-b64e-9988deb3d26e Ancestors: Chronology-Core-nice.52
Automatically update the time zone cached by the VM every 30 minutes:
- copied and modified Eliot's accessor to primitive 243 to do the
actual updating (Time class >> #primitiveUpdateTimeZone)
- update happens when Time class >> #posixMicrosecondClockWithOffset
or Time class >> #posixMicrosecondClockWithOffset: are sent. Other low-level accessors of the VM time zone are not updating the cached time zone value (e.g.
Time class >> #localMicrosecondClockPrimitive)
- actual update happens in Time class >> #updateTimeZoneCacheAt:
- postscript activates the update mechanism which can be turned off by
evaluating [ Time classPool at: #UpdateVMTimeZoneCacheAt put: nil ]
Other changes:
- do not send Time class >> #initialize from DateAndTime class >>
#startUp:. Let Time have its own #startUp: method instead. Postscript adds Time to the startUpList before DateAndTime.
- do not send super initialize from DateAndTime class >> #initialize
- do not send #automaticTimezone to DateAndTime on startup, because
that's just an accessor with no side effects
- do not overwrite set variables in Time class >> #initialize
- assert that the value passed to Time class >> #clockPolicy: is one
of the known values
=============== Diff against Chronology-Core-nice.52 ===============
Item was changed: ----- Method: DateAndTime class>>initialize (in category
'initialize-release') -----
initialize
super initialize.
!ClockProvider := Time. PosixEpochJulianDays := 2440588. InitializeFromPrimitive := self canInitializeFromPrimitive. Smalltalk addToStartUpList: self. self startUp: true
Item was changed: ----- Method: DateAndTime class>>startUp: (in category 'system
startup') -----
startUp: startingAfresh "Set local timezone" startingAfresh ifTrue: [InitializeFromPrimitive := self
canInitializeFromPrimitive.
Time initialize. "set LastClockTick to 0".
self now]!
self now.
self automaticTimezone]!
Item was changed: Magnitude subclass: #Time instanceVariableNames: 'seconds nanos'
classVariableNames: 'ClockPolicy
HighResClockTicksPerMillisecond LastClockTick UpdateVMTimeZoneCacheAt UseHighResClockForTiming'
classVariableNames: 'ClockPolicy
HighResClockTicksPerMillisecond LastClockTick UseHighResClockForTiming'
poolDictionaries: 'ChronologyConstants' category: 'Chronology-Core'!
!Time commentStamp: 'dew 10/23/2004 17:58' prior: 0! This represents a particular point in time during any given day.
For example, '5:19:45 pm'.
If you need a point in time on a particular day, use DateAndTime.
If you need a duration of time, use Duration.
!
Item was changed: ----- Method: Time class>>clockPolicy: (in category 'class
initialization') -----
clockPolicy: aSymbol "When sequencial calls are made to DateAndTime now, it may be
desirable to
force the system clock to be monotonic, and it may be
desirable for the clock
to appear to be strictly increasing with no repeat values.
The ClockPolicy
identifies which of several possible strategies to use. Allowable values are #acceptPlatformTime #monotonicAllowDuplicates #monotonicForceMicrosecondIncrement #monotonicForceNanosecondIncrement "
self assert: (
#(
acceptPlatformTime
monotonicAllowDuplicates
monotonicForceMicrosecondIncrement
monotonicForceNanosecondIncrement) includes:
aSymbol).
ClockPolicy := aSymbol!
Item was changed: ----- Method: Time class>>initialize (in category 'class
initialization') -----
initialize
" self initialize "
"Time initialize"
LastClockTick ifNil: [ LastClockTick := 0 ].
"Initialize at startup time to protect for the case of an
image saved with bad LastClockTick"
LastClockTick := 0.
HighResClockTicksPerMillisecond ifNil: [
HighResClockTicksPerMillisecond := 0 ].
HighResClockTicksPerMillisecond := 0.
ClockPolicy ifNil: [
"self clockPolicy: #acceptPlatformTime."
self clockPolicy: #monotonicAllowDuplicates.
"self clockPolicy:
#monotonicForceMicrosecondIncrement."
"self clockPolicy:
#monotonicForceNanosecondIncrement." ]!
"self clockPolicy: #acceptPlatformTime."
self clockPolicy: #monotonicAllowDuplicates.
"self clockPolicy: #monotonicForceMicrosecondIncrement."
"self clockPolicy: #monotonicForceNanosecondIncrement."
- !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset (in
category 'clock') -----
posixMicrosecondClockWithOffset "Answer an array with local microseconds since the Posix
epoch and the
current seconds offset from GMT in the local time zone."
| array posixUtcValue |
| array utcValue | array := self primPosixMicrosecondClockWithOffset.
posixUtcValue := array at: 1.
(self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time
zone may have changed: fetch again."
self primPosixMicrosecondClockWithOffset: array.
posixUtcValue := array at: 1 ]. ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ array] . [#monotonicAllowDuplicates] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick :=
posixUtcValue]
utcValue := array at: 1.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [array at: 1 put:
LastClockTick]] .
[#monotonicForceMicrosecondIncrement] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick :=
posixUtcValue]
utcValue := array at: 1.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick :=
LastClockTick + 1. "add one microsecond"
array at: 1 put:
LastClockTick]] .
[#monotonicForceNanosecondIncrement] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick :=
posixUtcValue]
utcValue := array at: 1.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick :=
LastClockTick + (1 / 1000). "add one nanosecond"
array at: 1 put:
LastClockTick]]
} otherwise: [].
^array!
^array
- !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset: (in
category 'clock') -----
posixMicrosecondClockWithOffset: aDateAndTime "Initialize aDateAndTime initialized with local microseconds
since the Posix
epoch and the current seconds offset from GMT in the local
time zone."
| posixUtcValue |
| utcValue | self primPosixMicrosecondClockWithOffset: aDateAndTime.
posixUtcValue := aDateAndTime utcMicroseconds.
(self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time
zone may have changed: fetch again."
self primPosixMicrosecondClockWithOffset:
aDateAndTime .
posixUtcValue := aDateAndTime utcMicroseconds ]. ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ aDateAndTime] . [#monotonicAllowDuplicates] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick :=
posixUtcValue]
utcValue := aDateAndTime utcMicroseconds.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [aDateAndTime
utcMicroseconds: LastClockTick]] .
[#monotonicForceMicrosecondIncrement] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick :=
posixUtcValue]
utcValue := aDateAndTime utcMicroseconds.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick :=
LastClockTick + 1. "add one microsecond"
aDateAndTime utcMicroseconds:
LastClockTick]] .
[#monotonicForceNanosecondIncrement] -> [
posixUtcValue > LastClockTick
ifTrue: [LastClockTick :=
posixUtcValue]
utcValue := aDateAndTime utcMicroseconds.
utcValue > LastClockTick
ifTrue: [LastClockTick := utcValue] ifFalse: [LastClockTick :=
LastClockTick + (1 / 1000). "add one nanosecond"
aDateAndTime utcMicroseconds:
LastClockTick]]
} otherwise: [].
^aDateAndTime!
^aDateAndTime
- !
Item was added:
- ----- Method: Time class>>primitiveUpdateTimeZone (in category
'clock') -----
- primitiveUpdateTimeZone
"Update the VMs notion of the current time zone. The VM sets
its notion
of the time zone once at start-up. If one wants the VM to
keep its notion
up-to-date arrange to invoke this primitive periodically."
<primitive: 243>
^nil "Return nil instead of self to indicate that the
primitive failed."!
Item was added:
- ----- Method: Time class>>startUp: (in category 'system startup')
- startUp: resuming
resuming ifTrue: [
LastClockTick := 0 ]!
Item was added:
- ----- Method: Time class>>updateTimeZoneCacheAt: (in category
'clock') -----
- updateTimeZoneCacheAt: posixUtcMicrosecondClock
"Tell the VM to update its cached time zone value if the
POSIX UTC time reached the valute stored in UpdateVMTimeZoneCacheAt has been reached. Assume that posixUtcMicrosecondClock is an integer with the current POSIX
UTC microsecond clock value. Return true when the cache was updated to
indicate that the time zone may have changed."
| updateInterval |
UpdateVMTimeZoneCacheAt ifNil: [
"Automatic update is disabled."
^false ].
posixUtcMicrosecondClock < UpdateVMTimeZoneCacheAt ifTrue: [
^false ].
self primitiveUpdateTimeZone ifNil: [
"The primitive failed."
^false ].
updateInterval := 1800000000. "This could be a preference but
30 minutes matches all upcoming DST change times."
UpdateVMTimeZoneCacheAt := posixUtcMicrosecondClock //
updateInterval + 1 * updateInterval "Round up posixUtcMicrosecondClock to the next multiple of updateInterval.".
^true!
Item was changed:
- (PackageInfo named: 'Chronology-Core') postscript: '"Make sure
UpdateVMTimeZoneCacheAt of Time is initialized."
- Time classPool at: #UpdateVMTimeZoneCacheAt put: 0.
- "Separated Time''s startup duties from DateAndTime."
- Smalltalk addToStartUpList: Time before: DateAndTime'!
- (PackageInfo named: 'Chronology-Core') postscript: 'DateAndTime
startUp: true.
- HashedCollection rehashAll.
- '!
Hi all, hi Levente,
should we maybe reset the timezone cache on start-up of the image, to ensure that a fresh image will always fetch the correct timezone? Or is this already happening and I did not get it from the code? :-)
Best, Christoph
--- Sent from Squeak Inbox Talk
On 2020-05-30T22:12:42+00:00, commits@source.squeak.org wrote:
Levente Uzonyi uploaded a new version of Chronology-Core to project The Trunk: http://source.squeak.org/trunk/Chronology-Core-ul.55.mcz
==================== Summary ====================
Name: Chronology-Core-ul.55 Author: ul Time: 31 May 2020, 12:10:20.250221 am UUID: ea36b609-177c-405a-b64e-9988deb3d26e Ancestors: Chronology-Core-nice.52
Automatically update the time zone cached by the VM every 30 minutes:
- copied and modified Eliot's accessor to primitive 243 to do the actual updating (Time class >> #primitiveUpdateTimeZone)
- update happens when Time class >> #posixMicrosecondClockWithOffset or Time class >> #posixMicrosecondClockWithOffset: are sent. Other low-level accessors of the VM time zone are not updating the cached time zone value (e.g. Time class >> #localMicrosecondClockPrimitive)
- actual update happens in Time class >> #updateTimeZoneCacheAt:
- postscript activates the update mechanism which can be turned off by evaluating [ Time classPool at: #UpdateVMTimeZoneCacheAt put: nil ]
Other changes:
- do not send Time class >> #initialize from DateAndTime class >> #startUp:. Let Time have its own #startUp: method instead. Postscript adds Time to the startUpList before DateAndTime.
- do not send super initialize from DateAndTime class >> #initialize
- do not send #automaticTimezone to DateAndTime on startup, because that's just an accessor with no side effects
- do not overwrite set variables in Time class >> #initialize
- assert that the value passed to Time class >> #clockPolicy: is one of the known values
=============== Diff against Chronology-Core-nice.52 ===============
Item was changed: ----- Method: DateAndTime class>>initialize (in category 'initialize-release') ----- initialize
- super initialize.
ClockProvider := Time. PosixEpochJulianDays := 2440588. InitializeFromPrimitive := self canInitializeFromPrimitive. Smalltalk addToStartUpList: self. self startUp: true !
Item was changed: ----- Method: DateAndTime class>>startUp: (in category 'system startup') ----- startUp: startingAfresh "Set local timezone" startingAfresh ifTrue: [InitializeFromPrimitive := self canInitializeFromPrimitive. Time initialize. "set LastClockTick to 0".
- self now]!
- self now.
- self automaticTimezone]!
Item was changed: Magnitude subclass: #Time instanceVariableNames: 'seconds nanos'
- classVariableNames: 'ClockPolicy HighResClockTicksPerMillisecond LastClockTick UpdateVMTimeZoneCacheAt UseHighResClockForTiming'
- classVariableNames: 'ClockPolicy HighResClockTicksPerMillisecond LastClockTick UseHighResClockForTiming'
poolDictionaries: 'ChronologyConstants' category: 'Chronology-Core'!
!Time commentStamp: 'dew 10/23/2004 17:58' prior: 0! This represents a particular point in time during any given day. For example, '5:19:45 pm'.
If you need a point in time on a particular day, use DateAndTime. If you need a duration of time, use Duration. !
Item was changed: ----- Method: Time class>>clockPolicy: (in category 'class initialization') ----- clockPolicy: aSymbol "When sequencial calls are made to DateAndTime now, it may be desirable to force the system clock to be monotonic, and it may be desirable for the clock to appear to be strictly increasing with no repeat values. The ClockPolicy identifies which of several possible strategies to use.
Allowable values are #acceptPlatformTime #monotonicAllowDuplicates #monotonicForceMicrosecondIncrement #monotonicForceNanosecondIncrement "
- self assert: (
- #(
- acceptPlatformTime
- monotonicAllowDuplicates
- monotonicForceMicrosecondIncrement
- monotonicForceNanosecondIncrement) includes: aSymbol).
ClockPolicy := aSymbol!
Item was changed: ----- Method: Time class>>initialize (in category 'class initialization') ----- initialize
- " self initialize "
- "Time initialize"
- LastClockTick ifNil: [ LastClockTick := 0 ].
- "Initialize at startup time to protect for the case of an image saved with bad LastClockTick"
- LastClockTick := 0.
- HighResClockTicksPerMillisecond ifNil: [ HighResClockTicksPerMillisecond := 0 ].
- HighResClockTicksPerMillisecond := 0.
- ClockPolicy ifNil: [
- "self clockPolicy: #acceptPlatformTime."
- self clockPolicy: #monotonicAllowDuplicates.
- "self clockPolicy: #monotonicForceMicrosecondIncrement."
- "self clockPolicy: #monotonicForceNanosecondIncrement." ]!
- "self clockPolicy: #acceptPlatformTime."
- self clockPolicy: #monotonicAllowDuplicates.
- "self clockPolicy: #monotonicForceMicrosecondIncrement."
- "self clockPolicy: #monotonicForceNanosecondIncrement."
- !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset (in category 'clock') ----- posixMicrosecondClockWithOffset "Answer an array with local microseconds since the Posix epoch and the current seconds offset from GMT in the local time zone."
- | array posixUtcValue |
- | array utcValue |
array := self primPosixMicrosecondClockWithOffset.
- posixUtcValue := array at: 1.
- (self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time zone may have changed: fetch again."
- self primPosixMicrosecondClockWithOffset: array.
- posixUtcValue := array at: 1 ].
ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ array] . [#monotonicAllowDuplicates] -> [
- posixUtcValue > LastClockTick
- ifTrue: [LastClockTick := posixUtcValue]
- utcValue := array at: 1.
- utcValue > LastClockTick
- ifTrue: [LastClockTick := utcValue]
ifFalse: [array at: 1 put: LastClockTick]] . [#monotonicForceMicrosecondIncrement] -> [
- posixUtcValue > LastClockTick
- ifTrue: [LastClockTick := posixUtcValue]
- utcValue := array at: 1.
- utcValue > LastClockTick
- ifTrue: [LastClockTick := utcValue]
ifFalse: [LastClockTick := LastClockTick + 1. "add one microsecond" array at: 1 put: LastClockTick]] . [#monotonicForceNanosecondIncrement] -> [
- posixUtcValue > LastClockTick
- ifTrue: [LastClockTick := posixUtcValue]
- utcValue := array at: 1.
- utcValue > LastClockTick
- ifTrue: [LastClockTick := utcValue]
ifFalse: [LastClockTick := LastClockTick + (1 / 1000). "add one nanosecond" array at: 1 put: LastClockTick]] } otherwise: [].
- ^array!
- ^array
- !
Item was changed: ----- Method: Time class>>posixMicrosecondClockWithOffset: (in category 'clock') ----- posixMicrosecondClockWithOffset: aDateAndTime "Initialize aDateAndTime initialized with local microseconds since the Posix epoch and the current seconds offset from GMT in the local time zone."
- | posixUtcValue |
- | utcValue |
self primPosixMicrosecondClockWithOffset: aDateAndTime.
- posixUtcValue := aDateAndTime utcMicroseconds.
- (self updateTimeZoneCacheAt: posixUtcValue) ifTrue: [ "Time zone may have changed: fetch again."
- self primPosixMicrosecondClockWithOffset: aDateAndTime .
- posixUtcValue := aDateAndTime utcMicroseconds ].
ClockPolicy caseOf: { [#acceptPlatformTime] -> [^ aDateAndTime] . [#monotonicAllowDuplicates] -> [
- posixUtcValue > LastClockTick
- ifTrue: [LastClockTick := posixUtcValue]
- utcValue := aDateAndTime utcMicroseconds.
- utcValue > LastClockTick
- ifTrue: [LastClockTick := utcValue]
ifFalse: [aDateAndTime utcMicroseconds: LastClockTick]] . [#monotonicForceMicrosecondIncrement] -> [
- posixUtcValue > LastClockTick
- ifTrue: [LastClockTick := posixUtcValue]
- utcValue := aDateAndTime utcMicroseconds.
- utcValue > LastClockTick
- ifTrue: [LastClockTick := utcValue]
ifFalse: [LastClockTick := LastClockTick + 1. "add one microsecond" aDateAndTime utcMicroseconds: LastClockTick]] . [#monotonicForceNanosecondIncrement] -> [
- posixUtcValue > LastClockTick
- ifTrue: [LastClockTick := posixUtcValue]
- utcValue := aDateAndTime utcMicroseconds.
- utcValue > LastClockTick
- ifTrue: [LastClockTick := utcValue]
ifFalse: [LastClockTick := LastClockTick + (1 / 1000). "add one nanosecond" aDateAndTime utcMicroseconds: LastClockTick]] } otherwise: [].
- ^aDateAndTime!
- ^aDateAndTime
- !
Item was added:
- ----- Method: Time class>>primitiveUpdateTimeZone (in category 'clock') -----
- primitiveUpdateTimeZone
- "Update the VMs notion of the current time zone. The VM sets its notion
- of the time zone once at start-up. If one wants the VM to keep its notion
- up-to-date arrange to invoke this primitive periodically."
- <primitive: 243>
- ^nil "Return nil instead of self to indicate that the primitive failed."!
Item was added:
- ----- Method: Time class>>startUp: (in category 'system startup') -----
- startUp: resuming
- resuming ifTrue: [
- LastClockTick := 0 ]!
Item was added:
- ----- Method: Time class>>updateTimeZoneCacheAt: (in category 'clock') -----
- updateTimeZoneCacheAt: posixUtcMicrosecondClock
- "Tell the VM to update its cached time zone value if the POSIX UTC time reached the valute stored in UpdateVMTimeZoneCacheAt has been reached. Assume that posixUtcMicrosecondClock is an integer with the current POSIX UTC microsecond clock value. Return true when the cache was updated to indicate that the time zone may have changed."
- | updateInterval |
- UpdateVMTimeZoneCacheAt ifNil: [
- "Automatic update is disabled."
- ^false ].
- posixUtcMicrosecondClock < UpdateVMTimeZoneCacheAt ifTrue: [ ^false ].
- self primitiveUpdateTimeZone ifNil: [
- "The primitive failed."
- ^false ].
- updateInterval := 1800000000. "This could be a preference but 30 minutes matches all upcoming DST change times."
- UpdateVMTimeZoneCacheAt := posixUtcMicrosecondClock // updateInterval + 1 * updateInterval "Round up posixUtcMicrosecondClock to the next multiple of updateInterval.".
- ^true!
Item was changed:
- (PackageInfo named: 'Chronology-Core') postscript: '"Make sure UpdateVMTimeZoneCacheAt of Time is initialized."
- Time classPool at: #UpdateVMTimeZoneCacheAt put: 0.
- "Separated Time''s startup duties from DateAndTime."
- Smalltalk addToStartUpList: Time before: DateAndTime'!
- (PackageInfo named: 'Chronology-Core') postscript: 'DateAndTime startUp: true.
- HashedCollection rehashAll.
- '!
Hi Christoph,
On Sat, 18 Sep 2021, christoph.thiede@student.hpi.uni-potsdam.de wrote:
Hi all, hi Levente,
should we maybe reset the timezone cache on start-up of the image, to ensure that a fresh image will always fetch the correct timezone? Or is this already happening and I did not get it from the code? :-)
The time zone is cached by the VM, so it always has an up-to-date value on startup.
Levente
Oh, of course, I had overridden this part ... :-)
Bestm Christoph
--- Sent from Squeak Inbox Talk
On 2021-09-19T02:52:13+02:00, leves@caesar.elte.hu wrote:
Hi Christoph,
On Sat, 18 Sep 2021, christoph.thiede at student.hpi.uni-potsdam.de wrote:
Hi all, hi Levente,
should we maybe reset the timezone cache on start-up of the image, to ensure that a fresh image will always fetch the correct timezone? Or is this already happening and I did not get it from the code? :-)
The time zone is cached by the VM, so it always has an up-to-date value on startup.
Levente
squeak-dev@lists.squeakfoundation.org