Time.st
branchjv
changeset 18120 e3a375d5f6a8
parent 18011 deb0c3355881
parent 17641 e28a4212f412
child 18457 214d760f8247
--- a/Time.st	Tue Feb 04 21:09:59 2014 +0100
+++ b/Time.st	Wed Apr 01 10:20:10 2015 +0100
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
 "
  COPYRIGHT (c) 1989 by Claus Gittinger
 	      All Rights Reserved
@@ -11,6 +13,8 @@
 "
 "{ Package: 'stx:libbasic' }"
 
+"{ NameSpace: Smalltalk }"
+
 AbstractTime subclass:#Time
 	instanceVariableNames:'timeEncoding'
 	classVariableNames:''
@@ -38,7 +42,7 @@
 "
     Instances of time represent a particular time-of-day.
     Since they only store hours, minutes and seconds within a day,
-    they cannot be used to compare times across midnight 
+    they cannot be used to compare times across midnight
     (i.e. they should not be used as timeStamps).
 
     Use instances of Timestamp (and read the comment there) to do this.
@@ -46,6 +50,19 @@
     Time now returns the time in the local timezone.
     Use Time utcNow to get the time in the UTC zone.
 
+    Note: time was changed recently to keep the number of milliseconds since midnight.
+          However, all existing instance creators so far only create time instances with 0-millis.
+          I.e. Time now still returns a time with second precision.
+
+          It is not done currently, to remain backward compatible, as users may get confused
+          to see t1 > t2 although they print the same (as long as the printed representation does not
+          include the milli seconds).
+          On the other side: a change of the default printformat is not done now, 
+          as it may affect many existing applications.
+
+          Any application which needs the millisecond precision time should call the new
+            Time nowWithMilliseconds.
+
     Examples:
         |t|
 
@@ -58,7 +75,7 @@
         t1 := Time now.
         (Delay forSeconds:10) wait.
         t2 := Time now.
-        t2 - t1   
+        t2 - t1
 
     [author:]
         Claus Gittinger
@@ -83,7 +100,7 @@
     ^ self hours:h minutes:m seconds:0
 
     "
-     Time hour:2 minute:33 
+     Time hour:2 minute:33
     "
 !
 
@@ -93,7 +110,7 @@
     ^ self hours:h minutes:m seconds:s
 
     "
-     Time hour:2 minute:33 second:0 
+     Time hour:2 minute:33 second:0
     "
 !
 
@@ -109,10 +126,10 @@
     ^ self hours:h minutes:m seconds:s
 
     "
-     Time hours:2 minutes:33 seconds:0 
-     Time hours:0 minutes:0 seconds:0 
-     Time hours:24 minutes:0 seconds:0 
-     Time hours23 minutes:59 seconds:59 
+     Time hours:2 minutes:33 seconds:0
+     Time hours:0 minutes:0 seconds:0
+     Time hours:24 minutes:0 seconds:0
+     Time hours23 minutes:59 seconds:59
     "
 
     "Modified: 19.4.1996 / 15:32:40 / cg"
@@ -125,10 +142,26 @@
     ^ self basicNew setHours:h minutes:m seconds:s
 
     "
-     Time hours:2 minutes:33 seconds:0 
-     Time hours:0 minutes:0 seconds:0 
-     Time hours:24 minutes:0 seconds:0 
-     Time hours:23 minutes:59 seconds:59 
+     Time hours:2 minutes:33 seconds:0
+     Time hours:0 minutes:0 seconds:0
+     Time hours:24 minutes:0 seconds:0
+     Time hours:23 minutes:59 seconds:59
+    "
+
+    "Modified: 19.4.1996 / 15:32:40 / cg"
+!
+
+hours:h minutes:m seconds:s milliseconds:ms
+    "return an instance of Time representing the given time.
+     See also Time now / Date today / Timestamp now."
+
+    ^ self basicNew setHours:h minutes:m seconds:s milliseconds:ms
+
+    "
+     Time hours:2 minutes:33 seconds:0
+     Time hours:0 minutes:0 seconds:0
+     Time hours:24 minutes:0 seconds:0
+     Time hours:23 minutes:59 seconds:59
     "
 
     "Modified: 19.4.1996 / 15:32:40 / cg"
@@ -156,117 +189,128 @@
 
 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 
