#FEATURE by cg
authorClaus Gittinger <cg@exept.de>
Mon, 14 May 2018 21:38:54 +0200
changeset 22926 663fa103b1e9
parent 22925 9748ba089af4
child 22927 6dab5d9ece9d
#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.
Timestamp.st
--- 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