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

Last change on this file since 580 was 580, checked in by keesvb, 11 years ago

typing error in last commit

  • Property svn:keywords set to Date Rev Author
File size: 8.0 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: 580 $
12 * $Author: keesvb $
13 * $Date: 2010-06-17 13:30:32 +0000 (do, 17 jun 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                if (reltime == 0) stringValue = "0s";
89
90                return stringValue.trim();
91        }
92
93        /**
94         * Return pretty human readable string of this reltime
95         */
96        public String toPrettyString() {
97                // Method to handle the difference between 1 day and 2 dayS
98                def handleNumerus = {number, string ->
99                        return number.toString() + (number == 1 ? string : string + 's')
100                }
101
102                def negative = this.reltimeValue < 0;
103                def reltime = this.reltimeValue.abs();
104
105                def seconds = Math.floor((reltime % m) / s).toInteger();
106                def minutes = Math.floor((reltime % h) / m).toInteger();
107                def hours = Math.floor((reltime % d) / h).toInteger();
108                def days = Math.floor((reltime % w) / d).toInteger();
109                def weeks = Math.floor(reltime / w).toInteger();
110
111                def stringValue = negative ? "-" : "";
112                def values = [];
113                if (weeks > 0) { values << handleNumerus(weeks, " week") }
114                if (days > 0) { values << handleNumerus(days, " day") }
115                if (hours > 0) { values << handleNumerus(hours, " hour") }
116                if (minutes > 0) { values << handleNumerus(minutes, " minute") }
117                if (seconds > 0) { values << handleNumerus(seconds, " second") }
118
119                if (reltime == 0) values << "0 seconds";
120
121                return stringValue + values.join(', ').trim();
122        }
123
124        /**
125         * Return pretty human readable string of this reltime
126         */
127        public String toPrettyRoundedString() {
128                // Method to handle the difference between 1 day and 2 dayS
129                def handleNumerus = {number, string ->
130                        return number.toString() + (number == 1 ? string : string + 's')
131                }
132
133                def negative = this.reltimeValue < 0;
134                def reltime = this.reltimeValue.abs();
135
136                def seconds = Math.floor((reltime % m) / s).toInteger();
137                def minutes = Math.floor((reltime % h) / m).toInteger();
138                def hours = Math.floor((reltime % d) / h).toInteger();
139                def days = Math.floor((reltime % w) / d).toInteger();
140                def weeks = Math.floor(reltime / w).toInteger();
141
142                def stringValue = negative ? "-" : "";
143                if (weeks > 0) { return stringValue + handleNumerus(weeks, " week") }
144                if (days > 0) { return stringValue + handleNumerus(days, " day") }
145                if (hours > 0) { return stringValue + handleNumerus(hours, " hour") }
146                if (minutes > 0) { return stringValue + handleNumerus(minutes, " minute") }
147                if (seconds > 0) { return stringValue + handleNumerus(seconds, " second") }
148
149                if (reltime == 0) return "0 seconds";
150
151                return "";
152        }
153
154        /**
155         * Returns the value in seconds
156         */
157        public long getValue() {
158                return reltimeValue;
159        }
160
161        /**
162         * Sets the value in seconds
163         */
164        public void setValue(long value) {
165                reltimeValue = value;
166        }
167
168        /**
169         * Sets the value as a string.
170         */
171        public void setValue(String value) {
172                parse(value);
173        }
174
175
176
177         /**
178          * Return a sentence that may be used in interfaces to give the user an instruction on how to enter RelTimes in string format
179         */
180        public static final String getHelpText() {
181                return "Use the first letter of weeks/days/hours/minutes/seconds, e.g. '1w 2d' for 1 week + 2 days or '10m30s' for 10 minutes and 30 seconds.";
182        }
183
184        /**
185         * Parses a string into a RelTime long
186         *
187         * The relative time may be set as a string, using the following format
188         *
189         *     #w #d #h #m #s
190         *
191         * Where w = weeks, d = days, h = hours, m = minutes, s = seconds
192         *
193         * The spaces between the values are optional. Every timespan
194         * (w, d, h, m, s) must appear at most once. You can also omit
195         * timespans if needed or use a different order.
196         * Other characters are disregarded, allthough results may not
197         * always be as expected.
198         *
199         * If an incorrect format is used, which can't be parsed
200         * an IllegalArgumentException is thrown.
201         *
202         * An empty span is treated as zero seconds.
203         *
204         * Examples:
205         * ---------
206         *    5d 3h 20m     // 5 days, 3 hours and 20 minutes
207         *    6h 2d         // 2 days, 6 hours
208         *    10m 200s      // 13 minutes, 20 seconds (200s == 3m + 20s)
209         *    5w4h15m       // 5 weeks, 4 hours, 15 minutes
210         *
211         *    16x14w10d     // Incorrect. 16x is disregarded, so the
212         *                  // result is 15 weeks, 3 days
213         *    13days        // Incorrect: days should be d, but this is
214         *                  // parsed as 13d, 0 seconds
215         */
216        public void parse(String value) {
217                long newvalue;
218
219                // An empty string should be parsed as 0
220                if (value == null || value.trim() == "" || value.trim() == "-") {
221                        newvalue = 0L;
222                } else {
223                        // Check whether it is a negative number
224                        // this is indicated by a dash in front
225                        def multiplier = 1L;
226                        if (value.trim()[0] == '-') {
227                                multiplier = -1L;
228                        }
229
230                        // Find all parts that contain numbers with
231                        // a character w, d, h, m or s after it
232                        def periodMatch = value =~ /([0-9]+)\s*([wdhms])/
233                        if (periodMatch.size() > 0) {
234                                def seconds = 0L;
235
236                                // Now check if every part contains data for
237                                // the time interval
238                                periodMatch.each {
239                                        def partValue
240
241                                        if (it[1].isLong()) {
242                                                partValue = Long.parseLong(it[1]);
243                                        } else {
244                                                partValue = 0;
245                                        }
246
247                                        switch (it[2]) {
248                                                case 'w':
249                                                        seconds += w * partValue;
250                                                        break;
251                                                case 'd':
252                                                        seconds += d * partValue;
253                                                        break;
254                                                case 'h':
255                                                        seconds += h * partValue;
256                                                        break;
257                                                case 'm':
258                                                        seconds += m * partValue;
259                                                        break;
260                                                case 's':
261                                                        seconds += s * partValue;
262                                                        break;
263                                                default:
264                                                        adf.error.warn('Parsing relative time: ' + it[0] + it[1] + ' is not understood and disregarded');
265                                                        break;
266                                        }
267                                }
268
269                                // Continue with the computed value
270                                newvalue = multiplier * seconds;
271                        } else {
272                                throw new IllegalArgumentException("String " + value + " cannot be parsed as a relative time. Use format #w #d #h #m #s.");
273                                return;
274                        }
275                }
276
277                setValue(newvalue);
278        }
279
280        public void computeDifference(Date start, Date end) {
281                println([start, end]);
282                println([start.getTime(), end.getTime()]);
283
284                if (start && end) {
285                        long seconds = (end.getTime() - start.getTime()) / 1000L;
286                        setValue(seconds);
287                } else {
288                        setValue(0);
289                }
290        }
291
292        static RelTime parseRelTime(String value) {
293                RelTime reltime = new RelTime();
294                reltime.parse(value);
295                return reltime;
296        }
297}
Note: See TracBrowser for help on using the repository browser.