class: TimeDuration
authorClaus Gittinger <cg@exept.de>
Thu, 17 Apr 2014 00:20:35 +0200
changeset 16356 d9c6b891d04c
parent 16355 cff880538e3e
child 16357 db103fed28a4
class: TimeDuration added: #asTimeDuration #isTimeDuration removed: #- comment/format in: #asTime changed: #formatForPrinting: fix for durations > 24hr
TimeDuration.st
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TimeDuration.st	Thu Apr 17 00:20:35 2014 +0200
@@ -0,0 +1,1088 @@
+"
+ COPYRIGHT (c) 1989 by Claus Gittinger
+	      All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+"
+"{ Package: 'stx:libbasic2' }"
+
+Time subclass:#TimeDuration
+	instanceVariableNames:''
+	classVariableNames:'TimeDurationZero DefaultFormatForPrinting'
+	poolDictionaries:''
+	category:'Magnitude-Time'
+!
+
+!TimeDuration class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 1989 by Claus Gittinger
+	      All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+"
+!
+
+documentation
+"
+    Represents a timestap difference.
+
+    DefaultFormatForPrinting    if non-nil, allows for the variable printFormat to be overwritten
+"
+! !
+
+!TimeDuration class methodsFor:'instance creation'!
+
+days:d 
+    "return a new TimeDuration representing a duration of d days."
+
+    d == 0 ifTrue:[^ TimeDurationZero].
+    ^ self hours:(d*24) minutes:0
+
+    "
+     TimeDuration days:1  
+    "
+!
+
+days:d hours:h minutes:m seconds:s 
+    "return a new TimeDuration representing a duration of d days, h hours, m minutes and s seconds.
+     See also Time now / Date today / Timestamp now."
+
+    ^ self basicNew 
+        setHours:(d*24)+h minutes:m seconds:s milliseconds:0
+
+    "
+     TimeDuration days:1  hours:2 minutes:33 seconds:0   
+     TimeDuration days:4 hours:100 minutes:33 seconds:0   
+    "
+!
+
+fromHours:hoursInterval
+    "return a new TimeDuration representing a duration of n hours."
+
+    ^ self new setSeconds:(hoursInterval * (60*60))
+
+    "
+     TimeDuration fromHours:8  
+    "
+!
+
+fromMilliseconds:n
+    "return a new TimeDuration representing a duration of n milliseconds."
+    "redefined to disable wrapping at 24hours."
+
+    ^ self new setMilliseconds:n
+
+    "
+     TimeDuration fromMilliseconds:500  
+     500 milliseconds  
+    "
+
+    "Created: / 18-07-2007 / 13:56:25 / cg"
+!
+
+fromMinutes:minutesInterval
+    "return a new TimeDuration representing a duration of n minutes."
+
+    ^ self new setSeconds:(minutesInterval * 60)
+
+    "
+     TimeDuration fromMinutes:120  
+    "
+!
+
+fromSeconds:secondsInterval
+    "return a new TimeDuration representing a duration of n seconds."
+    "redefined to disable wrapping at 24hours."
+
+    ^ self new setSeconds:secondsInterval
+
+    "
+     TimeDuration fromSeconds:3600  
+    "
+!
+
+hours:h
+    "return a new TimeDuration representing a duration of h hours.
+     See also Time now / Date today / Timestamp now."
+
+    h == 0 ifTrue:[^ TimeDurationZero].
+    ^ self basicNew setHours:h minutes:0 seconds:0 milliseconds:0
+
+    "
+     TimeDuration hours:2 
+     TimeDuration hours:100  
+    "
+
+    "Created: / 14-07-2007 / 18:15:51 / cg"
+!
+
+hours:h minutes:m
+    "return a new TimeDuration representing a duration of h hours and m minutes.
+     See also Time now / Date today / Timestamp now."
+
+    ^ self basicNew setHours:h minutes:m seconds:0 milliseconds:0
+
+    "
+     TimeDuration hours:2 minutes:33 
+     TimeDuration hours:100 minutes:33  
+    "
+!
+
+hours:h minutes:m seconds:s millis:millis
+    <resource: #obsolete>
+    "return a new TimeDuration representing a duration of h hours, m minutes, s seconds and millis milliseconds.
+     See also Time now / Date today / Timestamp now."
+
+    self obsoleteMethodWarning:'use hours:minutes:seconds:milliseconds:'.
+    ^ self hours:h minutes:m seconds:s milliseconds:millis
+
+    "
+     TimeDuration hours:2 minutes:33 seconds:0 milliseconds:123  
+     TimeDuration hours:100 minutes:33 seconds:0 milliseconds:123  
+    "
+!
+
+hours:h minutes:m seconds:s milliseconds:millis
+    "return a new TimeDuration representing a duration of h hours, m minutes, s seconds and millis milliseconds.
+     See also Time now / Date today / Timestamp now."
+
+    ^ self basicNew 
+        setHours:h minutes:m seconds:s milliseconds:millis
+
+    "
+     TimeDuration hours:2 minutes:33 seconds:0 milliseconds:123  
+     TimeDuration hours:100 minutes:33 seconds:0 milliseconds:123  
+    "
+!
+
+milliseconds:m
+    "return a new TimeDuration representing a duration of m millis.
+     See also Time now / Date today / Timestamp now."
+
+    m == 0 ifTrue:[^ TimeDurationZero].
+    ^ self basicNew setHours:0 minutes:0 seconds:0 milliseconds:m
+
+    "
+     TimeDuration milliseconds:2 
+    "
+!
+
+minutes:m
+    "return a new TimeDuration representing a duration of m minutes.
+     See also Time now / Date today / Timestamp now."
+
+    m == 0 ifTrue:[^ TimeDurationZero].
+    ^ self basicNew setHours:0 minutes:m seconds:0 milliseconds:0
+
+    "
+     TimeDuration minutes:2 
+    "
+
+    "Created: / 06-08-2007 / 15:32:42 / cg"
+!
+
+readFrom:aStringOrStream defaultUnit:defaultUnitOrNil onError:exceptionBlock
+    "return a new TimeDuration, reading a printed representation from aStream.
+     The format is either:
+        [n 'yr'] [n 'mon'] [n 'w'] [n 'd'] [n 'h'] [n 'm'] [n 's'] [n 'ms']
+        where 
+            yr -> year
+            mon -> month
+            w -> week
+            d -> day
+            h -> hour
+            m -> minutes
+            s -> seconds
+            ms -> milliseconds
+     or:
+        h:m:s.ms
+
+     The yr and mon specifiers stand for 365d and 30d respectively.
+     If defaultUnitOrNil is non-nil, a plain number is treated as that;
+     otherwise, a plain number raises an error.
+    "
+
+    ^ [
+        |seconds millis str val fraction uIdx unit unitChar1 unitChar2|
+
+        str := aStringOrStream readStream.
+        seconds := 0.
+        millis := 0.
+        [
+            |nextCh|
+
+            val := Integer readFrom:str onError:nil.
+            val isNil ifTrue:[^ exceptionBlock value].
+            str peek == $: ifTrue:[
+                "/ hour:minutes format
+                str next.
+                seconds := val*3600.
+                val := Integer readFrom:str onError:nil.
+                val isNil ifTrue:[^ exceptionBlock value].
+                seconds := seconds + (val*60).
+                str peek == $: ifTrue:[
+                    "/ hour:minutes:seconds format
+                    str next.
+                    val := Integer readFrom:str onError:nil.
+                    val isNil ifTrue:[^ exceptionBlock value].
+                    seconds := seconds + val.
+                    str peek == $. ifTrue:[
+                        "/ hour:minutes:seconds.millis format
+                        str next.
+                        val := Integer readFrom:str onError:nil.
+                        val isNil ifTrue:[^ exceptionBlock value].
+                        millis := val.
+                    ]
+                ].
+                ^ self fromMilliseconds:(seconds*1000+millis) rounded asInteger.
+            ].
+            str peek == $. ifTrue:[
+                str next.
+                fraction := Number readMantissaFrom:str radix:10.
+                val := val + fraction.
+            ].
+            str skipSeparators.
+            str atEnd ifTrue:[
+                defaultUnitOrNil isNil ifTrue:[
+                    ^ exceptionBlock value
+                ].
+                "/ no unit given - assume defaultUnit
+                unitChar1 := defaultUnitOrNil.
+            ] ifFalse:[
+                unitChar1 := str next.
+            ].
+            uIdx := #($y $w $d $h $m $s) indexOf:unitChar1.
+            uIdx == 0 ifTrue:[^ exceptionBlock value].
+
+            str atEnd ifFalse:[ 
+                nextCh := str peek
+            ].
+
+            (unitChar1 == $m and:[nextCh == $s]) ifTrue:[
+                millis := millis + val.
+            ] ifFalse:[
+                (unitChar1 == $m and:[nextCh == $o]) ifTrue:[
+                    unit := 2592000 "24*60*60*30"     "mon"
+                ] ifFalse:[
+                    unit := #(
+                              31536000 "24*60*60*365" "yr"
+                              604800 "24*60*60*7"     "w"
+                              86400  "24*60*60"       "d"
+                              3600                    "h"
+                              60                      "m"
+                              1 ) at:uIdx.
+                ].
+                seconds := seconds + (unit * val).
+            ].
+            [str atEnd not and:[str peek isSeparator not]] whileTrue:[ str next].
+            str skipSeparators.
+            str atEnd
+        ] whileFalse.
+        self fromMilliseconds:(seconds*1000+millis) rounded asInteger.
+    ] on:Error do:[
+        |t|
+
+        "/ retry, using inherited readFrom (Object-storeString)
+        t := Object readFrom:aStringOrStream onError:[^ exceptionBlock value].
+        (t isKindOf:TimeDuration) ifFalse:[
+            ^ exceptionBlock value
+        ].
+        t
+    ]
+
+    "
+     TimeDuration readFrom:'2' defaultUnit:$h onError:nil 2h
+     TimeDuration readFrom:'100' defaultUnit:$m onError:nil 1h 40m
+
+     TimeDuration readFrom:'1h'      
+     TimeDuration readFrom:'1h 35m'     
+     TimeDuration readFrom:'25h'     
+     TimeDuration readFrom:'3d'     
+     TimeDuration readFrom:'1w'     
+     TimeDuration readFrom:'120s'     
+     TimeDuration readFrom:'1500ms    
+     TimeDuration readFrom:'3ms'     
+     TimeDuration readFrom:'1yr 5d'     
+     TimeDuration readFrom:'1mon'     
+     TimeDuration readFrom:'05:10'     
+     TimeDuration readFrom:'05:10:5'     
+     TimeDuration readFrom:'05:10:5.150'  
+
+     TimeDuration readFrom:(TimeDuration new storeString)
+    "
+
+    "Modified: / 08-10-2007 / 16:41:48 / cg"
+!
+
+readFrom:aStringOrStream onError:exceptionBlock
+    "return a new TimeDuration, reading a printed representation from aStream.
+     The format is [n 'yr'] [n 'mon'] [n 'w'] [n 'd'] [n 'h'] [n 'm'] [n 's'] [n 'ms']
+     where 
+            yr -> year
+            mon -> month
+            w -> week
+            d -> day
+            h -> hour
+            m -> minutes
+            s -> seconds
+            ms -> milliseconds
+     The yr and mon specifiers stand for 365d and 30d respectively.
+     If no unit is given (i.e. a plain number string is given), assume seconds.
+    "
+
+    ^ self readFrom:aStringOrStream defaultUnit:$s onError:exceptionBlock
+
+    "
+     TimeDuration readFrom:'100' onError:nil      
+     TimeDuration readFrom:'100' defaultUnit:$m onError:nil 
+
+     TimeDuration readFrom:'1h'      
+     TimeDuration readFrom:'1h 35m'     
+     TimeDuration readFrom:'25h'     
+     TimeDuration readFrom:'3d'     
+     TimeDuration readFrom:'1w'     
+     TimeDuration readFrom:'120s'     
+     TimeDuration readFrom:'1500ms    
+     TimeDuration readFrom:'3ms'     
+     TimeDuration readFrom:'1yr 5d'     
+     TimeDuration readFrom:'1mon'     
+    "
+
+    "Modified: / 08-10-2007 / 16:41:48 / cg"
+!
+
+seconds:s
+    "return a new TimeDuration representing a duration of s seconds.
+     See also Time now / Date today / Timestamp now."
+
+    s == 0 ifTrue:[^ TimeDurationZero].
+
+    ^ self basicNew setHours:0 minutes:0 seconds:s milliseconds:0
+
+    "
+     TimeDuration seconds:2 
+    "
+
+    "Created: / 06-08-2007 / 15:32:21 / cg"
+!
+
+weeks:w 
+    "return a new TimeDuration representing a duration of w weeks."
+
+    ^ self days:(w * 7)
+
+    "
+     TimeDuration weeks:1  
+    "
+
+    "Created: / 05-09-2011 / 11:18:27 / cg"
+! !
+
+!TimeDuration class methodsFor:'class initialization'!
+
+initialize
+    TimeDurationZero isNil ifTrue:[
+        TimeDurationZero := self basicNew setHours:0 minutes:0 seconds:0 milliseconds:0.
+    ]
+
+    "Modified: / 10-05-2011 / 10:31:35 / cg"
+! !
+
+!TimeDuration class methodsFor:'constants'!
+
+zero
+    "return the neutral element for addition (0s)"
+
+    ^ TimeDurationZero
+
+    "Modified: 18.7.1996 / 12:26:12 / cg"
+! !
+
+!TimeDuration class methodsFor:'format strings'!
+
+defaultFormatForPrinting
+    ^  DefaultFormatForPrinting
+!
+
+defaultFormatForPrinting:aString
+    DefaultFormatForPrinting := aString
+!
+
+formatString12us
+    "return the format string used to format US times (and other areas)"
+
+    ^ '%h:%m:%s.%i'
+!
+
+formatString24
+    "return the format string used to format european times (and other areas)"
+
+    ^ '%h:%m:%s.%i'
+! !
+
+!TimeDuration class methodsFor:'timing evaluation'!
+
+toRun:aBlock
+    "return the TimeDuration it takes to execute aBlock.                          
+     A modern variant of Time millisecondsToRun: (which prints itself nicely)"
+
+    ^ self fromMilliseconds:(Time millisecondsToRun:aBlock).
+
+    "
+     TimeDuration toRun:[ 20000 factorial ]     
+    "
+! !
+
+!TimeDuration methodsFor:'accessing'!
+
+days
+    "get the number of days"
+
+    ^ timeEncoding // 1000 // 3600 // 24
+!
+
+hours
+    "get the number of hours.
+     (notice: that is NOT the total number of hours,
+     but the fractional part only. Use this only for printing"
+
+    ^ timeEncoding // 1000 // 3600 \\ 24
+!
+
+milliseconds
+    "get the milliseconds part 
+     (notice: that is NOT the total number of millis,
+     but the fractional part only. Use this only for printing"
+
+    ^ timeEncoding \\ 1000
+
+    "Modified: / 05-05-2010 / 14:22:04 / cg"
+!
+
+minutes
+    "get the number of minutes.
+     (notice: that is NOT the total number of minutes,
+     but the fractional part only. Use this only for printing"
+
+    ^ timeEncoding // 1000 // 60 \\ 60
+!
+
+seconds
+    "get the number of seconds.
+     (notice: that is NOT the total number of seconds,
+     but the fractional part only. Use this only for printing"
+
+    ^ timeEncoding // 1000 \\ 60
+! !
+
+!TimeDuration methodsFor:'arithmetic'!
+
+* aNumber
+    "return a new scaled timeDuration"
+
+    ^ self species basicNew 
+        setMilliseconds:(self getMilliseconds * aNumber) asInteger
+
+    "
+     (TimeDuration fromString:'10s') * 5
+    "
+!
+
++ aTimeDurationOrNumberOfSeconds
+    "return a new timeDuration"
+
+    aTimeDurationOrNumberOfSeconds isNumber ifTrue:[
+        ^ self species basicNew 
+            setMilliseconds:(self getMilliseconds + (aTimeDurationOrNumberOfSeconds * 1000) asInteger)
+    ].
+    ^ self species basicNew
+        setMilliseconds:(self getMilliseconds + aTimeDurationOrNumberOfSeconds getMilliseconds)
+
+    "Created: / 04-10-2007 / 14:12:40 / cg"
+!
+
+/ aTimeDurationOrNumberOfSeconds
+    "if the argument is a number, return a new timeDuration.
+     Otherwise, return the quotient as a number."
+
+    aTimeDurationOrNumberOfSeconds isNumber ifTrue:[
+        ^ self species basicNew 
+            setMilliseconds:(self getMilliseconds / aTimeDurationOrNumberOfSeconds) asInteger
+    ].
+    ^ (self getMilliseconds / aTimeDurationOrNumberOfSeconds getMilliseconds)
+
+    "
+     (TimeDuration fromString:'10s') / (TimeDuration fromString:'5s')
+     (TimeDuration fromString:'10s') / 5
+    "
+!
+
+negated
+    ^ self class new timeEncoding:(timeEncoding negated)
+!
+
+productFromFraction:aNumber
+    "return a new timeDuration"
+
+    ^ self productFromNumber:aNumber
+
+    "
+     (TimeDuration fromString:'10s') * 5
+    "
+!
+
+productFromNumber:aNumber
+    "return a new timeDuration"
+
+    ^ self species basicNew 
+        setMilliseconds:(self getMilliseconds * aNumber) asInteger
+
+    "
+     (TimeDuration fromString:'10s') * 5
+    "
+! !
+
+!TimeDuration methodsFor:'converting'!
+
+asTime
+    "return a Time object from the receiver."
+
+    ^ Time hours:(self hours) minutes:(self minutes) seconds:(self seconds)
+!
+
+asTimeDuration
+    "return a TimeDuration object from the receiver - thats the receiver."
+
+    ^ self
+! !
+
+!TimeDuration methodsFor:'double dispatching'!
+
+differenceFromTimestamp:aTimestamp
+    "return the timestamp this timeDuration before aTimestamp"
+
+    ^ aTimestamp subtractMilliseconds:(self getMilliseconds)
+!
+
+sumFromTimestamp:aTimestamp
+    "return the timestamp this timeDuration after aTimestamp"
+
+    ^ aTimestamp addMilliseconds:(self getMilliseconds)
+! !
+
+!TimeDuration methodsFor:'printing'!
+
+addPrintBindingsTo:aDictionary language:languageOrNil
+    "private print support: add bindings for printing to aDictionary.
+     languageOrNil can only be #en or nil for the current language.
+
+     Additional formats available here (for timeDuration) are:
+        %(Hd)       hours in day (i.e. 0..23)
+        %(hd)       hours in day padded to 2 chars (i.e. 00..23)
+
+        %(yrR)      years rounded (i.e. for 730 days, we get 2 asFixed:1 )
+        %(monR)     month rounded (i.e. for 45 days, we get 1.5 asFixed:1 )
+        %(dR)       days rounded (i.e. for 36 hours, we get 1.5 asFixed:1 )
+        %(hR)       hours rounded (i.e. for 3h 30m, we get 3.5 asFixed:1 )
+        %(mR)       minutes rounded (i.e. for 2m 30s, we get 2.5 asFixed:1 )
+        %(sR)       seconds rounded to 1 postDecimal (i.e. for 2s 100ms, we get 2.1 asFixed:1 )
+    "
+
+    |hoursInDay s yearsRounded monthsRounded daysRounded hoursRounded minutesRounded secondsRounded|
+
+    super addPrintBindingsTo:aDictionary language:languageOrNil.
+    aDictionary at:$d put:self days.
+
+    hoursInDay := self hours \\ 24.
+    aDictionary at:#Hd put:(s := hoursInDay printString).
+    aDictionary at:#hd put:(s leftPaddedTo:2 with:$0).
+
+    yearsRounded := (self hours / 24 / 365).
+    yearsRounded isInteger ifFalse:[
+        yearsRounded := yearsRounded asFixedPoint:1.
+    ].
+    aDictionary at:#yrR put:yearsRounded.
+
+    monthsRounded := (self hours / 24 / 30).
+    monthsRounded isInteger ifFalse:[
+        monthsRounded := monthsRounded asFixedPoint:1.
+        monthsRounded roundedToScale = monthsRounded asInteger ifTrue:[
+            monthsRounded := monthsRounded truncated
+        ].
+    ].
+    aDictionary at:#monR put:monthsRounded.
+
+    daysRounded := (self hours / 24).
+    daysRounded isInteger ifFalse:[
+        daysRounded := daysRounded asFixedPoint:1.
+        daysRounded roundedToScale = daysRounded asInteger ifTrue:[
+            daysRounded := daysRounded truncated
+        ].
+    ].
+    aDictionary at:#dR put:daysRounded.
+
+    hoursRounded := self hours + (self minutes / 60).
+    hoursRounded isInteger ifFalse:[
+        hoursRounded := hoursRounded asFixedPoint:1.
+        hoursRounded roundedToScale = hoursRounded asInteger ifTrue:[
+            hoursRounded := hoursRounded truncated
+        ].
+    ].
+    aDictionary at:#hR put:hoursRounded.
+
+    minutesRounded := self minutes + (self seconds / 60).
+    minutesRounded isInteger ifFalse:[
+        minutesRounded := minutesRounded asFixedPoint:1.
+        minutesRounded roundedToScale = minutesRounded asInteger ifTrue:[
+            minutesRounded := minutesRounded truncated
+        ].
+    ].
+    aDictionary at:#mR put:minutesRounded.
+
+    secondsRounded := self seconds + (self milliseconds / 1000).
+    secondsRounded isInteger ifFalse:[
+        secondsRounded := secondsRounded asFixedPoint:1.
+        secondsRounded roundedToScale = secondsRounded asInteger ifTrue:[
+            secondsRounded := secondsRounded truncated
+        ].
+    ].
+    aDictionary at:#sR put:secondsRounded.
+
+    "Modified: / 22-02-2011 / 15:55:38 / cg"
+!
+
+formatForApproximatePrinting
+    "Return a format which is suitable for a human - not meant to be read back.
+     In contrast to the regular format, this one only gives a rounded approximation
+     of the time duration as useful in information-dialogs or other user-hint-GUI elements.
+     For example, in a timeDuration of more than 2hours, the user might not be interested in
+     individual seconds or even milliseconds.
+     The way this hidding/rounding is done is pure magic heuristics."
+
+    |hours mins secs ms|
+
+    hours := self hours.
+
+    hours >= (24*356*2) ifTrue:[
+        ^ '%(yrR)yr'. 
+    ].
+    hours >= (24*40) ifTrue:[
+        ^ '%(monR)mon'. 
+    ].
+    hours >= 48 ifTrue:[
+        ^ '%(dR)d'. 
+    ].
+    hours >= 24 ifTrue:[
+        ^ '%dd %(Hd)h'. 
+    ].
+    hours >= 2 ifTrue:[
+        ^ '%(hR)h'.
+    ].
+    hours >= 1 ifTrue:[
+        ^ '%Hh %Mm'.
+    ].
+
+    "/ no hours
+    mins := self minutes.
+    mins >= 5 ifTrue:[
+        ^ '%(mR)m'.
+    ].
+    mins >= 1 ifTrue:[
+        ^ '%Mm %Ss'.
+    ].
+
+    "/ no mins
+    secs := self seconds.
+    secs >= 1 ifTrue:[
+        secs >= 30 ifTrue:[
+            ^ '%(S)s'.
+        ].
+        ^ '%(sR)s'.
+    ].
+
+    "/ no secs
+    ms := self milliseconds.
+    ms > 500 ifTrue:[
+        ^ '%(sR)s'
+    ].
+
+    ^ self formatForPrinting
+
+    "
+     (TimeDuration hours:0 minutes:0 seconds:0 millis:12) printStringForApproximation       
+
+     (TimeDuration hours:0 minutes:0 seconds:10 millis:123) printStringForApproximation        
+     (TimeDuration hours:0 minutes:1 seconds:10 millis:123) printStringForApproximation        
+     (TimeDuration hours:0 minutes:2 seconds:10 millis:123) printStringForApproximation        
+     (TimeDuration hours:0 minutes:33 seconds:0 millis:123) printStringForApproximation        
+     (TimeDuration hours:2 minutes:0 seconds:0 millis:123) printStringForApproximation         
+     (TimeDuration hours:2 minutes:33 seconds:0 millis:123) printStringForApproximation        
+     (TimeDuration hours:100 minutes:33 seconds:0 millis:123) printStringForApproximation      
+     (TimeDuration hours:10000 minutes:33 seconds:0 millis:123) printStringForApproximation    
+     (TimeDuration hours:1000000 minutes:33 seconds:0 millis:123) printStringForApproximation    
+
+     (TimeDuration hours:2 minutes:33 seconds:0 millis:0) printStringForApproximation         
+     (TimeDuration hours:2 minutes:0 seconds:0 millis:0) printStringForApproximation          
+     (TimeDuration hours:24 minutes:0 seconds:0 millis:0) printStringForApproximation          
+    "
+!
+
+formatForPrinting
+    "Return the format for printing"
+
+    DefaultFormatForPrinting notNil ifTrue:[
+        ^ DefaultFormatForPrinting
+    ].
+    ^ self formatForPrinting:false
+
+    "
+     (TimeDuration readFrom:'10h 3s') formatForPrinting  
+     (TimeDuration readFrom:'3s') formatForPrinting      
+     (TimeDuration readFrom:'1d 2ms') formatForPrinting      
+    "
+!
+
+formatForShortPrinting
+    "Return the short format for printing (without ms)"
+
+    ^ self formatForPrinting:true
+!
+
+printAsApproximationOn:aStream
+    "append a human readable printed representation of the receiver to aStream.
+     The format is meant for a human and does not give all information;
+     especially, useless detail is hidden.
+     This means, that seconds are rounded or hidden, if the dT is more than a few minutes;
+     minutes rounded into the hour or hidden, if its more than a few hours etc.
+     The way this is done is pure magic heuristics - let me know, if you have a better algorithm."
+
+    ^ self
+        printOn:aStream 
+        format:(self formatForApproximatePrinting).
+
+    "
+     (TimeDuration hours:0 minutes:0 seconds:0 milliseconds:123) printAsApproximationOn:Transcript
+     (TimeDuration hours:0 minutes:0 seconds:10 milliseconds:123) printAsApproximationOn:Transcript
+     (TimeDuration hours:0 minutes:33 seconds:0 milliseconds:123) printAsApproximationOn:Transcript
+     (TimeDuration hours:2 minutes:0 seconds:0 milliseconds:123) printAsApproximationOn:Transcript
+     (TimeDuration hours:2 minutes:33 seconds:0 milliseconds:123) printAsApproximationOn:Transcript
+     (TimeDuration hours:100 minutes:33 seconds:0 milliseconds:123) printAsApproximationOn:Transcript
+     (TimeDuration hours:10000 minutes:33 seconds:0 milliseconds:123) printAsApproximationOn:Transcript
+     (TimeDuration hours:1000000 minutes:33 seconds:0 milliseconds:123) printAsApproximationOn:Transcript
+
+     (TimeDuration hours:2 minutes:33 seconds:0) printAsApproximationOn:Transcript
+     (TimeDuration hours:2 minutes:0 seconds:0) printAsApproximationOn:Transcript
+     (TimeDuration hours:24 minutes:0 seconds:0) printAsApproximationOn:Transcript
+    "
+
+    "Modified: / 18-07-2007 / 14:06:17 / cg"
+!
+
+printOn:aStream
+    "append a human readable printed representation of the receiver to aStream.
+     The format is suitable for a human - not meant to be read back."
+
+    timeEncoding negative ifTrue:[
+        aStream nextPutAll:'-'.
+        (self class basicNew timeEncoding:timeEncoding negated) printOn:aStream.
+        ^  self
+    ].
+    ^ self
+        printOn:aStream 
+        format:(self formatForPrinting).
+
+    "
+     TimeDuration hours:0 minutes:0 seconds:0 millis:12       
+
+     TimeDuration hours:0 minutes:0 seconds:0 millis:123       
+     TimeDuration hours:0 minutes:0 seconds:10 millis:123       
+     TimeDuration hours:0 minutes:33 seconds:0 millis:123       
+     TimeDuration hours:2 minutes:0 seconds:0 millis:123       
+     TimeDuration hours:2 minutes:33 seconds:0 millis:123       
+     TimeDuration hours:100 minutes:33 seconds:0 millis:123    
+     TimeDuration hours:10000 minutes:33 seconds:0 millis:123    
+     TimeDuration hours:1000000 minutes:33 seconds:0 millis:123    
+
+     TimeDuration hours:2 minutes:33 seconds:0 millis:0         
+     TimeDuration hours:2 minutes:0 seconds:0 millis:0          
+     TimeDuration hours:24 minutes:0 seconds:0 millis:0          
+
+     (TimeDuration hours:0 minutes:0 seconds:0 millis:123) printStringFormat:'%h:%m:%s'       
+     (TimeDuration hours:0 minutes:0 seconds:10 millis:123) printStringFormat:'%h:%m:%s'         
+     (TimeDuration hours:0 minutes:33 seconds:0 millis:123) printStringFormat:'%h:%m:%s'         
+     (TimeDuration hours:2 minutes:33 seconds:0 millis:123) printStringFormat:'%h:%m:%s'         
+     (TimeDuration hours:100 minutes:33 seconds:0 millis:123) printStringFormat:'%h:%m:%s'      
+     (TimeDuration hours:10000 minutes:33 seconds:0 millis:123) printStringFormat:'%h:%m:%s'      
+     (TimeDuration hours:1000000 minutes:33 seconds:0 millis:123) printStringFormat:'%h:%m:%s'      
+    "
+
+    "Modified: / 18-07-2007 / 14:06:17 / cg"
+!
+
+printShortOn:aStream
+    "append a human readable printed representation  
+     of the receiver to aStream (without milliseconds)"
+
+    ^ self
+        printOn:aStream 
+        format:(self formatForShortPrinting).
+
+    "
+     TimeDuration hours:0 minutes:0 seconds:0 millis:12       
+
+     TimeDuration hours:0 minutes:0 seconds:0 millis:123       
+     TimeDuration hours:0 minutes:0 seconds:10 millis:123       
+     TimeDuration hours:0 minutes:33 seconds:0 millis:123       
+     TimeDuration hours:2 minutes:0 seconds:0 millis:123       
+     TimeDuration hours:2 minutes:33 seconds:0 millis:123       
+     TimeDuration hours:100 minutes:33 seconds:0 millis:123    
+     TimeDuration hours:10000 minutes:33 seconds:0 millis:123    
+     TimeDuration hours:1000000 minutes:33 seconds:0 millis:123    
+
+     TimeDuration hours:2 minutes:33 seconds:0 millis:0         
+     TimeDuration hours:2 minutes:0 seconds:0 millis:0          
+     TimeDuration hours:24 minutes:0 seconds:0 millis:0          
+
+     (TimeDuration hours:0 minutes:0 seconds:0 millis:123) printStringFormat:'%h:%m:%s'       
+     (TimeDuration hours:0 minutes:0 seconds:10 millis:123) printStringFormat:'%h:%m:%s'         
+     (TimeDuration hours:0 minutes:33 seconds:0 millis:123) printStringFormat:'%h:%m:%s'         
+     (TimeDuration hours:2 minutes:33 seconds:0 millis:123) printStringFormat:'%h:%m:%s'         
+     (TimeDuration hours:100 minutes:33 seconds:0 millis:123) printStringFormat:'%h:%m:%s'      
+     (TimeDuration hours:10000 minutes:33 seconds:0 millis:123) printStringFormat:'%h:%m:%s'      
+     (TimeDuration hours:1000000 minutes:33 seconds:0 millis:123) printStringFormat:'%h:%m:%s'      
+    "
+
+    "Modified: / 18-07-2007 / 14:06:17 / cg"
+!
+
+printStringForApproximation
+    "return a human readable printed representation of the receiver to aStream.
+     The format is meant for a human and does not give all information;
+     especially, useless detail is hidden.
+     This means, that seconds are rounded or hidden, if the dT is more than a few minutes;
+     minutes rounded into the hour or hidden, if its more than a few hours etc.
+     The way this is done is pure magic heuristics - let me know, if you have a better algorithm."
+
+    ^ self
+        printStringFormat:(self formatForApproximatePrinting).
+
+    "
+     (TimeDuration hours:0 minutes:0 seconds:0 milliseconds:123) printStringForApproximation
+     (TimeDuration hours:0 minutes:0 seconds:10 milliseconds:123) printStringForApproximation
+     (TimeDuration hours:0 minutes:33 seconds:0 milliseconds:123) printStringForApproximation
+     (TimeDuration hours:2 minutes:0 seconds:0 milliseconds:123) printStringForApproximation
+     (TimeDuration hours:2 minutes:33 seconds:0 milliseconds:123) printStringForApproximation
+     (TimeDuration hours:100 minutes:33 seconds:0 milliseconds:123) printStringForApproximation
+     (TimeDuration hours:10000 minutes:33 seconds:0 milliseconds:123) printStringForApproximation
+     (TimeDuration hours:1000000 minutes:33 seconds:0 milliseconds:123) printStringForApproximation
+
+     (TimeDuration hours:2 minutes:33 seconds:0) printStringForApproximation
+     (TimeDuration hours:2 minutes:0 seconds:0) printStringForApproximation
+     (TimeDuration hours:24 minutes:0 seconds:0) printStringForApproximation
+    "
+! !
+
+!TimeDuration methodsFor:'private'!
+
+formatForPrinting:shortFlag
+    "Return a format which is suitable for a human - not meant to be read back.
+     If shortFlag is true, some millisecond-info is ommitted for longer times."
+
+    |fmt days hours mins secs overAllSeconds millis|
+
+    days := self days.
+    hours := self hours.
+    mins := self minutes.
+    secs := self seconds.
+    millis := self milliseconds.
+
+    ((days > 0) or:[hours >= 24]) ifTrue:[
+        fmt := '%dd %(Hd)h %Mm'.
+        secs = 0 ifTrue:[
+            fmt := '%dd %(Hd)h %Mm'.
+            mins = 0 ifTrue:[
+                fmt := '%dd %(Hd)h'.
+                (hours \\ 24) = 0 ifTrue:[
+                    fmt := '%dd'.
+                ].
+            ].
+        ].
+    ] ifFalse:[
+        hours > 0 ifTrue:[
+            fmt := '%Hh %Mm'.
+            secs = 0 ifTrue:[
+                fmt := '%Hh %Mm'.
+                mins = 0 ifTrue:[
+                    fmt := '%Hh'.
+                ].
+            ].
+        ] ifFalse:[
+            mins > 0 ifTrue:[
+                fmt := '%Mm'.
+                secs = 0 ifTrue:[
+                    fmt := '%Mm'
+                ].
+            ] ifFalse:[
+                fmt := ''
+            ].
+        ].
+    ].
+    ((secs ~= 0) or:[millis ~= 0])ifTrue:[
+        fmt size ~~ 0 ifTrue:[
+            fmt := fmt , ' '
+        ].
+        (millis = 0) ifTrue:[
+            fmt := fmt , '%Ss'
+        ] ifFalse:[
+            secs = 0 ifTrue:[
+                fmt := fmt , '%Ims'
+            ] ifFalse:[
+                shortFlag ifFalse:[
+                    "/ show millis
+                    fmt := fmt , '%S.%is'
+                ] ifTrue:[
+                    "/ only show millis if the number of seconds is small
+                    overAllSeconds := self asSeconds.
+                    overAllSeconds > 2 ifTrue:[
+                        overAllSeconds > 10 ifTrue:[
+                            overAllSeconds > 300 ifTrue:[
+                                fmt := fmt , '%Ss'
+                            ] ifFalse:[
+                                fmt := fmt , '%S.%(milli1)s'
+                            ]
+                        ] ifFalse:[
+                            fmt := fmt , '%S.%(milli2)s'
+                        ]
+                    ] ifFalse:[
+                        fmt := fmt , '%S.%is'
+                    ]
+                ]
+            ]
+        ].
+    ] ifFalse:[
+        fmt isEmpty ifTrue:[
+            fmt := '%Ss'
+        ].
+    ].
+
+    ^ fmt.
+
+    "
+     (TimeDuration hours:0 minutes:0 seconds:0 millis:12) formatForPrinting       
+
+     (TimeDuration hours:0 minutes:0 seconds:0 millis:123) formatForPrinting       
+     (TimeDuration hours:0 minutes:0 seconds:10 millis:123) formatForPrinting       
+     (TimeDuration hours:0 minutes:33 seconds:0 millis:123) formatForPrinting       
+     (TimeDuration hours:2 minutes:0 seconds:0 millis:123) formatForPrinting       
+     (TimeDuration hours:2 minutes:33 seconds:0 millis:123) formatForPrinting       
+     (TimeDuration hours:100 minutes:33 seconds:0 millis:123) formatForPrinting    
+     (TimeDuration hours:10000 minutes:33 seconds:0 millis:123) formatForPrinting    
+     (TimeDuration hours:1000000 minutes:33 seconds:0 millis:123) formatForPrinting    
+
+     (TimeDuration hours:0 minutes:38 seconds:22 millis:123) formatForPrinting:true       
+
+     (TimeDuration hours:2 minutes:33 seconds:0 millis:0) formatForPrinting         
+     (TimeDuration hours:2 minutes:0 seconds:0 millis:0) formatForPrinting          
+     (TimeDuration hours:24 minutes:0 seconds:0 millis:0) formatForPrinting          
+
+     (TimeDuration hours:0 minutes:0 seconds:0 millis:123) printStringFormat:'%h:%m:%s'       
+     (TimeDuration hours:0 minutes:0 seconds:10 millis:123) printStringFormat:'%h:%m:%s'         
+     (TimeDuration hours:0 minutes:33 seconds:0 millis:123) printStringFormat:'%h:%m:%s'         
+     (TimeDuration hours:2 minutes:33 seconds:0 millis:123) printStringFormat:'%h:%m:%s'         
+     (TimeDuration hours:100 minutes:33 seconds:0 millis:123) printStringFormat:'%h:%m:%s'      
+     (TimeDuration hours:10000 minutes:33 seconds:0 millis:123) printStringFormat:'%h:%m:%s'      
+     (TimeDuration hours:1000000 minutes:33 seconds:0 millis:123) printStringFormat:'%h:%m:%s'      
+    "
+
+    "Modified: / 18-07-2007 / 14:06:17 / cg"
+!
+
+getMilliseconds
+    "return the number of milliseconds"
+
+    ^ timeEncoding
+
+    "Modified: / 18-07-2007 / 13:44:33 / cg"
+!
+
+getSeconds
+    "return the number of seconds"
+
+    ^ timeEncoding // 1000
+
+    "Modified: / 18-07-2007 / 13:44:37 / cg"
+!
+
+setHours:h minutes:m seconds:s millis:millis
+    <resource: #obsolete>
+    "set my time given individual values"
+
+    self obsoleteMethodWarning:'use setHours:minutes:seconds:milliseconds:'.
+    self setHours:h minutes:m seconds:s milliseconds:millis.
+!
+
+setHours:h minutes:m seconds:s milliseconds:millis
+    "set my time given individual values"
+
+    self setMilliseconds:((h * 60 * 60 ) + (m * 60) + s) * 1000 + millis.
+!
+
+setMilliseconds:millis
+    "set my duration given milliseconds.
+     Notice that (in contrast to Time), there is no modulu operation here.
+     Duration can be longer than a day"
+
+    "/ self assert:(millis isInteger).
+    timeEncoding := millis
+
+    "Modified: / 18-07-2007 / 13:44:16 / cg"
+!
+
+setSeconds:secs
+    "set my timeduration given seconds.
+     Notice that (in contrast to Time), there is no modulu operation here.
+     Duration can be longer than a day"
+
+    self setMilliseconds:(secs * 1000).
+
+    "Modified: / 18-07-2007 / 13:44:24 / cg"
+! !
+
+!TimeDuration methodsFor:'testing'!
+
+isTimeDuration
+    ^ true
+!
+
+isZero
+    ^ self = self class zero
+!
+
+negative
+    ^ timeEncoding < 0
+! !
+
+!TimeDuration class methodsFor:'documentation'!
+
+version
+    ^ '$Header: /cvs/stx/stx/libbasic/TimeDuration.st,v 1.65 2014-04-16 22:20:35 cg Exp $'
+!
+
+version_CVS
+    ^ '$Header: /cvs/stx/stx/libbasic/TimeDuration.st,v 1.65 2014-04-16 22:20:35 cg Exp $'
+! !
+
+
+TimeDuration initialize!