| 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 |