+     If no am/pm follows the time, the string is interpreted as
      either 24 hour format or being am."
 
     ^ [
-        |str hour min sec peekC|
+	|str hour min sec peekC millis|
 
-        str := aStringOrStream readStream.
+	str := aStringOrStream readStream.
 
-        hour := Integer readFrom:str.
-        (hour between:0 and:24) ifFalse:[^ exceptionBlock value].
+	hour := Integer readFrom:str.
+	(hour between:0 and:24) ifFalse:[^ exceptionBlock value].
 
-        min := 0.
-        sec := 0.
-        str atEnd ifFalse:[
-            peekC := str peek.
-            (peekC == $:) ifTrue:[
-                str next.
-                min := Integer readFrom:str.
-                (min between:0 and:59) ifFalse:[^ exceptionBlock value].
+	min := 0.
+	sec := 0.
+	millis := 0.
+
+	str atEnd ifFalse:[
+	    peekC := str peek.
+	    (peekC == $:) ifTrue:[
+		str next.
+		min := Integer readFrom:str.
+		(min between:0 and:59) ifFalse:[^ exceptionBlock value].
 
-                (str peek == $:) ifTrue:[
-                    str next.
-                    sec := Integer readFrom:str.
-                    (sec between:0 and:59) ifFalse:[^ exceptionBlock value].
-                ].
-                peekC := str peek.
-            ].
-            [peekC == Character space] whileTrue:[str next. peekC := str peek].
-            (peekC == $p or:[peekC == $P]) ifTrue:[
-                str next.
-                (str peek == $m or:[str peek == $M]) ifTrue:[
-                    str next
-                ].
-                (hour <= 0 or:[hour > 12]) ifTrue:[^ exceptionBlock value].
+		(str peek == $:) ifTrue:[
+		    str next.
+		    sec := Integer readFrom:str.
+		    (sec between:0 and:59) ifFalse:[^ exceptionBlock value].
+		    (str peek == $.) ifTrue:[
+			str next.
+			millis := ((Fraction readDecimalFractionFrom:str onError:[^ exceptionBlock value]) * 1000) asInteger.
+		    ].
+		].
+		peekC := str peek.
+	    ].
+	    [peekC == Character space] whileTrue:[str next. peekC := str peek].
+	    (peekC == $p or:[peekC == $P]) ifTrue:[
+		str next.
+		(str peek == $m or:[str peek == $M]) ifTrue:[
+		    str next
+		].
+		(hour <= 0 or:[hour > 12]) ifTrue:[^ exceptionBlock value].
 
-                "pm"
-                hour ~~ 12 ifTrue:[
-                    hour := hour + 12
-                ].
-                peekC := str peek
-            ] ifFalse:[
-                (peekC == $a or:[peekC == $A]) ifTrue:[
-                    str next.
-                    (str peek == $m or:[str peek == $M]) ifTrue:[
-                        str next
-                    ].
-                    hour == 12 ifTrue:[
-                        hour := 0.
-                    ].
-                    hour > 12 ifTrue:[^ exceptionBlock value].
-                    peekC := str peek
-                ] ifFalse:[
-                    "/ cg: dont be too picky here - we do not care, what comes after the
-                    "/ time string. (Needed to be able to read rfc822 strings where a timezone
-                    "/ follows (-/+0700 GMT, for example)
+		"pm"
+		hour ~~ 12 ifTrue:[
+		    hour := hour + 12
+		].
+		peekC := str peek
+	    ] ifFalse:[
+		(peekC == $a or:[peekC == $A]) ifTrue:[
+		    str next.
+		    (str peek == $m or:[str peek == $M]) ifTrue:[
+			str next
+		    ].
+		    hour == 12 ifTrue:[
+			hour := 0.
+		    ].
+		    hour > 12 ifTrue:[^ exceptionBlock value].
+		    peekC := str peek
+		] ifFalse:[
+		    "/ cg: dont be too picky here - we do not care, what comes after the
+		    "/ time string. (Needed to be able to read rfc822 strings where a timezone
+		    "/ follows (-/+0700 GMT, for example)
 "/                    peekC notNil ifTrue:[
 "/                        peekC isSeparator ifFalse:[^ exceptionBlock value].
 "/                    ]
-                ].
-            ]
-        ].
-        self basicNew setHours:hour minutes:min seconds:sec
+		].
+	    ]
+	].
+	self basicNew setHours:hour minutes:min seconds:sec milliseconds:millis
     ] on:Error do:exceptionBlock.
 
     "
