source: trunk/grails-app/domain/dbnp/studycapturing/RelTime.groovy @ 500

Last change on this file since 500 was 500, checked in by duh, 11 years ago
  • reformatted some indentations
  • set svn keyword expansion
  • Property svn:keywords set to Date Rev Author
File size: 9.4 KB
Line 
1/**
2 * RelTime Domain Class
3 *
4 * Contains useful functions for the RelTime templatefield
5 *
6 * @author      Robert Horlings
7 * @since       20100529
8 * @package     dbnp.studycapturing
9 *
10 * Revision information:
11 * $Rev: 500 $
12 * $Author: duh $
13 * $Date: 2010-05-31 08:24:00 +0000 (ma, 31 mei 2010) $
14 */
15package dbnp.studycapturing
16
17class RelTime {
18    final static long s = 1L;
19    final static long m = 60L * s;
20    final static long h = 60L * m;
21    final static long d = 24L * h;
22    final static long w = 7L * d;
23
24    private long reltimeValue;
25
26    public RelTime() {
27        this( 0L );
28    }
29
30    public RelTime( long reltime ) {
31        setValue( reltime);
32    }
33
34    public RelTime( String reltime ) {
35        parse( reltime );
36    }
37
38    /**
39     * Constructor to create a relative time from two given dates
40     *
41     * The reltime will be the second date, with the first date as reference,
42     * i.e. date2 - date1
43     */
44    public RelTime( Date date1, Date date2 ) {
45        computeDifference( date1, date2 );
46    }
47
48    /**
49     * Constructor to create a relative time from two given relative times
50     *
51     * The reltime will be the second date, with the first date as reference,
52     * i.e. date2 - date1
53     */
54    public RelTime( RelTime date1, RelTime date2 ) {
55        this( date1.getValue(), date2.getValue() );
56    }
57
58    /**
59     * Constructor to create a relative time from two given relative times
60     *
61     * The reltime will be the second date, with the first date as reference,
62     * i.e. date2 - date1
63     */
64    public RelTime( long date1, long date2 ) {
65        setValue( date2 - date1 );
66    }
67
68    /**
69     * Return simple string version of this reltime
70     */
71    public String toString() {
72        def negative = this.reltimeValue < 0;
73        def reltime = this.reltimeValue.abs();
74
75        def seconds = Math.floor( (reltime % m) / s ).toInteger();
76        def minutes = Math.floor( (reltime % h) / m ).toInteger();
77        def hours   = Math.floor( (reltime % d) / h ).toInteger();
78        def days    = Math.floor( (reltime % w) / d ).toInteger();
79        def weeks   = Math.floor(  reltime      / w ).toInteger();
80
81        def stringValue = negative ? "-" : "" ;
82        if( weeks > 0   ) { stringValue += weeks   + "w "; }
83        if( days > 0    ) { stringValue += days    + "d "; }
84        if( hours > 0   ) { stringValue += hours   + "h "; }
85        if( minutes > 0 ) { stringValue += minutes + "m "; }
86        if( seconds > 0 ) { stringValue += seconds + "s "; }
87
88        return stringValue.trim();
89    }
90
91    /**
92     * Return pretty human readable string of this reltime
93     */
94    public String toPrettyString() {
95        // Method to handle the difference between 1 day and 2 dayS
96        def handleNumerus = {number, string ->
97                return number.toString() + (number == 1 ? string : string + 's')
98        }
99
100        def negative = this.reltimeValue < 0;
101        def reltime = this.reltimeValue.abs();
102
103        def seconds = Math.floor( (reltime % m) / s ).toInteger();
104        def minutes = Math.floor( (reltime % h) / m ).toInteger();
105        def hours   = Math.floor( (reltime % d) / h ).toInteger();
106        def days    = Math.floor( (reltime % w) / d ).toInteger();
107        def weeks   = Math.floor(  reltime      / w ).toInteger();
108
109        def stringValue = negative ? "-" : "" ;
110        def values = [];
111        if( weeks > 0   ) { values << handleNumerus( weeks,   " week" ) }
112        if( days > 0    ) { values << handleNumerus( days,    " day" ) }
113        if( hours > 0   ) { values <<  handleNumerus( hours,   " hour" ) }
114        if( minutes > 0 ) { values << handleNumerus( minutes, " minute" ) }
115        if( seconds > 0 ) { values << handleNumerus( seconds, " second" ) }
116
117        return stringValue + values.join( ', ' ).trim();
118    }
119
120    /**
121     * Return pretty human readable string of this reltime
122     */
123    public String toPrettyRoundedString() {
124        // Method to handle the difference between 1 day and 2 dayS
125        def handleNumerus = {number, string ->
126                return number.toString() + (number == 1 ? string : string + 's')
127        }
128
129        def negative = this.reltimeValue < 0;
130        def reltime = this.reltimeValue.abs();
131
132        def seconds = Math.floor( (reltime % m) / s ).toInteger();
133        def minutes = Math.floor( (reltime % h) / m ).toInteger();
134        def hours   = Math.floor( (reltime % d) / h ).toInteger();
135        def days    = Math.floor( (reltime % w) / d ).toInteger();
136        def weeks   = Math.floor(  reltime      / w ).toInteger();
137
138        def stringValue = negative ? "-" : "" ;
139        if( weeks > 0   ) { return stringValue + handleNumerus( weeks,   " week"   ) }
140        if( days > 0    ) { return stringValue + handleNumerus( days,    " day"    ) }
141        if( hours > 0   ) { return stringValue + handleNumerus( hours,   " hour"   ) }
142        if( minutes > 0 ) { return stringValue + handleNumerus( minutes, " minute" ) }
143        if( seconds > 0 ) { return stringValue + handleNumerus( seconds, " second" ) }
144
145        return "";
146    }
147
148
149    /** 
150     * Returns the value in seconds
151     */
152    public long getValue() {
153        return reltimeValue;
154    }
155
156    /**
157     * Sets the value in seconds
158     */
159    public void setValue( long value ) {
160        reltimeValue = value;
161    }
162
163    /**
164     * Sets the value as a string.
165     */
166    public void setValue( String value ) {
167        parse( value );
168    }
169   
170    /**
171     * Parses a string into a RelTime long
172     *
173     * The relative time may be set as a string, using the following format
174     * 
175     *     #w #d #h #m #s
176     * 
177     * Where w = weeks, d = days, h = hours, m = minutes, s = seconds
178     * 
179     * The spaces between the values are optional. Every timespan
180     * (w, d, h, m, s) must appear at most once. You can also omit
181     * timespans if needed or use a different order.
182     * Other characters are disregarded, allthough results may not
183     * always be as expected.
184     * 
185     * If an incorrect format is used, which can't be parsed
186     * an IllegalArgumentException is thrown.
187     *
188     * An empty span is treated as zero seconds.
189     *
190     * Examples:
191     * ---------
192     *    5d 3h 20m     // 5 days, 3 hours and 20 minutes
193     *    6h 2d         // 2 days, 6 hours
194     *    10m 200s      // 13 minutes, 20 seconds (200s == 3m + 20s)
195     *    5w4h15m       // 5 weeks, 4 hours, 15 minutes
196     *   
197     *    16x14w10d     // Incorrect. 16x is disregarded, so the
198     *                  // result is 15 weeks, 3 days
199     *    13days        // Incorrect: days should be d, but this is
200     *                  // parsed as 13d, 0 seconds
201     */
202    public void parse( String value ) {
203        long newvalue;
204       
205        // An empty string should be parsed as 0
206        if( value == null || value.trim() == "" || value.trim() == "-" ) {
207            newvalue = 0L;
208        } else {
209            // Check whether it is a negative number
210            // this is indicated by a dash in front
211            def multiplier = 1L;
212            if( value.trim()[0] == '-' )
213            {
214                multiplier = -1L;
215            }
216
217            // Find all parts that contain numbers with
218            // a character w, d, h, m or s after it
219            def periodMatch = value =~ /([0-9]+)\s*([wdhms])/
220            if (periodMatch.size() > 0 ) {
221                    def seconds = 0L;
222
223                    // Now check if every part contains data for
224                    // the time interval
225                    periodMatch.each {
226                        def partValue
227
228                        if( it[1].isLong() ) {
229                            partValue = Long.parseLong( it[1] );
230                        } else {
231                            partValue = 0;
232                        }
233                       
234                        switch( it[ 2 ] ) {
235                            case 'w':
236                                seconds += w * partValue;
237                                break;
238                            case 'd':
239                                seconds += d * partValue;
240                                break;
241                            case 'h':
242                                seconds += h * partValue;
243                                break;
244                            case 'm':
245                                seconds += m * partValue;
246                                break;
247                            case 's':
248                                seconds += s * partValue;
249                                break;
250                            default:
251                                adf.error.warn( 'Parsing relative time: ' + it[0] + it[1] + ' is not understood and disregarded' );
252                                break;
253                        }
254                    }
255
256                    // Continue with the computed value
257                    newvalue = multiplier * seconds;
258            } else {
259                throw new IllegalArgumentException( "String " + value + " cannot be parsed as a relative time. Use format #w #d #h #m #s." );
260                return;
261            }
262        }
263
264        setValue( newvalue );
265    }
266
267    public void computeDifference( Date start, Date end ) {
268        println( [ start, end ] );
269        println( [ start.getTime(), end.getTime() ]);
270
271        if( start && end ) {
272            long seconds = (end.getTime() - start.getTime()) / 1000L;
273            setValue( seconds );
274        } else {
275            setValue( 0 );
276        }
277    }
278   
279    static RelTime parseRelTime( String value ) {
280        RelTime reltime = new RelTime();
281        reltime.parse( value );
282        return reltime;
283    }
284}
Note: See TracBrowser for help on using the repository browser.