Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
CommonTM |
|
| 6.0;6 |
1 | /** | |
2 | * The contents of this file are subject to the Mozilla Public License Version 1.1 | |
3 | * (the "License"); you may not use this file except in compliance with the License. | |
4 | * You may obtain a copy of the License at http://www.mozilla.org/MPL/ | |
5 | * Software distributed under the License is distributed on an "AS IS" basis, | |
6 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the | |
7 | * specific language governing rights and limitations under the License. | |
8 | * | |
9 | * The Original Code is "CommmonTM.java". Description: | |
10 | * "Note: The class description below has been excerpted from the Hl7 2.4 documentation" | |
11 | * | |
12 | * The Initial Developer of the Original Code is University Health Network. Copyright (C) | |
13 | * 2001. All Rights Reserved. | |
14 | * | |
15 | * Contributor(s): ______________________________________. | |
16 | * | |
17 | * Alternatively, the contents of this file may be used under the terms of the | |
18 | * GNU General Public License (the "GPL"), in which case the provisions of the GPL are | |
19 | * applicable instead of those above. If you wish to allow use of your version of this | |
20 | * file only under the terms of the GPL and not to allow others to use your version | |
21 | * of this file under the MPL, indicate your decision by deleting the provisions above | |
22 | * and replace them with the notice and other provisions required by the GPL License. | |
23 | * If you do not delete the provisions above, a recipient may use your version of | |
24 | * this file under either the MPL or the GPL. | |
25 | * | |
26 | */ | |
27 | ||
28 | package ca.uhn.hl7v2.model.primitive; | |
29 | ||
30 | import java.util.Calendar; | |
31 | import java.util.Date; | |
32 | import java.util.GregorianCalendar; | |
33 | import java.util.TimeZone; | |
34 | import java.io.Serializable; | |
35 | ||
36 | import ca.uhn.hl7v2.model.DataTypeException; | |
37 | import ca.uhn.hl7v2.model.DataTypeUtil; | |
38 | ||
39 | /** | |
40 | * This class contains functionality used by the TM class | |
41 | * in the version 2.3.0, 2.3.1, and 2.4 packages | |
42 | * | |
43 | * Note: The class description below has been excerpted from the Hl7 2.4 documentation. Sectional | |
44 | * references made below also refer to the same documentation. | |
45 | * | |
46 | * Format: HH[MM[SS[.S[S[S[S]]]]]][+/-ZZZZ] | |
47 | * In prior versions of HL7, this data type was always specified to be in the | |
48 | * format HHMM[SS[.SSSS]][+/-ZZZZ] using a 24 hour clock notation. In the | |
49 | * current and future versions, the precision of a time may be expressed by | |
50 | * limiting the number of digits used with the format specification as shown | |
51 | * above. By site-specific agreement, HHMM[SS[.SSSS]][+/-ZZZZ] may be used where | |
52 | * backward compatibility must be maintained. | |
53 | * Thus, HH is used to specify a precision of "hour," HHMM is used to specify a | |
54 | * precision of "minute," HHMMSS is used to specify a precision of seconds, and | |
55 | * HHMMSS.SSSS is used to specify a precision of ten-thousandths of a second. | |
56 | * In each of these cases, the time zone is an optional component. The fractional | |
57 | * seconds could be sent by a transmitter who requires greater precision than whole | |
58 | * seconds. Fractional representations of minutes, hours or other higher-order units | |
59 | * of time are not permitted. | |
60 | * Note: The time zone [+/-ZZZZ], when used, is restricted to legally-defined time zones | |
61 | * and is represented in HHMM format. | |
62 | * The time zone of the sender may be sent optionally as an offset from the coordinated | |
63 | * universal time (previously known as Greenwich Mean Time). Where the time zone | |
64 | * is not present in a particular TM field but is included as part of the date/time | |
65 | * field in the MSH segment, the MSH value will be used as the default time zone. | |
66 | * Otherwise, the time is understood to refer to the local time of the sender. | |
67 | * Midnight is represented as 0000. | |
68 | * Examples:|235959+1100| 1 second before midnight in a time zone eleven hours | |
69 | * ahead of Universal Coordinated Time (i.e., east of Greenwich). | |
70 | * |0800| Eight AM, local time of the sender. | |
71 | * |093544.2312| 44.2312 seconds after Nine thirty-five AM, local time of sender. | |
72 | * |13| 1pm (with a precision of hours), local time of sender. | |
73 | * @author Neal Acharya | |
74 | */ | |
75 | ||
76 | @SuppressWarnings("serial") | |
77 | public class CommonTM implements Serializable { | |
78 | ||
79 | /** | |
80 | * Value returned by {@link #getGMTOffset()} if no offset is set | |
81 | */ | |
82 | public static final int GMT_OFFSET_NOT_SET_VALUE = -99; | |
83 | ||
84 | private String value; | |
85 | private int hour; | |
86 | private int minute; | |
87 | private int second; | |
88 | private float fractionOfSec; | |
89 | private int offSet; | |
90 | 4378 | private boolean omitOffsetFg = false; |
91 | ||
92 | /** | |
93 | * Constructs a TM datatype with fields initialzed to zero and the value set to | |
94 | * null. | |
95 | */ | |
96 | 4293 | public CommonTM() { |
97 | //initialize all DT fields | |
98 | 4293 | value = null; |
99 | 4293 | hour = 0; |
100 | 4293 | minute = 0; |
101 | 4293 | second = 0; |
102 | 4293 | fractionOfSec = 0; |
103 | 4293 | offSet = GMT_OFFSET_NOT_SET_VALUE; |
104 | 4293 | } //end constructor |
105 | ||
106 | /** | |
107 | * Constructs a TM object with the given value. | |
108 | * The stored value will be in the following | |
109 | * format HH[MM[SS[.S[S[S[S]]]]]][+/-ZZZZ]. | |
110 | */ | |
111 | 85 | public CommonTM(String val) throws DataTypeException { |
112 | 85 | this.setValue(val); |
113 | 85 | } //end constructor |
114 | ||
115 | /** | |
116 | * This method takes in a string HL7 Time value and performs validations | |
117 | * then sets the value field. The stored value will be in the following | |
118 | * format HH[MM[SS[.S[S[S[S]]]]]][+/-ZZZZ]. | |
119 | * Note: Trailing zeros supplied in the time value (HH[MM[SS[.S[S[S[S]]]]]]) | |
120 | * and GMT offset ([+/-ZZZZ]) will be preserved. | |
121 | * Note: If the GMT offset is not supplied then the local | |
122 | * time zone (using standard time zone format which is not modified for daylight savings) | |
123 | * will be stored as a default. Passing in <code>null</code> clears any existing value. | |
124 | */ | |
125 | public void setValue(String val) throws DataTypeException { | |
126 | ||
127 | 725 | if (val != null && !val.equals("") && !val.equals("\"\"")) { |
128 | //check to see if any of the following characters exist: "." or "+/-" | |
129 | //this will help us determine the acceptable lengths | |
130 | ||
131 | 665 | int d = val.indexOf("."); |
132 | 665 | int sp = val.indexOf("+"); |
133 | 665 | int sm = val.indexOf("-"); |
134 | 665 | int indexOfSign = -1; |
135 | 665 | boolean offsetExists = false; |
136 | 665 | if ((sp != -1) || (sm != -1)) |
137 | 365 | offsetExists = true; |
138 | 665 | if (sp != -1) |
139 | 120 | indexOfSign = sp; |
140 | 665 | if (sm != -1) |
141 | 245 | indexOfSign = sm; |
142 | ||
143 | try { | |
144 | //If the GMT offset exists then extract it from the input string and store it | |
145 | //in another variable called tempOffset. Also, store the time value | |
146 | //(without the offset)in a separate variable called timeVal. | |
147 | //If there is no GMT offset then simply set timeVal to val. | |
148 | 665 | String timeVal = val; |
149 | 665 | String tempOffset = null; |
150 | 665 | if (offsetExists) { |
151 | 365 | timeVal = val.substring(0, indexOfSign); |
152 | 365 | tempOffset = val.substring(indexOfSign); |
153 | } //end if | |
154 | ||
155 | 665 | if (offsetExists && (tempOffset.length() != 5)) { |
156 | //The length of the GMT offset must be 5 characters (including the sign) | |
157 | 60 | String msg = |
158 | "The length of the TM datatype value does not conform to an allowable" | |
159 | + " format. Format should conform to HH[MM[SS[.S[S[S[S]]]]]][+/-ZZZZ]"; | |
160 | 60 | DataTypeException e = new DataTypeException(msg); |
161 | 60 | throw e; |
162 | } //end if | |
163 | ||
164 | 605 | if (d != -1) { |
165 | //here we know that decimal exists | |
166 | //thus length of the time value can be between 8 and 11 characters | |
167 | 260 | if ((timeVal.length() < 8) || (timeVal.length() > 11)) { |
168 | 15 | String msg = |
169 | "The length of the TM datatype value does not conform to an allowable" | |
170 | + " format. Format should conform to HH[MM[SS[.S[S[S[S]]]]]][+/-ZZZZ]"; | |
171 | 15 | DataTypeException e = new DataTypeException(msg); |
172 | 15 | throw e; |
173 | } //end if | |
174 | } //end if | |
175 | ||
176 | 590 | if (d == -1) { |
177 | //here we know that the decimal does not exist | |
178 | //thus length of the time value can be 2 or 4 or 6 characters | |
179 | 345 | if ((timeVal.length() != 2) && (timeVal.length() != 4) && (timeVal.length() != 6)) { |
180 | 55 | String msg = |
181 | "The length of the TM datatype value does not conform to an allowable" | |
182 | + " format. Format should conform to HH[MM[SS[.S[S[S[S]]]]]][+/-ZZZZ]"; | |
183 | 55 | DataTypeException e = new DataTypeException(msg); |
184 | 55 | throw e; |
185 | } //end if | |
186 | } //end if | |
187 | ||
188 | //We will now try to validate the timeVal portion of the TM datatype value | |
189 | 535 | if (timeVal.length() >= 2) { |
190 | //extract the hour data from the input value. If the first 2 characters | |
191 | //are not numeric then a number format exception will be generated | |
192 | 535 | int hrInt = Integer.parseInt(timeVal.substring(0, 2)); |
193 | //check to see if the hour value is valid | |
194 | 535 | if ((hrInt < 0) || (hrInt > 23)) { |
195 | 5 | String msg = "The hour value of the TM datatype must be >=0 and <=23"; |
196 | 5 | DataTypeException e = new DataTypeException(msg); |
197 | 5 | throw e; |
198 | } //end if | |
199 | 530 | hour = hrInt; |
200 | } //end if | |
201 | ||
202 | 530 | if (timeVal.length() >= 4) { |
203 | //extract the minute data from the input value | |
204 | //If these characters are not numeric then a number | |
205 | //format exception will be generated | |
206 | 515 | int minInt = Integer.parseInt(timeVal.substring(2, 4)); |
207 | //check to see if the minute value is valid | |
208 | 515 | if ((minInt < 0) || (minInt > 59)) { |
209 | 5 | String msg = "The minute value of the TM datatype must be >=0 and <=59"; |
210 | 5 | DataTypeException e = new DataTypeException(msg); |
211 | 5 | throw e; |
212 | } //end if | |
213 | 510 | minute = minInt; |
214 | } //end if | |
215 | ||
216 | 525 | if (timeVal.length() >= 6) { |
217 | //extract the seconds data from the input value | |
218 | //If these characters are not numeric then a number | |
219 | //format exception will be generated | |
220 | 410 | int secInt = Integer.parseInt(timeVal.substring(4, 6)); |
221 | //check to see if the seconds value is valid | |
222 | 410 | if ((secInt < 0) || (secInt > 59)) { |
223 | 5 | String msg = "The seconds value of the TM datatype must be >=0 and <=59"; |
224 | 5 | DataTypeException e = new DataTypeException(msg); |
225 | 5 | throw e; |
226 | } //end if | |
227 | 405 | second = secInt; |
228 | } //end if | |
229 | ||
230 | 520 | if (timeVal.length() >= 8) { |
231 | //extract the fractional second value from the input value | |
232 | //If these characters are not numeric then a number | |
233 | //format exception will be generated | |
234 | 245 | float fract = Float.parseFloat(timeVal.substring(6)); |
235 | //check to see if the fractional second value is valid | |
236 | 245 | if ((fract < 0) || (fract >= 1)) { |
237 | 0 | String msg = "The fractional second value of the TM datatype must be >= 0 and < 1"; |
238 | 0 | DataTypeException e = new DataTypeException(msg); |
239 | 0 | throw e; |
240 | } //end if | |
241 | 245 | fractionOfSec = fract; |
242 | } //end if | |
243 | ||
244 | //We will now try to validate the tempOffset portion of the TM datatype value | |
245 | 520 | if (offsetExists) { |
246 | //in case the offset are a series of zeros we should not omit displaying | |
247 | //it in the return value from the getValue() method | |
248 | 295 | omitOffsetFg = false; |
249 | //remove the sign from the temp offset | |
250 | 295 | String tempOffsetNoS = tempOffset.substring(1); |
251 | //extract the hour data from the offset value. If the first 2 characters | |
252 | //are not numeric then a number format exception will be generated | |
253 | 295 | int offsetInt = Integer.parseInt(tempOffsetNoS.substring(0, 2)); |
254 | //check to see if the hour value is valid | |
255 | 295 | if ((offsetInt < 0) || (offsetInt > 23)) { |
256 | 0 | String msg = "The GMT offset hour value of the TM datatype must be >=0 and <=23"; |
257 | 0 | DataTypeException e = new DataTypeException(msg); |
258 | 0 | throw e; |
259 | } //end if | |
260 | //extract the minute data from the offset value. If these characters | |
261 | //are not numeric then a number format exception will be generated | |
262 | 295 | offsetInt = Integer.parseInt(tempOffsetNoS.substring(2, 4)); |
263 | //check to see if the minute value is valid | |
264 | 295 | if ((offsetInt < 0) || (offsetInt > 59)) { |
265 | 30 | String msg = "The GMT offset minute value of the TM datatype must be >=0 and <=59"; |
266 | 30 | DataTypeException e = new DataTypeException(msg); |
267 | 30 | throw e; |
268 | } //end if | |
269 | //validation done, update the offSet field | |
270 | 265 | offSet = Integer.parseInt(tempOffsetNoS); |
271 | //add the sign back to the offset if it is negative | |
272 | 265 | if (sm != -1) { |
273 | 180 | offSet = -1 * offSet; |
274 | } //end if | |
275 | } //end if | |
276 | ||
277 | //If the GMT offset has not been supplied then set the offset to the | |
278 | //local timezone | |
279 | //[Bryan: changing this to omit time zone because erroneous if parser in different zone than sender] | |
280 | 490 | if (!offsetExists) { |
281 | 225 | omitOffsetFg = true; |
282 | // set the offSet field to the current time and local time zone | |
283 | //offSet = DataTypeUtil.getLocalGMTOffset(); | |
284 | } //end if | |
285 | ||
286 | //validations are now done store the time value into the private value field | |
287 | 490 | value = timeVal; |
288 | } //end try | |
289 | ||
290 | 175 | catch (DataTypeException e) { |
291 | 175 | throw e; |
292 | } //end catch | |
293 | ||
294 | 0 | catch (Exception e) { |
295 | 0 | throw new DataTypeException(e); |
296 | 490 | } //end catch |
297 | 490 | } //end if |
298 | else { | |
299 | //set the private value field to null or empty space. | |
300 | 60 | value = val; |
301 | } //end else | |
302 | 550 | } //end method |
303 | ||
304 | /** | |
305 | * This method takes in an integer value for the hour and performs validations, | |
306 | * it then sets the value field formatted as an HL7 time | |
307 | * value with hour precision (HH). | |
308 | */ | |
309 | public void setHourPrecision(int hr) throws DataTypeException { | |
310 | try { | |
311 | //validate input value | |
312 | 3523 | if ((hr < 0) || (hr > 23)) { |
313 | 65 | String msg = "The hour value of the TM datatype must be >=0 and <=23"; |
314 | 65 | DataTypeException e = new DataTypeException(msg); |
315 | 65 | throw e; |
316 | } //end if | |
317 | 3458 | hour = hr; |
318 | 3458 | minute = 0; |
319 | 3458 | second = 0; |
320 | 3458 | fractionOfSec = 0; |
321 | 3458 | offSet = 0; |
322 | //Here the offset is not defined, we should omit showing it in the | |
323 | //return value from the getValue() method | |
324 | 3458 | omitOffsetFg = true; |
325 | 3458 | value = DataTypeUtil.preAppendZeroes(hr, 2); |
326 | } //end try | |
327 | ||
328 | 65 | catch (DataTypeException e) { |
329 | 65 | throw e; |
330 | } //end catch | |
331 | ||
332 | 0 | catch (Exception e) { |
333 | 0 | throw new DataTypeException(e.getMessage()); |
334 | 3458 | } //end catch |
335 | ||
336 | 3458 | } //end method |
337 | ||
338 | /** | |
339 | * This method takes in integer values for the hour and minute and performs validations, | |
340 | * it then sets the value field formatted as an HL7 time value | |
341 | * with hour&minute precision (HHMM). | |
342 | */ | |
343 | public void setHourMinutePrecision(int hr, int min) throws DataTypeException { | |
344 | try { | |
345 | 3493 | this.setHourPrecision(hr); |
346 | //validate input minute value | |
347 | 3438 | if ((min < 0) || (min > 59)) { |
348 | 40 | String msg = "The minute value of the TM datatype must be >=0 and <=59"; |
349 | 40 | DataTypeException e = new DataTypeException(msg); |
350 | 40 | throw e; |
351 | } //end if | |
352 | 3398 | minute = min; |
353 | 3398 | second = 0; |
354 | 3398 | fractionOfSec = 0; |
355 | 3398 | offSet = 0; |
356 | //Here the offset is not defined, we should omit showing it in the | |
357 | //return value from the getValue() method | |
358 | 3398 | omitOffsetFg = true; |
359 | 3398 | value = value + DataTypeUtil.preAppendZeroes(min, 2); |
360 | } //end try | |
361 | ||
362 | 95 | catch (DataTypeException e) { |
363 | 95 | throw e; |
364 | } //end catch | |
365 | ||
366 | 0 | catch (Exception e) { |
367 | 0 | throw new DataTypeException(e.getMessage()); |
368 | 3398 | } //end catch |
369 | 3398 | } //end method |
370 | ||
371 | /** | |
372 | * This method takes in integer values for the hour, minute, seconds, and fractional seconds | |
373 | * (going to the tenthousandths precision). | |
374 | * The method performs validations and then sets the value field formatted as an | |
375 | * HL7 time value with a precision that starts from the hour and goes down to the tenthousandths | |
376 | * of a second (HHMMSS.SSSS). | |
377 | * Note: all of the precisions from tenths down to tenthousandths of a | |
378 | * second are optional. If the precision goes below tenthousandths of a second then the second | |
379 | * value will be rounded to the nearest tenthousandths of a second. | |
380 | */ | |
381 | public void setHourMinSecondPrecision(int hr, int min, float sec) throws DataTypeException { | |
382 | try { | |
383 | 3328 | this.setHourMinutePrecision(hr, min); |
384 | //multiply the seconds input value by 10000 and round the result | |
385 | //then divide the number by tenthousand and store it back. | |
386 | //This will round the fractional seconds to the nearest tenthousandths | |
387 | 3278 | int secMultRound = Math.round(10000F * sec); |
388 | 3278 | sec = secMultRound / 10000F; |
389 | //Now store the second and fractional component | |
390 | 3278 | second = (int) Math.floor(sec); |
391 | //validate input seconds value | |
392 | 3278 | if ((second < 0) || (second >= 60)) { |
393 | 35 | String msg = "The (rounded) second value of the TM datatype must be >=0 and <60"; |
394 | 35 | DataTypeException e = new DataTypeException(msg); |
395 | 35 | throw e; |
396 | } //end if | |
397 | 3243 | int fractionOfSecInt = (int) (secMultRound - (second * 10000)); |
398 | 3243 | fractionOfSec = fractionOfSecInt / 10000F; |
399 | 3243 | String fractString = ""; |
400 | //Now convert the fractionOfSec field to a string without the leading zero | |
401 | 3243 | if (fractionOfSec != 0.0F) { |
402 | 1732 | fractString = (Float.toString(fractionOfSec)).substring(1); |
403 | } //end if | |
404 | //Now update the value field | |
405 | 3243 | offSet = 0; |
406 | //Here the offset is not defined, we should omit showing it in the | |
407 | //return value from the getValue() method | |
408 | 3243 | omitOffsetFg = true; |
409 | 3243 | value = value + DataTypeUtil.preAppendZeroes(second, 2) + fractString; |
410 | } //end try | |
411 | ||
412 | 85 | catch (DataTypeException e) { |
413 | 85 | throw e; |
414 | } //end catch | |
415 | ||
416 | 0 | catch (Exception e) { |
417 | 0 | throw new DataTypeException(e); |
418 | 3243 | } //end catch |
419 | 3243 | } //end method |
420 | ||
421 | /** | |
422 | * This method takes in the four digit (signed) GMT offset and sets the offset | |
423 | * field | |
424 | */ | |
425 | public void setOffset(int signedOffset) throws DataTypeException { | |
426 | try { | |
427 | //When this function is called an offset is being created/updated | |
428 | //we should not omit displaying it in the return value from | |
429 | //the getValue() method | |
430 | 3303 | omitOffsetFg = false; |
431 | 3303 | String offsetStr = Integer.toString(signedOffset); |
432 | 3303 | if ((signedOffset >= 0 && offsetStr.length() > 4) || (signedOffset < 0 && offsetStr.length() > 5)) { |
433 | //The length of the GMT offset must be no greater than 5 characters (including the sign) | |
434 | 10 | String msg = |
435 | "The length of the GMT offset for the TM datatype value does" | |
436 | + " not conform to the allowable format [+/-ZZZZ]. Value: " + signedOffset; | |
437 | 10 | DataTypeException e = new DataTypeException(msg); |
438 | 10 | throw e; |
439 | } //end if | |
440 | //obtain the absolute value of the input | |
441 | 3293 | int absOffset = Math.abs(signedOffset); |
442 | //extract the hour data from the offset value. | |
443 | //first preappend zeros so we have a 4 char offset value (without sign) | |
444 | 3293 | offsetStr = DataTypeUtil.preAppendZeroes(absOffset, 4); |
445 | 3293 | int hrOffsetInt = Integer.parseInt(offsetStr.substring(0, 2)); |
446 | //check to see if the hour value is valid | |
447 | 3293 | if ((hrOffsetInt < 0) || (hrOffsetInt > 23)) { |
448 | 5 | String msg = "The GMT offset hour value of the TM datatype must be >=0 and <=23"; |
449 | 5 | DataTypeException e = new DataTypeException(msg); |
450 | 5 | throw e; |
451 | } //end if | |
452 | //extract the minute data from the offset value. | |
453 | 3288 | int minOffsetInt = Integer.parseInt(offsetStr.substring(2, 4)); |
454 | //check to see if the minute value is valid | |
455 | 3288 | if ((minOffsetInt < 0) || (minOffsetInt > 59)) { |
456 | 40 | String msg = "The GMT offset minute value of the TM datatype must be >=0 and <=59"; |
457 | 40 | DataTypeException e = new DataTypeException(msg); |
458 | 40 | throw e; |
459 | } //end if | |
460 | //The input value is valid, now store it in the offset field | |
461 | 3248 | offSet = signedOffset; |
462 | } //end try | |
463 | ||
464 | 55 | catch (DataTypeException e) { |
465 | 55 | throw e; |
466 | } //end catch | |
467 | ||
468 | 0 | catch (Exception e) { |
469 | 0 | throw new DataTypeException(e); |
470 | 3248 | } //end catch |
471 | 3248 | } //end method |
472 | ||
473 | /** | |
474 | * Returns the HL7 TM string value. | |
475 | */ | |
476 | public String getValue() { | |
477 | //combine the value field with the offSet field and return it | |
478 | 21658 | String returnVal = null; |
479 | 21658 | if (value != null && !value.equals("")) { |
480 | 21403 | if (omitOffsetFg == false && !value.equals("\"\"")) { |
481 | 19198 | int absOffset = Math.abs(offSet); |
482 | 19198 | String sign = ""; |
483 | 19198 | if (offSet >= 0) { |
484 | 5870 | sign = "+"; |
485 | } //end if | |
486 | else { | |
487 | 13328 | sign = "-"; |
488 | } //end else | |
489 | 19198 | returnVal = value + sign + DataTypeUtil.preAppendZeroes(absOffset, 4); |
490 | 19198 | } |
491 | else { | |
492 | 2205 | returnVal = value; |
493 | } //end else | |
494 | } //end if | |
495 | 21658 | return returnVal; |
496 | } //end method | |
497 | ||
498 | /** | |
499 | * Convenience setter which sets the value using a {@link Calendar} object. Passing in <code>null</code> clears any existing value. | |
500 | * | |
501 | * Note: Sets fields using precision up to the minute | |
502 | * | |
503 | * @param theCalendar The calendar object from which to retrieve values | |
504 | * @since 1.1 | |
505 | */ | |
506 | public void setValueToMinute(Calendar theCalendar) throws DataTypeException { | |
507 | 10 | if (theCalendar == null) { |
508 | 0 | setValue((String)null); |
509 | 0 | return; |
510 | } | |
511 | ||
512 | 10 | int hr = theCalendar.get(Calendar.HOUR_OF_DAY); |
513 | 10 | int min = theCalendar.get(Calendar.MINUTE); |
514 | 10 | setHourMinutePrecision(hr, min); |
515 | 10 | } |
516 | ||
517 | /** | |
518 | * Convenience setter which sets the value using a {@link Date} object. Passing in <code>null</code> clears any existing value. | |
519 | * | |
520 | * Note: Sets fields using precision up to the minute | |
521 | * Note: Date is timezone-agnostic, representing always GMT time | |
522 | * | |
523 | * @param theDate The date object from which to retrieve values | |
524 | * @since 1.1 | |
525 | */ | |
526 | public void setValueToMinute(Date theDate) throws DataTypeException { | |
527 | 5 | if (theDate == null) { |
528 | 0 | setValue((String)null); |
529 | 0 | return; |
530 | } | |
531 | ||
532 | 5 | Calendar calendar = Calendar.getInstance(); |
533 | 5 | calendar.setTime(theDate); |
534 | 5 | setValueToMinute(calendar); |
535 | 5 | } |
536 | ||
537 | /** | |
538 | * Convenience setter which sets the value using a {@link Calendar} object. Passing in <code>null</code> clears any existing value. | |
539 | * | |
540 | * Note: Sets fields using precision up to the second | |
541 | * | |
542 | * @param theCalendar The calendar object from which to retrieve values | |
543 | * @since 1.1 | |
544 | */ | |
545 | public void setValueToSecond(Calendar theCalendar) throws DataTypeException { | |
546 | 10 | if (theCalendar == null) { |
547 | 0 | setValue((String)null); |
548 | 0 | return; |
549 | } | |
550 | ||
551 | 10 | int hr = theCalendar.get(Calendar.HOUR_OF_DAY); |
552 | 10 | int min = theCalendar.get(Calendar.MINUTE); |
553 | 10 | int sec = theCalendar.get(Calendar.SECOND); |
554 | ||
555 | 10 | setHourMinSecondPrecision(hr, min, sec); |
556 | 10 | } |
557 | ||
558 | /** | |
559 | * Convenience setter which sets the value using a {@link Calendar} object. Passing in <code>null</code> clears any existing value. | |
560 | * | |
561 | * Note: Sets fields using precision up to the millisecond, including timezone offset | |
562 | * | |
563 | * @param theCalendar The calendar object from which to retrieve values | |
564 | * @since 1.1 | |
565 | */ | |
566 | public void setValue(Calendar theCalendar) throws DataTypeException { | |
567 | 25 | if (theCalendar == null) { |
568 | 0 | setValue((String)null); |
569 | 0 | return; |
570 | } | |
571 | ||
572 | 25 | int hr = theCalendar.get(Calendar.HOUR_OF_DAY); |
573 | 25 | int min = theCalendar.get(Calendar.MINUTE); |
574 | 25 | float sec = theCalendar.get(Calendar.SECOND) + (theCalendar.get(Calendar.MILLISECOND) / 1000.0F); |
575 | 25 | setHourMinSecondPrecision(hr, min, sec); |
576 | ||
577 | // 3410095: care for integer overflow and timezones not at the full hour, e.g. India | |
578 | 25 | int hourOffset= theCalendar.get(Calendar.ZONE_OFFSET) / (1000 * 60 * 60); |
579 | 25 | int minuteOffset = (theCalendar.get(Calendar.ZONE_OFFSET) / (1000 * 60)) % 60; |
580 | 25 | int zoneOffset = hourOffset * 100 + minuteOffset; |
581 | 25 | setOffset(zoneOffset); |
582 | 25 | } |
583 | ||
584 | /** | |
585 | * Convenience setter which sets the value using a {@link Calendar} object. Passing in <code>null</code> clears any existing value. | |
586 | * | |
587 | * Note: Sets fields using precision up to the millisecond, and sets the timezone offset to | |
588 | * the current system offset | |
589 | * Note: Date is timezone-agnostic, representing always GMT time | |
590 | * | |
591 | * @param theDate The calendar object from which to retrieve values | |
592 | * @since 1.1 | |
593 | */ | |
594 | public void setValue(Date theDate) throws DataTypeException { | |
595 | 0 | if (theDate == null) { |
596 | 0 | setValue((String)null); |
597 | 0 | return; |
598 | } | |
599 | ||
600 | 0 | GregorianCalendar cal = new GregorianCalendar(); |
601 | 0 | cal.setTime(theDate); |
602 | 0 | setValue(cal); |
603 | 0 | } |
604 | ||
605 | /** | |
606 | * Convenience setter which sets the value using a {@link Date} object. Passing in <code>null</code> clears any existing value. | |
607 | * | |
608 | * Note: Sets fields using precision up to the second | |
609 | * Note: Date is timezone-agnostic, representing always GMT time | |
610 | * | |
611 | * @param theDate The date object from which to retrieve values | |
612 | * @since 1.1 | |
613 | */ | |
614 | public void setValueToSecond(Date theDate) throws DataTypeException { | |
615 | 5 | if (theDate == null) { |
616 | 0 | setValue((String)null); |
617 | 0 | return; |
618 | } | |
619 | ||
620 | 5 | Calendar calendar = Calendar.getInstance(); |
621 | 5 | calendar.setTime(theDate); |
622 | 5 | setValueToSecond(calendar); |
623 | 5 | } |
624 | ||
625 | /** | |
626 | * <p>Return the value as a calendar object.</p> | |
627 | * | |
628 | * <b>Note that only the time component of the return value is set to | |
629 | * the value from this object. Returned value will have today's date</b> | |
630 | * @since 1.1 | |
631 | */ | |
632 | public Calendar getValueAsCalendar() { | |
633 | 920 | int gmtOff = getGMTOffset(); |
634 | Calendar retVal; | |
635 | 920 | if (gmtOff != GMT_OFFSET_NOT_SET_VALUE && !omitOffsetFg) { |
636 | 860 | int hrOffset = gmtOff / 100; |
637 | 860 | int minOffset = Math.abs(gmtOff % 100); |
638 | 860 | String timeZone = String.format("GMT%+d:%02d", hrOffset, minOffset); |
639 | 860 | retVal = new GregorianCalendar(TimeZone.getTimeZone(timeZone)); |
640 | 860 | } else { |
641 | 60 | retVal = Calendar.getInstance(); |
642 | } | |
643 | ||
644 | 920 | retVal.set(Calendar.HOUR_OF_DAY, getHour()); |
645 | 920 | retVal.set(Calendar.MINUTE, getMinute()); |
646 | 920 | retVal.set(Calendar.SECOND, getSecond()); |
647 | 920 | float fractSecond = getFractSecond(); |
648 | 920 | retVal.set(Calendar.MILLISECOND, (int) Math.round(fractSecond * 1000.0)); |
649 | ||
650 | 920 | return retVal; |
651 | } | |
652 | ||
653 | ||
654 | /** | |
655 | * <p>Return the value as a date object</p> | |
656 | * | |
657 | * <b>Note that only the time component of the return value is set to | |
658 | * the value from this object. Returned value will have today's date</b> | |
659 | * Note: Date is timezone-agnostic, representing always GMT time | |
660 | * @since 1.1 | |
661 | */ | |
662 | public Date getValueAsDate() { | |
663 | 10 | return getValueAsCalendar().getTime(); |
664 | } | |
665 | ||
666 | /** | |
667 | * Returns the hour as an integer. | |
668 | */ | |
669 | public int getHour() { | |
670 | 1470 | return hour; |
671 | } //end method | |
672 | ||
673 | /** | |
674 | * Returns the minute as an integer. | |
675 | */ | |
676 | public int getMinute() { | |
677 | 1470 | return minute; |
678 | } //end method | |
679 | ||
680 | /** | |
681 | * Returns the second as an integer. | |
682 | */ | |
683 | public int getSecond() { | |
684 | 1470 | return second; |
685 | } //end method | |
686 | ||
687 | /** | |
688 | * Returns the fractional second value as a float. | |
689 | */ | |
690 | public float getFractSecond() { | |
691 | 1470 | return fractionOfSec; |
692 | } //end method | |
693 | ||
694 | /** | |
695 | * Returns the GMT offset value as an integer, {@link #GMT_OFFSET_NOT_SET_VALUE} if not set. | |
696 | */ | |
697 | public int getGMTOffset() { | |
698 | 1690 | return offSet; |
699 | } //end method | |
700 | ||
701 | /** | |
702 | * Returns a string value representing the input Gregorian Calendar object in | |
703 | * an Hl7 Time Format. | |
704 | */ | |
705 | public static String toHl7TMFormat(GregorianCalendar cal) throws DataTypeException { | |
706 | 25 | String val = ""; |
707 | try { | |
708 | //set the input cal object so that it can report errors | |
709 | //on it's value | |
710 | 25 | cal.setLenient(false); |
711 | 25 | int calHour = cal.get(GregorianCalendar.HOUR_OF_DAY); |
712 | 25 | int calMin = cal.get(GregorianCalendar.MINUTE); |
713 | 25 | int calSec = cal.get(GregorianCalendar.SECOND); |
714 | 25 | int calMilli = cal.get(GregorianCalendar.MILLISECOND); |
715 | //the inputs seconds and milli seconds should be combined into a float type | |
716 | 25 | float fractSec = calMilli / 1000F; |
717 | 25 | float calSecFloat = calSec + fractSec; |
718 | 25 | int calOffset = cal.get(GregorianCalendar.ZONE_OFFSET) + cal.get(GregorianCalendar.DST_OFFSET); |
719 | //Note the input's Offset value is in milliseconds, we must convert it to | |
720 | //a 4 digit integer in the HL7 Offset format. | |
721 | int offSetSignInt; | |
722 | 25 | if (calOffset < 0) { |
723 | 15 | offSetSignInt = -1; |
724 | } | |
725 | else { | |
726 | 10 | offSetSignInt = 1; |
727 | } | |
728 | //get the absolute value of the gmtOffSet | |
729 | 25 | int absGmtOffSet = Math.abs(calOffset); |
730 | 25 | int gmtOffSetHours = absGmtOffSet / (3600 * 1000); |
731 | 25 | int gmtOffSetMin = (absGmtOffSet / 60000) % (60); |
732 | //reset calOffset | |
733 | 25 | calOffset = ((gmtOffSetHours * 100) + gmtOffSetMin) * offSetSignInt; |
734 | //Create an object of the TS class and populate it with the above values | |
735 | //then return the HL7 string value from the object | |
736 | 25 | CommonTM tm = new CommonTM(); |
737 | 25 | tm.setHourMinSecondPrecision(calHour, calMin, calSecFloat); |
738 | 25 | tm.setOffset(calOffset); |
739 | 25 | val = tm.getValue(); |
740 | } // end try | |
741 | ||
742 | 0 | catch (DataTypeException e) { |
743 | 0 | throw e; |
744 | } //end catch | |
745 | ||
746 | 0 | catch (Exception e) { |
747 | 0 | throw new DataTypeException(e); |
748 | 25 | } //end catch |
749 | 25 | return val; |
750 | } //end method | |
751 | ||
752 | } //end class |