-     Time readFrom:'0:00'     
-     Time readFrom:'2:00'     
-     Time readFrom:'12:00'    
-     Time readFrom:'14:00'    
-     Time readFrom:'23:00'    
-     Time readFrom:'24:00'    
-     Time readFrom:'2:30 am'    
-     Time readFrom:'2:30 pm'    
-     Time readFrom:'14'    
-     Time readFrom:'2 am'    
-     Time readFrom:'2 pm'    
-     Time readFrom:'12:05 pm'    
-     Time readFrom:'12:06 am'    
+     Time readFrom:'0:00'
+     Time readFrom:'2:00'
+     Time readFrom:'12:00'
+     Time readFrom:'14:00'
+     Time readFrom:'23:00'
+     Time readFrom:'24:00'
+     Time readFrom:'2:30 am'
+     Time readFrom:'2:30 pm'
+     Time readFrom:'14'
+     Time readFrom:'2 am'
+     Time readFrom:'2 pm'
+     Time readFrom:'12:05 pm'
+     Time readFrom:'12:06 am'
 
-     Time readFrom:'18:22:00'    
-     Time readFrom:'14:00:11'    
-     Time readFrom:'7:00:11'     
-     Time readFrom:'24:00:00'     
-     Time readFrom:'0:00:00'     
-     Time readFrom:'12:00:00'     
-     Time readFrom:'0:00:00'     
-     Time readFrom:'6:22:00 pm'   
-     Time readFrom:'2:00:11 pm'  
-     Time readFrom:'7:00:11 am'  
-     Time readFrom:'12:00:00 am'  
-     Time readFrom:'0:00:00 am'  
-     Time readFrom:'24:00:00 am'  
-     Time readFrom:'12:00:00 pm'  
+     Time readFrom:'18:22:00'
+     Time readFrom:'14:00:11'
+     Time readFrom:'7:00:11'
+     Time readFrom:'24:00:00'
+     Time readFrom:'0:00:00'
+     Time readFrom:'12:00:00'
+     Time readFrom:'0:00:00'
+     Time readFrom:'6:22:00 pm'
+     Time readFrom:'2:00:11 pm'
+     Time readFrom:'7:00:11 am'
+     Time readFrom:'12:00:00 am'
+     Time readFrom:'0:00:00 am'
+     Time readFrom:'24:00:00 am'
+     Time readFrom:'12:00:00 pm'
      Time readFrom:'0:00:00 pm' onError:'invalid'
-     Time readFrom:'24:00:00 pm'  
+     Time readFrom:'24:00:00 pm'
+
+     Time readFrom:'13:00:00.5'
+     Time readFrom:'13:00:00.123'
+     Time readFrom:'1:00:00.123 pm'
     "
 
     "Modified: 8.10.1996 / 19:32:11 / cg"
 !
 
 utcNow
-    "return an instance of myself representing this moment."
+    "return an instance of myself representing this moment in UTC.
+     That is, the current time in London without any daylight saving adjustments."
 
     ^ self basicNew fromUtcOSTime:(OperatingSystem getOSTime)
 
     "
-     Timestamp now   
+     Timestamp now
      Timestamp utcNow
 
-     Time now   
-     Time utcNow   
+     Time now
+     Time utcNow
     "
 
     "Modified: 1.7.1996 / 15:20:10 / cg"
@@ -275,15 +319,26 @@
 !Time class methodsFor:'format strings'!
 
 defaultFormatString
+    "a language specific format string to present times in user interfaces.
+     Do not use this to store/retrieve times (use ISO8601 for that)"
+
     LanguageTerritory == #us ifTrue:[
-        ^ self formatString12us
+	^ self formatString12us
     ] ifFalse:[
-        ^ self formatString24
+	^ self formatString24
     ]
 
     "Created: / 16-01-2011 / 11:23:36 / cg"
 !
 
+defaultFormatStringWithMilliseconds
+    LanguageTerritory == #us ifTrue:[
+	^ self formatStringWithMilliseconds12us
+    ] ifFalse:[
+	^ self formatStringWithMilliseconds24
+    ]
+!
+
 formatString12us
     "return the format string used to format US times (and other areas)"
 
@@ -294,18 +349,41 @@
     "return the format string used to format non US times"
 
     ^ '%h:%m:%s'
