Time.st
branchjv
changeset 18457 214d760f8247
parent 18120 e3a375d5f6a8
parent 18456 74744af7f90d
child 19863 513bd7237fe7
--- a/Time.st	Sat Jun 06 06:39:31 2015 +0200
+++ b/Time.st	Sun Jun 07 06:38:49 2015 +0200
@@ -1,5 +1,3 @@
-"{ Encoding: utf8 }"
-
 "
  COPYRIGHT (c) 1989 by Claus Gittinger
 	      All Rights Reserved
@@ -187,6 +185,133 @@
     "
 !
 
+readFrom:aStringOrStream format:formatString language:languageOrNil onError:exceptionalValue
+    "return a new Time, reading a printed representation from aStream using a formatString.
+     The formatString is similar to the one used when printing.
+     On error, exceptionalValue is returned.
+     If exceptionalValue is a one-arg block, an error message is passed as argument.
+     Format:
+        %h      hours, 00..23 (i.e. european)  0-padded to length 2
+        %u      hours, 00..12 (i.e. us)        0-padded to length 2
+        %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
+        %a      am/pm
+
+     an optional length after the % gives a field length;
+        i.e. %2h%2m%2s parses '123557' as 12:35:37
+
+     Please consider using a standard format, such as iso8601.
+    "
+
+    |hour minute second millisecond
+     utcOffset inStream formatStream error fChar format itemHandler
+     len s|
+
+    error := [:msg |
+                exceptionalValue isBlock ifTrue:[
+                    ^ exceptionalValue valueWithOptionalArgument:'format error'
+                ] ifFalse:[
+                    ^ exceptionalValue value
+                ].
+             ].
+
+    itemHandler := [:format |
+        |input|
+
+        input := len isNil ifTrue:[ inStream ] ifFalse:[ inStream next: len ].
+
+        ( format = 'h' or:[ format = 'H' ]) ifTrue:[
+            hour := Integer readFrom:input onError:[ error value:'invalid hour' ].
+
+        ] ifFalse:[ ( format = 'u'  or:[ format = 'U']) ifTrue:[
+            hour := Integer readFrom:input onError:[ error value:'invalid hour' ].
+
+        ] ifFalse:[ ( format = 'm'  or:[ format = 'M' ]) ifTrue:[
+            minute := Integer readFrom:input onError:[ error value:'invalid minute' ].
+
+        ] ifFalse:[ ( format = 's'  or:[ format = 'S' ]) ifTrue:[
+            second := Integer readFrom:input onError:[ error value:'invalid second' ].
+
+        ] ifFalse:[ ( format = 'i'  or:[ format = 'I' ]) ifTrue:[
+            millisecond := Integer readFrom:input onError:[ error value:'invalid millsecond' ].
+
+        ] ifFalse:[ ( format = 'tz' ) ifTrue:[
+            utcOffset := Timestamp utcOffsetFrom:input.
+            utcOffset isNil ifTrue:[ error value:'invalid timezone' ]
+        ] ifFalse:[ ( format = 'a' ) ifTrue:[
+            s := (input next:2) asLowercase.
+            s = 'am' ifTrue:[
+                (hour between:0 and:12) ifFalse:[ error value:'invalid hour' ]
+            ] ifFalse:[
+                s = 'pm' ifTrue:[
+                    (hour between:1 and:12) ifFalse:[ error value:'invalid hour' ].
+                    hour := hour + 12.
+                ] ifFalse:[
+                    error value:'invalid am/pm'
+                ]
+            ]
+
+        ] ifFalse:[
+            error value:'unhandled format:',format
+        ]]]]]]]
+    ].
+
+    hour := 0.
+    minute := 0.
+    second := 0.
+    millisecond := 0.
+    utcOffset := 0.
+
+    inStream := aStringOrStream readStream.
+    formatStream := formatString readStream.
+
+    [formatStream atEnd] whileFalse:[
+        fChar := formatStream next.
+        fChar = Character space ifTrue:[
+            inStream peek isSeparator ifFalse:[ error value: 'format error; space expcected' ].
+            inStream skipSeparators.
+        ] ifFalse:[
+            fChar == $% ifTrue:[
+                len := nil.
+                (formatStream peek isDigit) ifTrue:[
+                    len := Integer readFrom:formatStream onError:[ error value: 'format error; invalid length' ]
+                ].
+                (formatStream peek == $() ifTrue:[
+                    formatStream next.
+                    format := formatStream upTo:$).
+                ] ifFalse:[
+                    (formatStream peek == ${) ifTrue:[
+                        formatStream next.
+                        format := formatStream upTo:$}.
+                    ] ifFalse:[
+                        (formatStream peek isLetter) ifTrue:[
+                            format := formatStream nextAlphaNumericWord.
+                        ] ifFalse:[
+                            error value:'unhandled format:',formatStream peek
+                        ]
+                    ]
+                ].
+                itemHandler value:format.
+            ] ifFalse:[
+                inStream peek = fChar ifFalse:[^ error value: 'format error; ',fChar,' expcected'].
+                inStream next.
+            ]
+        ].
+    ].
+
+    ^ (self 
+        hours:(hour ? 0) minutes:(minute ? 0) seconds:(second ? 0) milliseconds:millisecond) 
+            + utcOffset
+
+    "
+     Time readFrom:'13:11:06' format:'%h:%m:%s' language:nil onError:[self halt]
+     Time readFrom:'131106' format:'%2h%2m%2s' language:nil onError:[self halt]
+     Time readFrom:'7:30pm EST' format:'%u:%m%a %tz' language:#en onError:[self halt]
+     Time readFrom:'7:30pm UTC' format:'%u:%m%a %tz' language:#en onError:[self halt]
+    "
+!
+
 readFrom:aStringOrStream onError:exceptionBlock
     "return a new Time, reading a printed representation from aStream.
      If no am/pm follows the time, the string is interpreted as
@@ -707,7 +832,6 @@
     "
 ! !
 
-
 !Time methodsFor:'printing & storing'!
 
 print12HourFormatOn:aStream
@@ -953,10 +1077,10 @@
 !Time class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Time.st,v 1.103 2015-03-24 07:20:13 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Time.st,v 1.104 2015-06-06 12:57:19 cg Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/Time.st,v 1.103 2015-03-24 07:20:13 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Time.st,v 1.104 2015-06-06 12:57:19 cg Exp $'
 ! !