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

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

fixed person problem in BootStrap?, added comments to Event class, fixed #104

  • Property svn:keywords set to Date Rev Author
File size: 7.8 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: 564 $
12 * $Author: keesvb $
13 * $Date: 2010-06-14 15:20:07 +0000 (ma, 14 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                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         * Returns the value in seconds
150         */
151        public long getValue() {
152                return reltimeValue;
153        }
154
155        /**
156         * Sets the value in seconds
157         */
158        public void setValue(long value) {
159                reltimeValue = value;
160        }
161
162        /**
163         * Sets the value as a string.
164         */
165        public void setValue(String value) {
166                parse(value);
167        }
168
169
170
171         /**
172          * Return a sentence that may be used in interfaces to give the user an instruction on how to enter RelTimes in string format
173         */
174        public static final String getHelpText() {
175                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.";
176        }
177
178        /**
179         * Parses a string into a RelTime long
180         *
181         * The relative time may be set as a string, using the following format
182         *
183         *     #w #d #h #m #s
184         *
185         * Where w = weeks, d = days, h = hours, m = minutes, s = seconds
186         *
187         * The spaces between the values are optional. Every timespan
188         * (w, d, h, m, s) must appear at most once. You can also omit
189         * timespans if needed or use a different order.
190         * Other characters are disregarded, allthough results may not
191         * always be as expected.
192         *
193         * If an incorrect format is used, which can't be parsed
194         * an IllegalArgumentException is thrown.
195         *
196         * An empty span is treated as zero seconds.
197         *
198         * Examples:
199         * ---------
200         *    5d 3h 20m     // 5 days, 3 hours and 20 minutes
201         *    6h 2d         // 2 days, 6 hours
202         *    10m 200s      // 13 minutes, 20 seconds (200s == 3m + 20s)
203         *    5w4h15m       // 5 weeks, 4 hours, 15 minutes
204         *
205         *    16x14w10d     // Incorrect. 16x is disregarded, so the
206         *                  // result is 15 weeks, 3 days
207         *    13days        // Incorrect: days should be d, but this is
208         *                  // parsed as 13d, 0 seconds
209         */
210        public void parse(String value) {
211                long newvalue;
212
213                // An empty string should be parsed as 0
214                if (value == null || value.trim() == "" || value.trim() == "-") {
215                        newvalue = 0L;
216                } else {
217                        // Check whether it is a negative number
218                        // this is indicated by a dash in front
219                        def multiplier = 1L;
220                        if (value.trim()[0] == '-') {
221                                multiplier = -1L;
222                        }
223
224                        // Find all parts that contain numbers with
225                        // a character w, d, h, m or s after it
226                        def periodMatch = value =~ /([0-9]+)\s*([wdhms])/
227                        if (periodMatch.size() > 0) {
228                                def seconds = 0L;
229
230                                // Now check if every part contains data for
231                                // the time interval
232                                periodMatch.each {
233                                        def partValue
234
235                                        if (it[1].isLong()) {
236                                                partValue = Long.parseLong(it[1]);
237                                        } else {
238                                                partValue = 0;
239                                        }
240
241                                        switch (it[2]) {
242                                                case 'w':
243                                                        seconds += w * partValue;
244                                                        break;
245                                                case 'd':
246                                                        seconds += d * partValue;
247                                                        break;
248                                                case 'h':
249                                                        seconds += h * partValue;
250                                                        break;
251                                                case 'm':
252                                                        seconds += m * partValue;
253                                                        break;
254                                                case 's':
255                                                        seconds += s * partValue;
256                                                        break;
257                                                default:
258                                                        adf.error.warn('Parsing relative time: ' + it[0] + it[1] + ' is not understood and disregarded');
259                                                        break;
260                                        }
261                                }
262
263                                // Continue with the computed value
264                                newvalue = multiplier * seconds;
265                        } else {
266                                throw new IllegalArgumentException("String " + value + " cannot be parsed as a relative time. Use format #w #d #h #m #s.");
267                                return;
268                        }
269                }
270
271                setValue(newvalue);
272        }
273
274        public void computeDifference(Date start, Date end) {
275                println([start, end]);
276                println([start.getTime(), end.getTime()]);
277
278                if (start && end) {
279                        long seconds = (end.getTime() - start.getTime()) / 1000L;
280                        setValue(seconds);
281                } else {
282                        setValue(0);
283                }
284        }
285
286        static RelTime parseRelTime(String value) {
287                RelTime reltime = new RelTime();
288                reltime.parse(value);
289                return reltime;
290        }
291}
Note: See TracBrowser for help on using the repository browser.