#FEATURE by cg
class: Timestamp::TimestampISO8601Builder class
added: #print:compact:asLocal:asUTC:subSecondDigits:suppressZeroSubSecondDigits:timeSeparator:timeOnly:on:
changed: #print:compact:asLocal:asUTC:withMilliseconds:timeSeparator:timeOnly:on:
better adjustments.
--- a/Timestamp.st Mon May 14 21:07:27 2018 +0200
+++ b/Timestamp.st Mon May 14 21:38:54 2018 +0200
@@ -4174,6 +4174,140 @@
!Timestamp::TimestampISO8601Builder class methodsFor:'printing - basic'!
+print:aTimeOrTimestamp compact:compact asLocal:asLocal asUTC:asUTC
+ subSecondDigits:numDigits
+ suppressZeroSubSecondDigits:suppressZeroSubSecondDigits
+ timeSeparator:tSep timeOnly:timeOnly on:aStream
+
+ "Print the given timestamp in general ISO8601 format,
+ such as '2014-11-06T11:48:09Z'.
+ compact: if true, the compact format (without separating dashes and colons is generated)
+ asLocal: if true, generates a localtime string (without any timezone info)
+ asUTC: if true, generates a utc string
+ if both are false:
+ generate a string depending on the type of timestamp:
+ if local: generate a local timezone string
+ if utc: generate a utc string
+ otherwise it is a timestamp from another timezone (TZTimestamp), then print in its timezone
+ numDigits: nr of post-second fractional part (i.e. 3 for millis, 6 for micros, 0 for none, #variable for as-required);
+ suppressZeroSubSecondDigits: to suppress zeros (i.e. the old behavior).
+ if timeOnly is true, only the time is printed."
+
+ |aTimestamp timeInfo picos picosString |
+
+ aTimestamp := aTimeOrTimestamp asTimestamp.
+
+ asLocal ifTrue:[
+ "/ force local
+ timeInfo := aTimestamp asLocalTimestamp timeInfo.
+ ] ifFalse:[
+ asUTC ifTrue:[
+ "/ force utc
+ timeInfo := aTimestamp asUtcTimestamp timeInfo.
+ ] ifFalse:[
+ "/ in the timestamps own format
+ timeInfo := aTimestamp timeInfo.
+ ]
+ ].
+
+ timeOnly ifFalse:[
+ timeInfo year printOn:aStream leftPaddedTo:4 with:$0.
+ compact ifFalse:[ aStream nextPut: $- ].
+ timeInfo month printOn:aStream leftPaddedTo:2 with:$0.
+ compact ifFalse:[ aStream nextPut: $- ].
+ timeInfo day printOn:aStream leftPaddedTo:2 with:$0.
+ ].
+ aStream nextPut:tSep.
+ timeInfo hours printOn:aStream leftPaddedTo:2 with:$0.
+ compact ifFalse:[ aStream nextPut: $:].
+ timeInfo minutes printOn:aStream leftPaddedTo:2 with:$0.
+
+ "always print the seconds, even if 0.
+ According to http://www.w3.org/TR/xmlschema11-2/#dateTime this is mandatory"
+
+ compact ifFalse:[ aStream nextPut: $:].
+ timeInfo seconds printOn:aStream leftPaddedTo:2 with:$0.
+
+ numDigits == 3 ifTrue:[
+ "/ special case, because it is so common
+ aStream nextPut: $..
+ aTimestamp milliseconds printOn:aStream leftPaddedTo:3 with:$0.
+ ] ifFalse:[
+ numDigits ~~ 0 ifTrue:[
+ picos := aTimestamp picoseconds.
+ (suppressZeroSubSecondDigits and:[picos = 0]) ifFalse:[
+ "/ not suppressed
+ picosString := picos printStringLeftPaddedTo:12 with:$0.
+ numDigits == #variable ifTrue:[
+ picosString := picosString withoutTrailing:$0.
+ ] ifFalse:[
+ numDigits > 12 ifTrue:[
+ picosString := picosString paddedTo:numDigits with:$0
+ ] ifFalse:[
+ picosString := picosString copyTo:numDigits.
+ ].
+ ].
+ aStream nextPut: $..
+ aStream nextPutAll:picosString.
+ ]
+ ].
+ ].
+
+ asUTC ifTrue:[
+ aStream nextPut: $Z
+ ] ifFalse:[
+ asLocal ifFalse:[
+ self printTimeZone:aTimestamp utcOffset on:aStream.
+ ].
+ ].
+
+ "
+ Transcript cr. self
+ print:(Timestamp nowWithMicroseconds)
+ compact:false asLocal:false asUTC:true
+ subSecondDigits:3
+ suppressZeroSubSecondDigits:false
+ timeSeparator:$T timeOnly:false on:Transcript
+
+ Transcript cr. self
+ print:(Timestamp nowWithMicroseconds)
+ compact:false asLocal:false asUTC:true
+ subSecondDigits:6
+ suppressZeroSubSecondDigits:false
+ timeSeparator:$T timeOnly:false on:Transcript
+
+ Transcript cr. self
+ print:(Timestamp nowWithMicroseconds)
+ compact:false asLocal:false asUTC:true
+ subSecondDigits:#variable
+ suppressZeroSubSecondDigits:false
+ timeSeparator:$T timeOnly:false on:Transcript
+
+ Transcript cr. self
+ print:(Timestamp now)
+ compact:false asLocal:false asUTC:true
+ subSecondDigits:#variable
+ suppressZeroSubSecondDigits:false
+ timeSeparator:$T timeOnly:false on:Transcript
+
+ Transcript cr. self
+ print:(Timestamp now)
+ compact:false asLocal:false asUTC:true
+ subSecondDigits:1
+ suppressZeroSubSecondDigits:false
+ timeSeparator:$T timeOnly:false on:Transcript
+
+ Transcript cr. self
+ print:(Timestamp now)
+ compact:false asLocal:false asUTC:true
+ subSecondDigits:0
+ suppressZeroSubSecondDigits:false
+ timeSeparator:$T timeOnly:false on:Transcript
+ "
+
+ "Created: / 15-06-2005 / 17:56:51 / masca"
+!
+
print: aTimestamp compact:compact asLocal:asLocal asUTC:asUTC withMilliseconds:withMillis on: aStream
"Print the given timestamp in general ISO8601 format,
such as '2014-11-06T11:48:09Z'.
@@ -4229,7 +4363,9 @@
"Created: / 15-06-2005 / 17:56:51 / masca"
!
-print:aTimeOrTimestamp compact:compact asLocal:asLocal asUTC:asUTC withMilliseconds:withMillis timeSeparator:tSep timeOnly:timeOnly on:aStream
+print:aTimeOrTimestamp compact:compact asLocal:asLocal asUTC:asUTC
+ withMilliseconds:withMillis timeSeparator:tSep timeOnly:timeOnly on:aStream
+
"Print the given timestamp in general ISO8601 format,
such as '2014-11-06T11:48:09Z'.
compact: if true, the compact format (without separating dashes and colons is generated)
@@ -4241,56 +4377,21 @@
if utc: generate a utc string
otherwise it is a timestamp from another timezone (TZTimestamp), then print in its timezone
withMilliseconds: if false, no milliseconds are generated.
- if timeOnly is true, only the time is printed."
-
- |aTimestamp timeInfo millis |
-
- aTimestamp := aTimeOrTimestamp asTimestamp.
-
- asLocal ifTrue:[
- "/ force local
- timeInfo := aTimestamp asLocalTimestamp timeInfo.
- ] ifFalse:[
- asUTC ifTrue:[
- "/ force utc
- timeInfo := aTimestamp asUtcTimestamp timeInfo.
- ] ifFalse:[
- "/ in the timestamps own format
- timeInfo := aTimestamp timeInfo.
- ]
- ].
-
- timeOnly ifFalse:[
- timeInfo year printOn:aStream leftPaddedTo:4 with:$0.
- compact ifFalse:[ aStream nextPut: $- ].
- timeInfo month printOn:aStream leftPaddedTo:2 with:$0.
- compact ifFalse:[ aStream nextPut: $- ].
- timeInfo day printOn:aStream leftPaddedTo:2 with:$0.
- ].
- aStream nextPut:tSep.
- timeInfo hours printOn:aStream leftPaddedTo:2 with:$0.
- compact ifFalse:[ aStream nextPut: $:].
- timeInfo minutes printOn:aStream leftPaddedTo:2 with:$0.
-
- "always print the seconds, even if 0.
- According to http://www.w3.org/TR/xmlschema11-2/#dateTime this is mandatory"
-
- compact ifFalse:[ aStream nextPut: $:].
- timeInfo seconds printOn:aStream leftPaddedTo:2 with:$0.
-
- millis := withMillis ifTrue:[timeInfo milliseconds] ifFalse:[0].
- millis ~= 0 ifTrue:[
- aStream nextPut: $..
- millis printOn:aStream leftPaddedTo:3 with:$0.
- ].
-
- asUTC ifTrue:[
- aStream nextPut: $Z
- ] ifFalse:[
- asLocal ifFalse:[
- self printTimeZone:aTimestamp utcOffset on:aStream.
- ].
- ].
+ if timeOnly is true, only the time is printed.
+ Warning: this has a feature (a bug) of implicitly suppressing fractional seconds, if the millis are zero.
+ this is strange, but for backward compatibility, left as is
+ (in case some printout depends on it)"
+
+ |nDigits|
+
+ nDigits := withMillis ifTrue:[3] ifFalse:[0].
+ self
+ print:aTimeOrTimestamp
+ compact:compact asLocal:asLocal asUTC:asUTC
+ subSecondDigits:nDigits
+ suppressZeroSubSecondDigits:true
+ timeSeparator:tSep timeOnly:timeOnly on:aStream
+
"
self print:(Timestamp now) on:Transcript