+!
+
+formatStringWithMilliseconds12us
+    "return the format string used to format US times (and other areas)"
+
+    ^ '%u:%m:%s.%i %A'
+!
+
+formatStringWithMilliseconds24
+    "return the format string used to format non US times"
+
+    ^ '%h:%m:%s.%i'
+! !
+
+!Time methodsFor:'Compatibility-Backward'!
+
+asMilliSeconds
+    <resource: #obsolete>
+    "return the number of milliseconds elapsed since midnight"
+
+    ^ self asMilliseconds
+
+    "
+     Time now asMilliSeconds
+     (TimeDuration days:1) asMilliSeconds
+     (TimeDuration hours:1) asMilliSeconds
+    "
+
+    "Created: / 05-09-2011 / 10:40:15 / cg"
 ! !
 
 !Time methodsFor:'Compatibility-Squeak'!
 
-asMilliseconds
-    ^ self asMilliSeconds
-
-    "Created: / 05-09-2011 / 14:56:36 / cg"
-!
-
 intervalString
-    "Treat the time as a difference.  
+    "Treat the time as a difference.
      Give it in hours and minutes with two digits of accuracy."
 
     |hours minutes seconds hh mm ss s|
@@ -314,55 +392,55 @@
     minutes := self minutes.
     seconds := self seconds.
 
-    hours = 0   
-        ifTrue: [hh := ''] 
-        ifFalse: [
-            hh := hours printString, ' hour'.
-            hours > 1 ifTrue:[
-                hh := hh , 's'
-            ]
-        ].
-    minutes = 0 
-        ifTrue: [mm := ''] 
-        ifFalse: [
-            mm := minutes printString, ' minute'.
-            minutes > 1 ifTrue:[
-                mm := mm , 's'
-            ]
-        ].
-    seconds = 0 
-        ifTrue: [ss := ''] 
-        ifFalse: [
-            ss := seconds printString, ' second'.
-            seconds > 1 ifTrue:[
-                ss := ss , 's'
-            ]
-        ].
+    hours = 0
+	ifTrue: [hh := '']
+	ifFalse: [
+	    hh := hours printString, ' hour'.
+	    hours > 1 ifTrue:[
+		hh := hh , 's'
+	    ]
+	].
+    minutes = 0
+	ifTrue: [mm := '']
+	ifFalse: [
+	    mm := minutes printString, ' minute'.
+	    minutes > 1 ifTrue:[
+		mm := mm , 's'
+	    ]
+	].
+    seconds = 0
+	ifTrue: [ss := '']
+	ifFalse: [
+	    ss := seconds printString, ' second'.
+	    seconds > 1 ifTrue:[
+		ss := ss , 's'
+	    ]
+	].
 
     "/ do not show seconds, if hours are there
     hh size > 0 ifTrue: [ss := ''].
 
     s := hh.
     mm notEmpty ifTrue:[
-        s notEmpty ifTrue:[
-            s := s , ' '
-        ].
-        s := s , mm.
+	s notEmpty ifTrue:[
+	    s := s , ' '
+	].
+	s := s , mm.
     ].
     ss notEmpty ifTrue:[
-        s notEmpty ifTrue:[
-            s := s , ' '
-        ].
-        s := s , ss
+	s notEmpty ifTrue:[
+	    s := s , ' '
+	].
+	s := s , ss
     ].
     ^ s
 
     "
-     (Time fromSeconds:3600) intervalString     
-     (Time fromSeconds:3605) intervalString    
-     (Time fromSeconds:3700) intervalString    
-     (Time fromSeconds:5) intervalString       
-     (Time fromSeconds:65) intervalString      
+     (Time fromSeconds:3600) intervalString
+     (Time fromSeconds:3605) intervalString
+     (Time fromSeconds:3700) intervalString
+     (Time fromSeconds:5) intervalString
+     (Time fromSeconds:65) intervalString
     "
 !
 
