--- a/AbstractTime.st Mon Oct 26 22:21:00 2020 +0000
+++ b/AbstractTime.st Tue Jun 01 12:09:10 2021 +0100
@@ -254,15 +254,38 @@
"Modified: 1.7.1996 / 15:20:10 / cg"
!
+nowWithMicroseconds
+ "return an instance of myself representing this moment with at least microsecond precision."
+
+ |osTime millis micros|
+
+ osTime := OperatingSystem getOSTimeWithMicros.
+ millis := osTime at:1.
+ micros := osTime at:2.
+ ^ self basicNew fromOSTimeWithMilliseconds:millis additionalPicoseconds:(micros*(1000*1000)).
+
+ "
+ Timestamp now
+ Time now
+ Timestamp nowWithMilliseconds
+ Timestamp nowWithMicroseconds
+ "
+
+ "Modified: 1.7.1996 / 15:20:10 / cg"
+!
+
nowWithMilliseconds
- "return an instance of myself representing this moment with millisecond precision."
+ "return an instance of myself representing this moment with at least millisecond precision."
^ self basicNew fromOSTimeWithMilliseconds:(OperatingSystem getOSTime)
"
+ Time now
+ Time nowWithMilliseconds
+
Timestamp now
- Time now
- Time nowWithMilliseconds
+ Timestamp nowWithMilliseconds
+ Timestamp nowWithMicroseconds
"
"Modified: 1.7.1996 / 15:20:10 / cg"
@@ -357,7 +380,6 @@
^ '%h:%m:%s'
! !
-
!AbstractTime class methodsFor:'private-instance creation'!
fromOSTime:osTime
@@ -398,7 +420,11 @@
!
microsecondClockValue
- "return microseconds seconds of now"
+ "This returns a microsecond timer value.
+ The returned value is a 64bit value
+ (which is the number of microseconds since the system's boot time -
+ but you should not depend on that because it is system specific.
+ Only use for relative delta-times."
^ OperatingSystem getMicrosecondTime
@@ -418,6 +444,8 @@
t2 := Time microsecondClockValue.
t2 - t1 - overhead
"
+
+ "Modified (comment): / 17-05-2020 / 15:05:12 / cg"
!
millisecondClockValue
@@ -457,6 +485,8 @@
!
readFrom:aStringOrStream format:formatString language:languageString onError:exceptionalValue
+ "see format description in readFrom:format:language:onError:"
+
^ self subclassResponsibility
!
@@ -586,6 +616,41 @@
"
! !
+!AbstractTime methodsFor:'Compatibility-ST80'!
+
+hour
+ "return the hour (0..23).
+ ST-80 Timestamp compatibility
+ (I'd prefer the name #hours, for Time compatibility)."
+
+ ^ self hours
+
+ "Created: 1.7.1996 / 15:14:50 / cg"
+ "Modified: 1.7.1996 / 15:15:32 / cg"
+!
+
+minute
+ "return the minute (0..59).
+ ST-80 Timestamp compatibility
+ (I'd prefer the name #minutes, for Time compatibility)."
+
+ ^ self minutes
+
+ "Created: 1.7.1996 / 15:14:29 / cg"
+ "Modified: 1.7.1996 / 15:15:37 / cg"
+!
+
+second
+ "return the second (0..59).
+ ST-80 Timestamp compatibility
+ (I'd prefer the name #seconds, for Time compatibility)."
+
+ ^ self seconds
+
+ "Created: 1.7.1996 / 15:14:19 / cg"
+ "Modified: 1.7.1996 / 15:15:49 / cg"
+! !
+
!AbstractTime methodsFor:'abstract'!
hours
@@ -645,6 +710,17 @@
"
!
+microseconds
+ "return the microseconds within the current second (0..999999)"
+
+ ^ (self milliseconds * 1000) + (self additionalPicoseconds // (1000*1000)).
+
+ "
+ Timestamp now microseconds
+ Timestamp nowWithMicroseconds microseconds
+ "
+!
+
minuteInDay
"return the minutes (0..59)"
@@ -656,6 +732,43 @@
"
!
+nanoseconds
+ "return the nanoseconds within the current second (0..999999)"
+
+ ^ (self milliseconds * 1000000) + (self additionalPicoseconds // (1000)).
+
+ "
+ Timestamp now nanoseconds
+ Timestamp nowWithMicroseconds nanoseconds
+ "
+!
+
+picoseconds
+ "return the picoseconds within the current second (0..999999999).
+ notice: that is NOT the total number of picoseconds,
+ but the fractional part (within the second) only.
+ Use this only for printing.
+ Here, fall back and generate something based on the milliseconds"
+
+ ^ (self milliseconds * 1000 * 1000 * 1000) + (self additionalPicoseconds).
+
+ "
+ Timestamp now picoseconds
+ Timestamp nowWithMicroseconds picoseconds
+
+ (TimeDuration fromPicoseconds:100) picoseconds
+ (TimeDuration fromPicoseconds:100000) picoseconds
+ (TimeDuration fromPicoseconds:100000) nanoseconds
+ (TimeDuration fromPicoseconds:100000000) picoseconds
+ (TimeDuration fromPicoseconds:100000000) nanoseconds
+ (TimeDuration fromPicoseconds:100000000) microseconds
+ (TimeDuration fromPicoseconds:100000000000) picoseconds
+ (TimeDuration fromPicoseconds:100000000000) nanoseconds
+ (TimeDuration fromPicoseconds:100000000000) microseconds
+ (TimeDuration fromPicoseconds:100000000000) milliseconds
+ "
+!
+
secondInDay
"return the seconds (0..59)"
@@ -687,36 +800,56 @@
!AbstractTime methodsFor:'arithmetic'!
+ aNumberOrTimeDuration
- "Add aNumber numberOfSeconds or, if its a timeDuration, add its value"
+ "Add aNumber (numberOfSeconds) or, if it's a timeDuration, add it's value"
^ aNumberOrTimeDuration sumFromTimestamp:self.
-"/ ^ self speciesNew
-"/ setMilliseconds:(self getMilliseconds + (aNumberOrTimeDuration * 1000) asInteger)
-
"
Timestamp now to:(Timestamp now + 30) by:2 do:[:time|
Transcript showCR:time.
].
+ Timestamp now to:(Timestamp now + 30) by:2 seconds do:[:time|
+ Transcript showCR:time.
+ ].
+ (Timestamp now + 30 seconds) to:(Timestamp now) by:-2 seconds do:[:time|
+ Transcript showCR:time.
+ ].
+ (Timestamp now + 30 seconds) to:(Timestamp now) by:-2 do:[:time|
+ Transcript showCR:time.
+ ].
(Timestamp now + 20) - Timestamp now
(Timestamp now + 0.5) - Timestamp now
(Timestamp now + (TimeDuration fromString:'1m 10s')) - Timestamp now
(Timestamp now + (10 seconds)) - Timestamp now
"
+
+ "Modified (comment): / 13-02-2017 / 19:55:04 / cg"
!
-- aTimeOrNumberOfSeconds
+- aTimeOrTimeDurationOrNumberOfSeconds
"return the delta in seconds between 2 times or subtract a number of seconds."
- ^ aTimeOrNumberOfSeconds differenceFromTimestamp:self.
+ "/ Q: for Time - x hours
+ "/ should we convert to timestamp i.e. caring for time-wrapping at midnight?
+ "/ no - for compatibility, we'll get the time-within-the day again
+ "/ if you need the real timestamp, a for it explicitly
+
+ ^ aTimeOrTimeDurationOrNumberOfSeconds differenceFromTimestamp:self.
"
- Timestamp now - 3600.
- Time now - 3600.
- (Time now addSeconds:10) - Time now
- (TimeDuration fromString:'1.5hr') - 3600.
- (TimeDuration fromString:'1.5hr') - (TimeDuration fromString:'1hr')
+ Timestamp now - 3600. -> 2018-05-09 15:37:57.485
+ Timestamp now - 3600 seconds. -> 2018-05-09 15:38:04.665
+ (Timestamp now addSeconds:10) - Timestamp now -> 10s
+
+ Time now - 3600. -> 03:38:23 PM
+ Time now - 3600 seconds. -> 03:38:35 PM
+ (Time now addSeconds:10) - Time now -> 10s
+ Time now - 1 hours. -> 11:04:02
+ Time now - 24 hours. -> 11:04:02
+
+ (TimeDuration fromString:'1.5hr') - 3600. -> 30m
+ (TimeDuration fromString:'1.5hr') - (TimeDuration fromString:'1hr') -> 30m
|t1 t2|
@@ -725,6 +858,8 @@
t2 := Timestamp now.
Transcript showCR:('seconds passed: ' , (t2 - t1) printString).
"
+
+ "Modified (comment): / 08-05-2019 / 12:49:59 / Claus Gittinger"
!
addDays:numberOfDays
@@ -763,11 +898,46 @@
"
!
+addMicroseconds:numberOfMicroSeconds
+ "return a new instance of myself, numberOfMicroSeconds afterwards."
+
+ ^ self speciesNew
+ setMilliseconds:(self getMilliseconds + (numberOfMicroSeconds // 1000))
+ additionalPicoseconds:(self additionalPicoseconds
+ + ((numberOfMicroSeconds \\ 1000)*1000000) truncated)
+
+ "
+ |t1 t2|
+
+ t1 := Timestamp now.
+ Transcript showCR:t1.
+ t2 := t1 addMicroseconds:1000.
+ Transcript showCR:t2.
+ t2 := t1 addMicroseconds:1010.
+ Transcript showCR:t2.
+ Transcript showCR:(t2 - t1).
+ self halt.
+ Transcript showCR:(t2 - t1) asMicroseconds.
+ "
+
+ "
+ |t|
+
+ t := Time now.
+ Transcript showCR:t.
+ Transcript showCR:(t addMilliseconds:1000).
+ "
+
+ "Modified: / 22-05-2018 / 16:52:37 / Stefan Vogel"
+!
+
addMilliseconds:numberOfMilliSeconds
"return a new instance of myself, numberOfMilliSeconds afterwards."
^ self speciesNew
- setMilliseconds:(self getMilliseconds + numberOfMilliSeconds)
+ setMilliseconds:(self getMilliseconds + (numberOfMilliSeconds // 1 "this is inlined #truncated"))
+ additionalPicoseconds:(self additionalPicoseconds
+ + ((numberOfMilliSeconds \\ 1)*1000000000) truncated)
"
|t|
@@ -784,6 +954,8 @@
Transcript showCR:t.
Transcript showCR:(t addMilliseconds:1000).
"
+
+ "Modified: / 22-05-2018 / 17:03:20 / Stefan Vogel"
!
addMinutes:numberOfMinutes
@@ -811,8 +983,7 @@
addSeconds:numberOfSeconds
"return a new instance of myself, numberOfSeconds afterwards."
- ^ self speciesNew
- setMilliseconds:(self getMilliseconds + (numberOfSeconds * 1000))
+ ^ self addMilliseconds:(numberOfSeconds * 1000)
"
|t|
@@ -876,6 +1047,8 @@
!
roundTo:aTimeDuration
+ "round the receiver to the next multiple of a TimeDuration"
+
^ self class new setMilliseconds:(self getMilliseconds roundTo:aTimeDuration getMilliseconds)
"
@@ -924,8 +1097,7 @@
subtractMilliseconds:numberOfMilliSeconds
"return a new instance of myself, numberOfMilliSeconds before."
- ^ self speciesNew
- setMilliseconds:(self getMilliseconds - numberOfMilliSeconds)
+ ^ self addMilliseconds:numberOfMilliSeconds negated
"
|t|
@@ -969,8 +1141,7 @@
subtractSeconds:numberOfSeconds
"return a new instance of myself, numberOfSeconds before."
- ^ self speciesNew
- setMilliseconds:(self getMilliseconds - (numberOfSeconds * 1000))
+ ^ self addMilliseconds:(numberOfSeconds * -1000)
"
|t|
@@ -1005,6 +1176,8 @@
!
truncateTo:aTimeDuration
+ "truncate the receiver to the next multiple of a TimeDuration"
+
^ self class new setMilliseconds:(self getMilliseconds truncateTo:aTimeDuration getMilliseconds)
"
@@ -1016,20 +1189,149 @@
!AbstractTime methodsFor:'comparing'!
-< aTime
+< aTimeOrTimeDurationOrNumberOfSeconds
"return true if the receiver is before the argument"
- ^ self getMilliseconds < aTime getMilliseconds
-
- "Modified: 3.7.1996 / 13:10:17 / cg"
+ |myMilliseconds otherMilliseconds myPicos otherPicos|
+
+ myMilliseconds := self getMilliseconds.
+ myPicos := self additionalPicoseconds.
+
+ aTimeOrTimeDurationOrNumberOfSeconds isNumber ifTrue:[
+ "backward compatibility for old code, which expects (time1 - time2) to return seconds"
+ otherMilliseconds := (aTimeOrTimeDurationOrNumberOfSeconds * 1000) asInteger. "integer seconds"
+ otherPicos := 0.
+ ] ifFalse:[
+ otherMilliseconds := aTimeOrTimeDurationOrNumberOfSeconds getMilliseconds.
+ otherPicos := aTimeOrTimeDurationOrNumberOfSeconds additionalPicoseconds.
+ ].
+ ^ (myMilliseconds < otherMilliseconds)
+ or:[ myMilliseconds = otherMilliseconds and:[myPicos < otherPicos ]].
+
+ "
+ (Timestamp now + 10) - Timestamp now < 10
+ (Timestamp now + 10) - Timestamp now < 11
+ "
+!
+
+<= aTimeOrTimeDurationOrNumberOfSeconds
+ "return true if the receiver is before or the same time as the argument"
+
+ |myMilliseconds otherMilliseconds myPicos otherPicos|
+
+ myMilliseconds := self getMilliseconds.
+ myPicos := self additionalPicoseconds.
+
+ aTimeOrTimeDurationOrNumberOfSeconds isNumber ifTrue:[
+ "backward compatibility for old code, which expects (time1 - time2) to return seconds"
+ otherMilliseconds := (aTimeOrTimeDurationOrNumberOfSeconds * 1000) asInteger. "integer seconds"
+ otherPicos := 0.
+ ] ifFalse:[
+ otherMilliseconds := aTimeOrTimeDurationOrNumberOfSeconds getMilliseconds.
+ otherPicos := aTimeOrTimeDurationOrNumberOfSeconds additionalPicoseconds.
+ ].
+ ^ (myMilliseconds < otherMilliseconds)
+ or:[ myMilliseconds = otherMilliseconds and:[myPicos <= otherPicos ]].
+
+ "
+ (Timestamp now + 10) - Timestamp now <= 10
+ (Timestamp now + 10) - Timestamp now <= 11
+ (Timestamp now + 10) - Timestamp now <= 9
+ "
!
-> aTime
+= aTimeOrTimeDurationOrNumberOfSeconds
+ "return true if the receiver is before or the same time as the argument"
+
+ |myMilliseconds otherMilliseconds myPicos otherPicos|
+
+ myMilliseconds := self getMilliseconds.
+ myPicos := self additionalPicoseconds.
+
+ aTimeOrTimeDurationOrNumberOfSeconds isNumber ifTrue:[
+ "backward compatibility for old code, which expects (time1 - time2) to return seconds"
+ otherMilliseconds := (aTimeOrTimeDurationOrNumberOfSeconds * 1000) asInteger. "integer seconds"
+ otherPicos := 0.
+ ] ifFalse:[
+ self speciesForCompare = aTimeOrTimeDurationOrNumberOfSeconds speciesForCompare ifFalse:[
+ ^ false
+ ].
+ otherMilliseconds := aTimeOrTimeDurationOrNumberOfSeconds getMilliseconds.
+ otherPicos := aTimeOrTimeDurationOrNumberOfSeconds additionalPicoseconds.
+ ].
+ ^ (myMilliseconds = otherMilliseconds) and:[myPicos = otherPicos ].
+
+ "
+ (Timestamp now + 10) - Timestamp now = 10
+ (Timestamp now + 10) - Timestamp now = 9
+
+ (Timestamp now) = (Timestamp now + 10 - 10)
+ (Timestamp now) = (UtcTimestamp now)
+
+ (Time now + 10 seconds) - Time now = 10
+ (Time now + 10) - Time now = 10
+
+ (Time now + 10 seconds) > Time now
+ (Time now + 10) > Time now
+
+ (Time now + 10 milliSeconds) > Time now
+ (Time now + 0 milliseconds) > Time now
+ "
+!
+
+> aTimeOrTimeDurationOrNumberOfSeconds
"return true if the receiver is after the argument"
- ^ self getMilliseconds > aTime getMilliseconds
-
- "Modified: 1.7.1996 / 15:24:38 / cg"
+ |myMilliseconds otherMilliseconds myPicos otherPicos|
+
+ myMilliseconds := self getMilliseconds.
+ myPicos := self additionalPicoseconds.
+
+ aTimeOrTimeDurationOrNumberOfSeconds isNumber ifTrue:[
+ "backward compatibility for old code, which expects (time1 - time2) to return seconds"
+ otherMilliseconds := (aTimeOrTimeDurationOrNumberOfSeconds * 1000) asInteger. "integer seconds"
+ otherPicos := 0.
+ ] ifFalse:[
+ otherMilliseconds := aTimeOrTimeDurationOrNumberOfSeconds getMilliseconds.
+ otherPicos := aTimeOrTimeDurationOrNumberOfSeconds additionalPicoseconds.
+ ].
+ ^ (myMilliseconds > otherMilliseconds)
+ or:[ myMilliseconds = otherMilliseconds and:[myPicos > otherPicos ]].
+
+ "
+ (Timestamp now + 10) - Timestamp now > 10
+ (Timestamp now + 10) - Timestamp now > 9
+ "
+!
+
+>= aTimeOrTimeDurationOrNumberOfSeconds
+ "return true if the receiver is after the argument or the same"
+
+ |myMilliseconds otherMilliseconds myPicos otherPicos|
+
+ myMilliseconds := self getMilliseconds.
+ myPicos := self additionalPicoseconds.
+
+ aTimeOrTimeDurationOrNumberOfSeconds isNumber ifTrue:[
+ "backward compatibility for old code, which expects (time1 - time2) to return seconds"
+ otherMilliseconds := (aTimeOrTimeDurationOrNumberOfSeconds * 1000) asInteger. "integer seconds"
+ otherPicos := 0.
+ ] ifFalse:[
+ otherMilliseconds := aTimeOrTimeDurationOrNumberOfSeconds getMilliseconds.
+ otherPicos := aTimeOrTimeDurationOrNumberOfSeconds additionalPicoseconds.
+ ].
+ ^ (myMilliseconds > otherMilliseconds)
+ or:[ myMilliseconds = otherMilliseconds and:[myPicos >= otherPicos ]].
+
+ "
+ (Timestamp now + 10) - Timestamp now >= 11
+ (Timestamp now + 10) - Timestamp now >= 10
+ (Timestamp now + 10) - Timestamp now >= 9
+ "
+!
+
+hash
+ ^ self getMilliseconds
! !
!AbstractTime methodsFor:'converting'!
@@ -1049,7 +1351,9 @@
!
asMilliseconds
- "return the number of milliseconds elapsed since midnight"
+ "return the number of milliseconds elapsed since some starttime,
+ which is subclass specific (i.e. Time: since midnight; Timestamp: since the epoch).
+ Use this only to compute relative millisecond deltas."
^ self getMilliseconds
@@ -1065,9 +1369,9 @@
asSeconds
"get the seconds since some point of time in the past.
- For Time instances, this is the number of seconds elapsed since midnight;
- For TimeDurations, that is the duration in seconds;
- For TimeStamps, that is the number of seconds since the epoch"
+ For Time instances, this is the number of seconds elapsed since midnight (truncated);
+ For TimeDurations, that is the duration in seconds (truncated);
+ For TimeStamps, that is the number of seconds since the epoch (truncated)"
^ self getSeconds
@@ -1076,6 +1380,26 @@
Time now asSeconds
(TimeDuration days:1) asSeconds
"
+
+ "Modified (comment): / 24-05-2020 / 13:53:16 / cg"
+!
+
+asTZTimestamp
+ "raise an error: must be redefined in concrete subclass(es)"
+
+ ^ self subclassResponsibility
+!
+
+asTime
+ "return a Time object from the receiver."
+
+ ^ Time hours:(self hours) minutes:(self minutes) seconds:(self seconds) milliseconds:(self milliseconds)
+
+ "
+ (1 seconds + 0.01 seconds) asTime
+ "
+
+ "Created: / 17-07-2017 / 13:57:54 / cg"
!
asTimestamp
@@ -1093,18 +1417,11 @@
!AbstractTime methodsFor:'double dispatching'!
differenceFromTimestamp:aTimestamp
- "/ the correct thing to do (and I will, in the future) is to
- "/ return a TimeDuration:
- "/
- ^ TimeDuration fromMilliseconds:(aTimestamp getMilliseconds - self getMilliseconds).
-
- "/ which is the same as: deltaFrom:aTimestamp
- "/
- "/ however, there might be old code around, which is not be prepared for
- "/ getting a non-number (the seconds). Therefore, for the meantime,
- "/ we return:
-
- "/ ^ aTimestamp getSeconds - self getSeconds
+ "return the time difference as a timeDuration instance"
+
+ ^ self subclassResponsibility.
+
+ "Modified: / 27-07-2018 / 11:30:27 / Stefan Vogel"
! !
!AbstractTime methodsFor:'printing & storing'!
@@ -1120,6 +1437,7 @@
%m minutes, 00..59 0-padded to length 2
%s seconds, 00..59 0-padded to length 2
%i milliseconds, 000..999 0-padded to length 3
+ %j microseconds, 000000..999999 0-padded to length 6
Timestamp only:
%(day) day, 00..31 0-padded to length 2
@@ -1131,13 +1449,32 @@
%M minutes - unpadded
%S seconds - unpadded
%I milliseconds, unpadded
+ %J microseconds, unpadded
+ %F subsecond fraction, unpadded with as many post-digits as appropriate
+ (i.e. for .1 , .01 , .001 etc.)
%t seconds within hour (unpadded)
%T seconds from midNight (unpadded)
+ %(milli) milliseconds unpadded - alias for %I for convenience
%(milli1) milliseconds, truncated to 1/10th of a second 0..9
%(milli2) milliseconds, truncated to 1/100th of a second 00..99 0-padded to length 2
- %(milli3) milliseconds, same as %i for convenience
+ %(milli3) milliseconds, padded to 3 (same as %i for convenience)
+ %(milliF1) milliseconds + 1 digits of micros
+ %(milliF2) milliseconds + 2 digits of micros
+ %(milliF3) milliseconds + 3 digits of micros
+ %(milliF4) milliseconds + 4 digits of micros
+
+ %(micro) microseconds unpadded - alias for %J for convenience
+ %(micro6) microseconds, padded to 6 (same as %j for convenience)
+
+ %(nano) nanoseconds unpadded
+ %(nano9) nanoseconds, padded to 9
+
+ %(pico) picoseconds unpadded
+ %(pico12) picoseconds, padded to 12
+
+ %(fract) fraction part - as many as needed alias for %F for convenience
Timestamp only:
%(Day) - day - unpadded
@@ -1199,13 +1536,20 @@
"
- |time hours minutes seconds millis s t|
+ |time hours minutes seconds millis micros nanos picos
+ millisZ3 picosZ9 fract012 fract s t|
+
+ aDictionary at:#'iso8601' put:[ self printStringIso8601 ].
+ aDictionary at:#'iso8601_compact' put:[ self printStringIso8601Compressed ].
time := self asTime.
hours := time hours.
minutes := time minutes.
seconds := time seconds.
millis := self milliseconds.
+ micros := self microseconds.
+ nanos := self nanoseconds.
+ picos := self picoseconds.
aDictionary at:$H put:(s := hours printString).
aDictionary at:$h put:(s leftPaddedTo:2 with:$0).
@@ -1217,22 +1561,70 @@
aDictionary at:$s put:(s leftPaddedTo:2 with:$0).
aDictionary at:$I put:(s := millis printString).
- aDictionary at:$i put:(t := s leftPaddedTo:3 with:$0).
- aDictionary at:#milli3 put:t.
+ aDictionary at:#milli put:s.
+ aDictionary at:$i put:(millisZ3 := s leftPaddedTo:3 with:$0).
+ aDictionary at:#milli3 put:millisZ3.
aDictionary at:#milli1 put:((millis // 100) printString).
aDictionary at:#milli2 put:((millis // 10) printStringLeftPaddedTo:2 with:$0).
+ aDictionary at:#milliF1 put:((micros asFixedPoint:1) / 1000).
+ aDictionary at:#milliF2 put:((micros asFixedPoint:2) / 1000).
+ aDictionary at:#milliF3 put:((micros asFixedPoint:3) / 1000).
+ aDictionary at:#milliF4 put:((nanos asFixedPoint:4) / 1000000).
+
+ aDictionary at:$J put:(s := micros printString).
+ aDictionary at:#micro put:s.
+ aDictionary at:$j put:(t := s leftPaddedTo:6 with:$0).
+ aDictionary at:#micro6 put:t.
+ aDictionary at:#microF1 put:((nanos asFixedPoint:1) / 1000).
+ aDictionary at:#microF2 put:((nanos asFixedPoint:2) / 1000).
+ aDictionary at:#microF3 put:((nanos asFixedPoint:3) / 1000).
+ aDictionary at:#microF4 put:((picos asFixedPoint:4) / 1000000).
+
+ aDictionary at:#nano put:(s := nanos printString).
+ aDictionary at:#nano9 put:(s leftPaddedTo:9 with:$0).
+
+ aDictionary at:#pico put:(s := picos printString).
+ aDictionary at:#pico12 put:(s leftPaddedTo:12 with:$0).
+
+ picosZ9 := self picoseconds printString leftPaddedTo:9 with:$0.
+ fract012 := millisZ3,picosZ9.
+ fract := fract012 copyTo:(fract012 findLast:[:ch | ch ~~ $0] ifNone:12).
+ aDictionary at:$F put:fract.
+ aDictionary at:#fract put:fract.
aDictionary at:$t put:(seconds * minutes) printString.
aDictionary at:$T put:(seconds * minutes * hours) printString.
-
"
|dict|
dict := Dictionary new.
Timestamp now addBasicPrintBindingsTo:dict language:#en.
dict inspect
"
+ "
+ Timestamp now printStringFormat:'%(milli)' -- millis only
+ Timestamp now printStringFormat:'%(milli3)' -- millis padded
+ Timestamp now printStringFormat:'%(micro6)' -- micros padded
+ Timestamp now printStringFormat:'%(fract)' -- fraction part - as needed
+ Timestamp nowWithMicroseconds printStringFormat:'%(fract)' -- fraction part - as needed
+
+ (TimeDuration fromMicroseconds:30) printStringFormat:'%(milliF1)ms'
+ (TimeDuration fromMicroseconds:30) printStringFormat:'%(milliF2)ms'
+ (TimeDuration fromMicroseconds:30) printStringFormat:'%(milliF3)ms'
+ (TimeDuration fromMicroseconds:30) printStringFormat:'%(milliF4)ms'
+ (TimeDuration fromMicroseconds:3) printStringFormat:'%(milliF4)ms'
+ (TimeDuration fromNanoseconds:300) printStringFormat:'%(milliF4)us'
+
+ (TimeDuration fromNanoseconds:30) printStringFormat:'%(microF1)us'
+ (TimeDuration fromNanoseconds:30) printStringFormat:'%(microF2)us'
+ (TimeDuration fromNanoseconds:30) printStringFormat:'%(microF3)us'
+ (TimeDuration fromNanoseconds:30) printStringFormat:'%(microF4)us'
+ (TimeDuration fromNanoseconds:3) printStringFormat:'%(microF4)us'
+ (TimeDuration fromPicoseconds:300) printStringFormat:'%(microF4)us'
+ "
+
+ "Modified (comment): / 14-01-2019 / 18:21:38 / Claus Gittinger"
!
addPrintBindingsTo:aDictionary
@@ -1271,6 +1663,7 @@
%T seconds from midNight (unpadded)
%(TZD) timeZone delta of the receiver from UTC in the format +/-hh:mm
+ %(TZD822) timeZone delta of the receiver from UTC in the(RFC822-)format +/-hhmm
%(milli1) milliseconds, truncated to 1/10th of a second 0..9
%(milli2) milliseconds, truncated to 1/100th of a second 00..99 0-padded to length 2
@@ -1339,7 +1732,7 @@
"
- |usHours ampm s zone tzDelta|
+ |usHours ampm s zone tzDelta s0 s1 s2 s822|
self addBasicPrintBindingsTo:aDictionary language:languageOrNil.
zone := self timeZoneName.
@@ -1350,7 +1743,6 @@
aDictionary at:$U put:usHours.
aDictionary at:$u put:(usHours leftPaddedTo:2 with:$0).
-
aDictionary at:$a put:ampm.
aDictionary at:$A put:ampm asUppercase.
aDictionary at:$z put:zone.
@@ -1358,12 +1750,17 @@
tzDelta == 0 ifTrue:[
s := 'Z'.
+ s822 := '+0000'
] ifFalse:[
- s := tzDelta < 0 ifTrue:[ '-' ] ifFalse:[ '+' ].
+ s0 := tzDelta < 0 ifTrue:[ '-' ] ifFalse:[ '+' ].
tzDelta := tzDelta abs.
- s := s , ((tzDelta // 60) printStringLeftPaddedTo:2 with:$0),
- ':' , ((tzDelta \\ 60) printStringLeftPaddedTo:2 with:$0).
+
+ s1 := ((tzDelta // 60) printStringLeftPaddedTo:2 with:$0).
+ s2 := ((tzDelta \\ 60) printStringLeftPaddedTo:2 with:$0).
+ s := s0, s1, ':', s2.
+ s822 := s0, s1, s2.
].
+ aDictionary at:#TZD822 put:s822.
aDictionary at:#TZD put:s
@@ -1373,6 +1770,34 @@
Timestamp now addPrintBindingsTo:dict language:#en.
dict inspect
"
+
+ "Modified (format): / 03-03-2020 / 17:49:57 / Stefan Vogel"
+!
+
+printIso8601CompressedOn:aStream
+ self subclassResponsibility
+
+ "
+ Timestamp now printStringIso8601 -> '2018-05-09T12:15:53.279'
+ Time now printStringIso8601 -> 'T16:27:08'
+ Date today printStringIso8601 -> '2018-05-09'
+
+ Timestamp now printStringIso8601Compressed -> '20180525T120822.699'
+ Time now printStringIso8601Compressed -> 'T120837'
+ Date today printStringIso8601Compressed -> '20180525'
+ "
+
+ "Created: / 25-05-2018 / 12:08:07 / Claus Gittinger"
+!
+
+printIso8601FormatOn:aStream
+ self subclassResponsibility
+
+ "
+ Timestamp now printStringIso8601 -> '2018-05-09T12:15:53.279+02'
+ Time now printStringIso8601 -> 'T16:27:08'
+ Date today printStringIso8601 -> '2018-05-09'
+ "
!
printOn:aStream format:aFormatString
@@ -1400,6 +1825,17 @@
|dict|
+"/ is this a good idea?
+"/ aFormatString = '%h:%m:%s' ifTrue:[
+"/ "/ this is so common...
+"/ aStream nextPutAll:(self hours printStringLeftPaddedTo:2 with:$0).
+"/ aStream nextPutAll:':'.
+"/ aStream nextPutAll:(self minutes printStringLeftPaddedTo:2 with:$0).
+"/ aStream nextPutAll:':'.
+"/ aStream nextPutAll:(self seconds printStringLeftPaddedTo:2 with:$0).
+"/ ^ self
+"/ ].
+
dict := IdentityDictionary new.
self addPrintBindingsTo:dict language:languageString.
@@ -1415,7 +1851,8 @@
Time now printOn:Transcript format:'minutes:%M seconds:%S'. Transcript cr.
"
- "Modified: 22.2.1996 / 16:58:30 / cg"
+ "Modified: / 22-02-1996 / 16:58:30 / cg"
+ "Modified: / 14-01-2019 / 18:22:12 / Claus Gittinger"
!
printStringFormat:aFormatString
@@ -1456,12 +1893,12 @@
|s|
- s := CharacterWriteStream on:(String new:20).
+ s := CharacterWriteStream new.
self printOn:s format:aFormatString language:languageString.
^ s contents.
"
- Timestamp now printStringFormat:'%U:%m:%s %a
+ Timestamp now printStringFormat:'%U:%m:%s %a'
Time now printStringFormat:'%U:%m:%s %a'
Time now printStringFormat:'%h:%m:%s'
@@ -1484,10 +1921,75 @@
"
"Modified: 22.2.1996 / 16:58:30 / cg"
+!
+
+printStringIso8601
+ "return the Iso8601 representation of the receiver with local timezon information.
+ This format looks like:
+ 1999-01-01T24:00:00
+ or, for zero hr:min:sec,
+ 1999-01-01
+ Of course, a 24 hour clock is used."
+
+ ^ String streamContents:[:s | self printIso8601FormatOn:s]
+
+ "
+ Timestamp now printStringIso8601
+ "
+
+ "Modified (comment): / 25-05-2018 / 11:58:37 / Claus Gittinger"
+!
+
+printStringIso8601Compressed
+ "return the Iso8601 representation of the receiver with local timezon information.
+ This format looks like:
+ 1999-01-01T24:00:00
+ or, for zero hr:min:sec,
+ 1999-01-01
+ Of course, a 24 hour clock is used."
+
+ ^ String streamContents:[:s | self printIso8601CompressedOn:s]
+
+ "
+ Timestamp now printStringIso8601Compressed
+ "
+
+ "Created: / 25-05-2018 / 11:58:29 / Claus Gittinger"
+!
+
+printStringIso8601Format
+ "would like to make it obsolete, but it is:"
+ <resource: #EXPECCO_API>
+ "<resource: #obsolete>"
+
+ "return the Iso8601 representation of the receiver with local timezon information.
+ This format looks like:
+ 1999-01-01T24:00:00
+ or, for zero hr:min:sec,
+ 1999-01-01
+ Of course, a 24 hour clock is used."
+
+ "/ self obsoleteMethodWarning:'use printStringIso8601'.
+ ^ self printStringIso8601
+
+ "
+ Timestamp now printStringIso8601Format
+ "
! !
!AbstractTime methodsFor:'private'!
+additionalPicoseconds
+ "return the additional picoseconds within the current second (0..999999999).
+ Here, assume that we have none"
+
+ ^ 0.
+
+ "
+ Timestamp now picoseconds
+ "
+!
+
fromOSTime:osTime
"set my time, from operatingSystems time parts"
@@ -1496,10 +1998,31 @@
"Modified: 1.7.1996 / 15:09:44 / cg"
!
+fromOSTimeWithMilliseconds:anUninterpretedOSTime
+ "strictly private: set the milliseconds from an OS time (since the epoch)"
+
+ self subclassResponsibility
+!
+
+getMicroseconds
+ "get the milliseconds since some point of time in the past.
+ Since I am abstract (not knowing how the time is actually
+ represented), this must be done by a concrete class.
+ Also be aware that the returned value is concrete-class specific;
+ Time returns the micros since midnight, Timestamp since the epoch.
+ Use this only to compute relative time deltas.
+ Here is a fallback, which only returns milliseocnd precision values"
+
+ ^ self getMilliseconds * 1000
+!
+
getMilliseconds
"get the milliseconds since some point of time in the past.
Since I am abstract (not knowing how the time is actually
- represented), this must be done by a concrete class."
+ represented), this must be done by a concrete class.
+ Also be aware that the returned value is concrete-class specific;
+ Time returns the millis since midnight, Timestamp since the epoch.
+ Use this only to compute relative time deltas."
^ self subclassResponsibility
@@ -1507,11 +2030,13 @@
!
getSeconds
- "get the seconds since some point of time in the past.
+ "get the (truncated) seconds since some point of time in the past.
Since I am abstract (not knowing how the time is actually
represented), this must be done by a concrete class."
^ self subclassResponsibility
+
+ "Modified (comment): / 21-09-2017 / 18:50:30 / cg"
!
setMilliseconds:millis
@@ -1524,6 +2049,12 @@
"Created: 1.7.1996 / 14:17:00 / cg"
!
+setMilliseconds:arg1 additionalPicoseconds:arg2
+ "raise an error: must be redefined in concrete subclass(es)"
+
+ ^ self subclassResponsibility
+!
+
setSeconds:secs
"set the seconds since some point of time in the past.
Since I am abstract (not knowing how the time is actually