@@ -384,22 +462,22 @@
     |format|
 
     prnt24Format ifTrue:[
-        doSeconds ifTrue:[
-            format := '%h:%m:%s'
-        ] ifFalse:[
-            format := '%h:%m'
-        ].
+	doSeconds ifTrue:[
+	    format := '%h:%m:%s'
+	] ifFalse:[
+	    format := '%h:%m'
+	].
     ] ifFalse:[
-        "/ US format
-        doSeconds ifTrue:[
-            format := '%u:%m:%s %a'
-        ] ifFalse:[
-            format := '%u:%m %a'
-        ].
+	"/ US format
+	doSeconds ifTrue:[
+	    format := '%u:%m:%s %a'
+	] ifFalse:[
+	    format := '%u:%m %a'
+	].
     ].
     ^ self
-        printOn:aStream 
-        format:format.
+	printOn:aStream
+	format:format.
 
     "
      Time now print24:true showSeconds:true on:Transcript. Transcript cr.
@@ -422,10 +500,11 @@
 !
 
 milliseconds
-    "time does not keep milliseconds 
-     - for compatibility with Timestamp"
+    "get the milliseconds part
+     (notice: that is NOT the total number of millis (since midnight),
+     but the fractional part only. Use this only for printing"
 
-    ^ 0
+    ^ timeEncoding \\ 1000
 !
 
 minutes
@@ -452,7 +531,7 @@
     "answer the number of minutes between local time and utc time.
      Delta is positive if local time is ahead of utc, negative if behind utc.
 
-     Time is local time, so answer the delta of today"
+     Time is local time, so ask a local timestamp"
 
     ^ Timestamp now timeZoneDeltaInMinutes
 
@@ -467,31 +546,91 @@
 < aTime
     "return true if the receiver is before the argument"
 
+    |milliseconds|
+
     aTime class == self class ifTrue:[
         ^ timeEncoding < aTime timeEncoding
     ].
-    ^ self getSeconds < aTime getSeconds
+    aTime isNumber ifTrue:[
+        "backward compatibility for old code, which expects (time1 - time2) to return seconds"    
+        milliseconds := (aTime * 1000) asInteger.   "integer seconds"
+    ] ifFalse:[
+        milliseconds := aTime getMilliseconds.
+    ].
+    ^ self getMilliseconds < milliseconds
+
+    "
+        (Timestamp now + 10) - Timestamp now  < 10
+        (Timestamp now + 10) - Timestamp now  < 11
+    "
+!
+
+<= aTime
+    "return true if the receiver is before the argument"
+
+    |milliseconds|
+
+    aTime class == self class ifTrue:[
+        ^ timeEncoding <= aTime timeEncoding
+    ].
+    aTime isNumber ifTrue:[
+        "backward compatibility for old code, which expects (time1 - time2) to return seconds"    
+        milliseconds := (aTime * 1000) asInteger.   "integer seconds"
+    ] ifFalse:[
+        milliseconds := aTime getMilliseconds.
+    ].
+    ^ self getMilliseconds <= milliseconds
+
+    "
+        (Timestamp now + 10) - Timestamp now  <= 10
+        (Timestamp now + 10) - Timestamp now  <= 11
+        (Timestamp now + 10) - Timestamp now  <= 9
+    "
 !
 
 = aTime
     "return true if the argument, aTime represents the same timeOfDay"
 
+    |milliseconds|
+
     aTime class == self class ifTrue:[
         ^ timeEncoding = aTime timeEncoding
     ].
-    (aTime species == self species) ifFalse:[^ false].
-    ^ self getSeconds = aTime getSeconds
+    aTime isNumber ifTrue:[
+        "backward compatibility for old code, which expects (time1 - time2) to return seconds"    
+        milliseconds := (aTime * 1000) asInteger.   "integer seconds"
+    ] ifFalse:[
+        aTime species == self species ifFalse:[^ false].
+        milliseconds := aTime getMilliseconds.
+    ].
+    ^ self getMilliseconds = milliseconds
 
-    "Modified: / 18-07-2007 / 14:16:34 / cg"
+    "
+        (Timestamp now + 10) - Timestamp now  = 10
+        (Timestamp now + 10) - Timestamp now  = 9
+    "
 !
 
 > aTime
     "return true if the receiver is before the argument"
 
+    |milliseconds|
+
     aTime class == self class ifTrue:[
         ^ timeEncoding > aTime timeEncoding
     ].
-    ^ self getSeconds > aTime getSeconds
+    aTime isNumber ifTrue:[
+        "backward compatibility for old code, which expects (time1 - time2) to return seconds"    
+        milliseconds := (aTime * 1000) asInteger.   "integer seconds"
+    ] ifFalse:[
+        milliseconds := aTime getMilliseconds.
+    ].
+    ^ self getMilliseconds > milliseconds
+
+    "
+        (Timestamp now + 10) - Timestamp now  > 10
+        (Timestamp now + 10) - Timestamp now  > 9
+    "
 !
 
 hash
@@ -521,33 +660,8 @@
     "
 !
 
-asMilliSeconds
-    "return the number of milliseconds elapsed since midnight"
-
-    ^ self getMilliseconds
-
-    "
-     Time now asMilliSeconds
-     (TimeDuration days:1) asMilliSeconds 
-     (TimeDuration hours:1) asMilliSeconds 
-    "
-
-    "Created: / 05-09-2011 / 10:40:15 / cg"
-!
-
-asSeconds
-    "return the number of seconds elapsed since midnight"
-
-    ^ self getSeconds
-
-    "
-     Time now asSeconds
-     (TimeDuration days:1) asSeconds 
-    "
-!
-
 asTime
-    "return a Time object from the receiver - thats the receiver."
+    "return a Time object from the receiver - that's the receiver."
 
     ^ self
 !
@@ -555,11 +669,11 @@
 asTimeDuration
     "return an TimeDuration object from the receiver, taking the time since midnight."
 
-    ^ TimeDuration 
-                   hours:(self hours) minutes:(self minutes) seconds:(self seconds)
-                   milliseconds:(self milliseconds)
+    ^ TimeDuration
+		   hours:(self hours) minutes:(self minutes) seconds:(self seconds)
+		   milliseconds:(self milliseconds)
     "
-     Time now asTimeDuration 
+     Time now asTimeDuration
     "
 !
 
@@ -581,18 +695,19 @@
 
     |todayTimestamp|
 
-    todayTimestamp := UtcTimestamp now.
+    todayTimestamp := Timestamp now.
     todayTimestamp year:todayTimestamp year month:todayTimestamp month day:todayTimestamp day
-                   hour:(self hours) minute:(self minutes) second:(self seconds)
-                   millisecond:(self milliseconds).
+		   hour:(self hours) minute:(self minutes) second:(self seconds)
+		   millisecond:(self milliseconds).
 
-    ^ todayTimestamp.
+    ^ todayTimestamp asUtcTimestamp.
 
     "
-      Time now asUtcTimestamp
+     Time now asUtcTimestamp
     "
 ! !
 
+
 !Time methodsFor:'printing & storing'!
 
 print12HourFormatOn:aStream
@@ -600,8 +715,8 @@
      Format is hh:mm:ss am/pm (i.e. 12-hour american format)."
 
     ^ self
-        printOn:aStream 
-        format:(self class formatString12us)
+	printOn:aStream
+	format:(self class formatString12us)
 
 "/    |h m s ampm|
 "/
@@ -638,7 +753,7 @@
      (Time hour:12 minutes:0 seconds:0) print12HourFormatOn:Transcript. Transcript cr
      (Time hour:0 minutes:0 seconds:0) print12HourFormatOn:Transcript. Transcript cr
      0 to:24 do:[:h |
-         (Time hour:h minutes:0 seconds:0) print12HourFormatOn:Transcript. Transcript cr
+	 (Time hour:h minutes:0 seconds:0) print12HourFormatOn:Transcript. Transcript cr
      ]
     "
 !
@@ -648,8 +763,8 @@
      Format is hh:mm:ss (i.e. 24-hour european format)."
 
     ^ self
-        printOn:aStream 
-        format:(self class formatString24).
+	printOn:aStream
+	format:(self class formatString24).
 
 "/    |h m s|
 "/
@@ -676,11 +791,16 @@
 
      Format is hh:mm:ss either in 12-hour or 24-hour format.
      depending on the setting of LanguageTerritory.
-     I dont know what ST-80 does here (12-hour format ?)"
+     I don't know what ST-80 does here (12-hour format ?)"
+
+    |format|
 
+    format := (self milliseconds = 0)
+                    ifTrue:[self class defaultFormatString]
+                    ifFalse:[self class defaultFormatStringWithMilliseconds].
     ^ self
-        printOn:aStream 
-        format:(self class defaultFormatString)               
+        printOn:aStream
+        format:format
 
     "
      Time now printOn:Transcript. Transcript cr
@@ -692,7 +812,7 @@
 printString12HourFormat
     "return a printed representation in 12 hour format"
 
-    ^ self printStringFormat:(self class formatString12us)               
+    ^ self printStringFormat:(self class formatString12us)
 
     "
      Time now printString12HourFormat
@@ -702,7 +822,7 @@
 printString24HourFormat
     "return a printed representation in 24 hour format"
 
-    ^ self printStringFormat:(self class formatString24)               
+    ^ self printStringFormat:(self class formatString24)
 
     "
      Time now printString24HourFormat
@@ -731,6 +851,15 @@
     "Modified: 1.7.1996 / 15:21:06 / cg"
 !
 
+fromOSTimeWithMilliseconds:osTime
+    "set my time in the local timezone, given an osTime"
+
+    |i|
+
+    i := OperatingSystem computeTimeAndDateFrom:osTime.
+    self setHours:(i hours) minutes:(i minutes) seconds:(i seconds) milliseconds:(i milliseconds)
+!
+
 fromUtcOSTime:osTime
     "set my time in the local timezone, given an osTime"
 
@@ -745,13 +874,13 @@
 getMilliseconds
     "return the number of milliseconds since midnight"
 
-    ^ self getSeconds * 1000
+    ^ timeEncoding
 !
 
 getSeconds
     "return the number of seconds since midnight"
 
-    ^ timeEncoding
+    ^ timeEncoding // 1000
 !
 
 setHours:h minutes:m seconds:s
@@ -760,10 +889,34 @@
     self setSeconds:(((h\\24) * 60 * 60 ) + (m * 60) + s).
 !
 
+setHours:h minutes:m seconds:s milliseconds:ms
+    "set my time given individual values"
+
+    self setMilliseconds:((((h\\24) * 60 * 60 ) + (m * 60) + s) * 1000) + ms.
+!
+
 setMilliseconds:millis
-    "set my time given milliseconds since midnight"
+    "set my time given milliseconds since midnight.
+     Notice the modulo operations here - there cannot be a time beyond 24hours
+     (use TimeDuration, if you need that)."
 
-    self setSeconds:(millis // 1000)
+    millis < 0 ifTrue:[
+	timeEncoding := (24 * 3600 * 1000) - (millis negated \\ (24 * 3600 * 1000))
+    ] ifFalse:[
+	timeEncoding := millis
+    ].
+    timeEncoding >= (24 * 3600 * 1000) ifTrue:[
+	timeEncoding := timeEncoding \\ (24 * 3600 * 1000).
+    ]
+
+    "
+     Time basicNew setSeconds:0
+     Time fromSeconds:3601
+     Time now seconds
+     Time now timeEncoding
+     (Time now addDays:5) seconds
+     (Time now addDays:5) timeEncoding
+    "
 !
 
 setSeconds:secs
@@ -771,34 +924,27 @@
      Notice the modulo operations here - there cannot be a time beyond 24hours
      (use TimeDuration, if you need that)."
 
-    secs < 0 ifTrue:[
-        timeEncoding := (24 * 3600) - (secs negated \\ (24 * 3600))
-    ] ifFalse:[
-        timeEncoding := secs
-    ].
-    timeEncoding > (24 * 3600) ifTrue:[
-        timeEncoding := timeEncoding \\ (24 * 3600).
-    ]
+    self setMilliseconds:secs * 1000
 
     "
-     Time basicNew setSeconds:0 
-     Time fromSeconds:3601  
+     Time basicNew setSeconds:0
+     Time fromSeconds:3601
      Time now seconds
      Time now timeEncoding
-     (Time now addDays:5) seconds     
+     (Time now addDays:5) seconds
      (Time now addDays:5) timeEncoding
     "
 !
 
 timeEncoding
-    "the internal encoding is stricktly private, 
+    "the internal encoding is stricktly private,
      and should not be used outside."
 
     ^ timeEncoding
 !
 
 timeEncoding:encoding
-    "the internal encoding is stricktly private, 
+    "the internal encoding is stricktly private,
      and should not be used outside."
 
     timeEncoding := encoding
@@ -807,9 +953,10 @@
 !Time class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Time.st,v 1.92 2011-09-05 13:03:28 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Time.st,v 1.103 2015-03-24 07:20:13 cg Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/Time.st,v 1.92 2011-09-05 13:03:28 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Time.st,v 1.103 2015-03-24 07:20:13 cg Exp $'
 ! !
+