001/** 002 * The contents of this file are subject to the Mozilla Public License Version 1.1 003 * (the "License"); you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at http://www.mozilla.org/MPL/ 005 * Software distributed under the License is distributed on an "AS IS" basis, 006 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 007 * specific language governing rights and limitations under the License. 008 * 009 * The Original Code is "CommmonTM.java". Description: 010 * "Note: The class description below has been excerpted from the Hl7 2.4 documentation" 011 * 012 * The Initial Developer of the Original Code is University Health Network. Copyright (C) 013 * 2001. All Rights Reserved. 014 * 015 * Contributor(s): ______________________________________. 016 * 017 * Alternatively, the contents of this file may be used under the terms of the 018 * GNU General Public License (the "GPL"), in which case the provisions of the GPL are 019 * applicable instead of those above. If you wish to allow use of your version of this 020 * file only under the terms of the GPL and not to allow others to use your version 021 * of this file under the MPL, indicate your decision by deleting the provisions above 022 * and replace them with the notice and other provisions required by the GPL License. 023 * If you do not delete the provisions above, a recipient may use your version of 024 * this file under either the MPL or the GPL. 025 * 026 */ 027 028package ca.uhn.hl7v2.model.primitive; 029 030import java.util.Calendar; 031import java.util.Date; 032import java.util.GregorianCalendar; 033import java.util.TimeZone; 034import java.io.Serializable; 035 036import ca.uhn.hl7v2.model.DataTypeException; 037import ca.uhn.hl7v2.model.DataTypeUtil; 038 039/** 040 * This class contains functionality used by the TM class 041 * in the version 2.3.0, 2.3.1, and 2.4 packages 042 * 043 * Note: The class description below has been excerpted from the Hl7 2.4 documentation. Sectional 044 * references made below also refer to the same documentation. 045 * 046 * Format: HH[MM[SS[.S[S[S[S]]]]]][+/-ZZZZ] 047 * In prior versions of HL7, this data type was always specified to be in the 048 * format HHMM[SS[.SSSS]][+/-ZZZZ] using a 24 hour clock notation. In the 049 * current and future versions, the precision of a time may be expressed by 050 * limiting the number of digits used with the format specification as shown 051 * above. By site-specific agreement, HHMM[SS[.SSSS]][+/-ZZZZ] may be used where 052 * backward compatibility must be maintained. 053 * Thus, HH is used to specify a precision of "hour," HHMM is used to specify a 054 * precision of "minute," HHMMSS is used to specify a precision of seconds, and 055 * HHMMSS.SSSS is used to specify a precision of ten-thousandths of a second. 056 * In each of these cases, the time zone is an optional component. The fractional 057 * seconds could be sent by a transmitter who requires greater precision than whole 058 * seconds. Fractional representations of minutes, hours or other higher-order units 059 * of time are not permitted. 060 * Note: The time zone [+/-ZZZZ], when used, is restricted to legally-defined time zones 061 * and is represented in HHMM format. 062 * The time zone of the sender may be sent optionally as an offset from the coordinated 063 * universal time (previously known as Greenwich Mean Time). Where the time zone 064 * is not present in a particular TM field but is included as part of the date/time 065 * field in the MSH segment, the MSH value will be used as the default time zone. 066 * Otherwise, the time is understood to refer to the local time of the sender. 067 * Midnight is represented as 0000. 068 * Examples:|235959+1100| 1 second before midnight in a time zone eleven hours 069 * ahead of Universal Coordinated Time (i.e., east of Greenwich). 070 * |0800| Eight AM, local time of the sender. 071 * |093544.2312| 44.2312 seconds after Nine thirty-five AM, local time of sender. 072 * |13| 1pm (with a precision of hours), local time of sender. 073 * @author Neal Acharya 074 */ 075 076@SuppressWarnings("serial") 077public class CommonTM implements Serializable { 078 079 /** 080 * Value returned by {@link #getGMTOffset()} if no offset is set 081 */ 082 public static final int GMT_OFFSET_NOT_SET_VALUE = -99; 083 084 private String value; 085 private int hour; 086 private int minute; 087 private int second; 088 private float fractionOfSec; 089 private int offSet; 090 private boolean omitOffsetFg = false; 091 092 /** 093 * Constructs a TM datatype with fields initialzed to zero and the value set to 094 * null. 095 */ 096 public CommonTM() { 097 //initialize all DT fields 098 value = null; 099 hour = 0; 100 minute = 0; 101 second = 0; 102 fractionOfSec = 0; 103 offSet = GMT_OFFSET_NOT_SET_VALUE; 104 } //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 public CommonTM(String val) throws DataTypeException { 112 this.setValue(val); 113 } //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 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 int d = val.indexOf("."); 132 int sp = val.indexOf("+"); 133 int sm = val.indexOf("-"); 134 int indexOfSign = -1; 135 boolean offsetExists = false; 136 if ((sp != -1) || (sm != -1)) 137 offsetExists = true; 138 if (sp != -1) 139 indexOfSign = sp; 140 if (sm != -1) 141 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 String timeVal = val; 149 String tempOffset = null; 150 if (offsetExists) { 151 timeVal = val.substring(0, indexOfSign); 152 tempOffset = val.substring(indexOfSign); 153 } //end if 154 155 if (offsetExists && (tempOffset.length() != 5)) { 156 //The length of the GMT offset must be 5 characters (including the sign) 157 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 DataTypeException e = new DataTypeException(msg); 161 throw e; 162 } //end if 163 164 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 if ((timeVal.length() < 8) || (timeVal.length() > 11)) { 168 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 DataTypeException e = new DataTypeException(msg); 172 throw e; 173 } //end if 174 } //end if 175 176 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 if ((timeVal.length() != 2) && (timeVal.length() != 4) && (timeVal.length() != 6)) { 180 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 DataTypeException e = new DataTypeException(msg); 184 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 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 int hrInt = Integer.parseInt(timeVal.substring(0, 2)); 193 //check to see if the hour value is valid 194 if ((hrInt < 0) || (hrInt > 23)) { 195 String msg = "The hour value of the TM datatype must be >=0 and <=23"; 196 DataTypeException e = new DataTypeException(msg); 197 throw e; 198 } //end if 199 hour = hrInt; 200 } //end if 201 202 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 int minInt = Integer.parseInt(timeVal.substring(2, 4)); 207 //check to see if the minute value is valid 208 if ((minInt < 0) || (minInt > 59)) { 209 String msg = "The minute value of the TM datatype must be >=0 and <=59"; 210 DataTypeException e = new DataTypeException(msg); 211 throw e; 212 } //end if 213 minute = minInt; 214 } //end if 215 216 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 int secInt = Integer.parseInt(timeVal.substring(4, 6)); 221 //check to see if the seconds value is valid 222 if ((secInt < 0) || (secInt > 59)) { 223 String msg = "The seconds value of the TM datatype must be >=0 and <=59"; 224 DataTypeException e = new DataTypeException(msg); 225 throw e; 226 } //end if 227 second = secInt; 228 } //end if 229 230 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 float fract = Float.parseFloat(timeVal.substring(6)); 235 //check to see if the fractional second value is valid 236 if ((fract < 0) || (fract >= 1)) { 237 String msg = "The fractional second value of the TM datatype must be >= 0 and < 1"; 238 DataTypeException e = new DataTypeException(msg); 239 throw e; 240 } //end if 241 fractionOfSec = fract; 242 } //end if 243 244 //We will now try to validate the tempOffset portion of the TM datatype value 245 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 omitOffsetFg = false; 249 //remove the sign from the temp offset 250 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 int offsetInt = Integer.parseInt(tempOffsetNoS.substring(0, 2)); 254 //check to see if the hour value is valid 255 if ((offsetInt < 0) || (offsetInt > 23)) { 256 String msg = "The GMT offset hour value of the TM datatype must be >=0 and <=23"; 257 DataTypeException e = new DataTypeException(msg); 258 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 offsetInt = Integer.parseInt(tempOffsetNoS.substring(2, 4)); 263 //check to see if the minute value is valid 264 if ((offsetInt < 0) || (offsetInt > 59)) { 265 String msg = "The GMT offset minute value of the TM datatype must be >=0 and <=59"; 266 DataTypeException e = new DataTypeException(msg); 267 throw e; 268 } //end if 269 //validation done, update the offSet field 270 offSet = Integer.parseInt(tempOffsetNoS); 271 //add the sign back to the offset if it is negative 272 if (sm != -1) { 273 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 if (!offsetExists) { 281 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 value = timeVal; 288 } //end try 289 290 catch (DataTypeException e) { 291 throw e; 292 } //end catch 293 294 catch (Exception e) { 295 throw new DataTypeException(e); 296 } //end catch 297 } //end if 298 else { 299 //set the private value field to null or empty space. 300 value = val; 301 } //end else 302 } //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 if ((hr < 0) || (hr > 23)) { 313 String msg = "The hour value of the TM datatype must be >=0 and <=23"; 314 DataTypeException e = new DataTypeException(msg); 315 throw e; 316 } //end if 317 hour = hr; 318 minute = 0; 319 second = 0; 320 fractionOfSec = 0; 321 offSet = 0; 322 //Here the offset is not defined, we should omit showing it in the 323 //return value from the getValue() method 324 omitOffsetFg = true; 325 value = DataTypeUtil.preAppendZeroes(hr, 2); 326 } //end try 327 328 catch (DataTypeException e) { 329 throw e; 330 } //end catch 331 332 catch (Exception e) { 333 throw new DataTypeException(e.getMessage()); 334 } //end catch 335 336 } //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 this.setHourPrecision(hr); 346 //validate input minute value 347 if ((min < 0) || (min > 59)) { 348 String msg = "The minute value of the TM datatype must be >=0 and <=59"; 349 DataTypeException e = new DataTypeException(msg); 350 throw e; 351 } //end if 352 minute = min; 353 second = 0; 354 fractionOfSec = 0; 355 offSet = 0; 356 //Here the offset is not defined, we should omit showing it in the 357 //return value from the getValue() method 358 omitOffsetFg = true; 359 value = value + DataTypeUtil.preAppendZeroes(min, 2); 360 } //end try 361 362 catch (DataTypeException e) { 363 throw e; 364 } //end catch 365 366 catch (Exception e) { 367 throw new DataTypeException(e.getMessage()); 368 } //end catch 369 } //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 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 int secMultRound = Math.round(10000F * sec); 388 sec = secMultRound / 10000F; 389 //Now store the second and fractional component 390 second = (int) Math.floor(sec); 391 //validate input seconds value 392 if ((second < 0) || (second >= 60)) { 393 String msg = "The (rounded) second value of the TM datatype must be >=0 and <60"; 394 DataTypeException e = new DataTypeException(msg); 395 throw e; 396 } //end if 397 int fractionOfSecInt = (int) (secMultRound - (second * 10000)); 398 fractionOfSec = fractionOfSecInt / 10000F; 399 String fractString = ""; 400 //Now convert the fractionOfSec field to a string without the leading zero 401 if (fractionOfSec != 0.0F) { 402 fractString = (Float.toString(fractionOfSec)).substring(1); 403 } //end if 404 //Now update the value field 405 offSet = 0; 406 //Here the offset is not defined, we should omit showing it in the 407 //return value from the getValue() method 408 omitOffsetFg = true; 409 value = value + DataTypeUtil.preAppendZeroes(second, 2) + fractString; 410 } //end try 411 412 catch (DataTypeException e) { 413 throw e; 414 } //end catch 415 416 catch (Exception e) { 417 throw new DataTypeException(e); 418 } //end catch 419 } //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 omitOffsetFg = false; 431 String offsetStr = Integer.toString(signedOffset); 432 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 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 DataTypeException e = new DataTypeException(msg); 438 throw e; 439 } //end if 440 //obtain the absolute value of the input 441 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 offsetStr = DataTypeUtil.preAppendZeroes(absOffset, 4); 445 int hrOffsetInt = Integer.parseInt(offsetStr.substring(0, 2)); 446 //check to see if the hour value is valid 447 if ((hrOffsetInt < 0) || (hrOffsetInt > 23)) { 448 String msg = "The GMT offset hour value of the TM datatype must be >=0 and <=23"; 449 DataTypeException e = new DataTypeException(msg); 450 throw e; 451 } //end if 452 //extract the minute data from the offset value. 453 int minOffsetInt = Integer.parseInt(offsetStr.substring(2, 4)); 454 //check to see if the minute value is valid 455 if ((minOffsetInt < 0) || (minOffsetInt > 59)) { 456 String msg = "The GMT offset minute value of the TM datatype must be >=0 and <=59"; 457 DataTypeException e = new DataTypeException(msg); 458 throw e; 459 } //end if 460 //The input value is valid, now store it in the offset field 461 offSet = signedOffset; 462 } //end try 463 464 catch (DataTypeException e) { 465 throw e; 466 } //end catch 467 468 catch (Exception e) { 469 throw new DataTypeException(e); 470 } //end catch 471 } //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 String returnVal = null; 479 if (value != null && !value.equals("")) { 480 if (omitOffsetFg == false && !value.equals("\"\"")) { 481 int absOffset = Math.abs(offSet); 482 String sign = ""; 483 if (offSet >= 0) { 484 sign = "+"; 485 } //end if 486 else { 487 sign = "-"; 488 } //end else 489 returnVal = value + sign + DataTypeUtil.preAppendZeroes(absOffset, 4); 490 } 491 else { 492 returnVal = value; 493 } //end else 494 } //end if 495 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 if (theCalendar == null) { 508 setValue((String)null); 509 return; 510 } 511 512 int hr = theCalendar.get(Calendar.HOUR_OF_DAY); 513 int min = theCalendar.get(Calendar.MINUTE); 514 setHourMinutePrecision(hr, min); 515 } 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 if (theDate == null) { 528 setValue((String)null); 529 return; 530 } 531 532 Calendar calendar = Calendar.getInstance(); 533 calendar.setTime(theDate); 534 setValueToMinute(calendar); 535 } 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 if (theCalendar == null) { 547 setValue((String)null); 548 return; 549 } 550 551 int hr = theCalendar.get(Calendar.HOUR_OF_DAY); 552 int min = theCalendar.get(Calendar.MINUTE); 553 int sec = theCalendar.get(Calendar.SECOND); 554 555 setHourMinSecondPrecision(hr, min, sec); 556 } 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 if (theCalendar == null) { 568 setValue((String)null); 569 return; 570 } 571 572 int hr = theCalendar.get(Calendar.HOUR_OF_DAY); 573 int min = theCalendar.get(Calendar.MINUTE); 574 float sec = theCalendar.get(Calendar.SECOND) + (theCalendar.get(Calendar.MILLISECOND) / 1000.0F); 575 setHourMinSecondPrecision(hr, min, sec); 576 577 // 3410095: care for integer overflow and timezones not at the full hour, e.g. India 578 int hourOffset= theCalendar.get(Calendar.ZONE_OFFSET) / (1000 * 60 * 60); 579 int minuteOffset = (theCalendar.get(Calendar.ZONE_OFFSET) / (1000 * 60)) % 60; 580 int zoneOffset = hourOffset * 100 + minuteOffset; 581 setOffset(zoneOffset); 582 } 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 if (theDate == null) { 596 setValue((String)null); 597 return; 598 } 599 600 GregorianCalendar cal = new GregorianCalendar(); 601 cal.setTime(theDate); 602 setValue(cal); 603 } 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 if (theDate == null) { 616 setValue((String)null); 617 return; 618 } 619 620 Calendar calendar = Calendar.getInstance(); 621 calendar.setTime(theDate); 622 setValueToSecond(calendar); 623 } 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 int gmtOff = getGMTOffset(); 634 Calendar retVal; 635 if (gmtOff != GMT_OFFSET_NOT_SET_VALUE && !omitOffsetFg) { 636 int hrOffset = gmtOff / 100; 637 int minOffset = Math.abs(gmtOff % 100); 638 String timeZone = String.format("GMT%+d:%02d", hrOffset, minOffset); 639 retVal = new GregorianCalendar(TimeZone.getTimeZone(timeZone)); 640 } else { 641 retVal = Calendar.getInstance(); 642 } 643 644 retVal.set(Calendar.HOUR_OF_DAY, getHour()); 645 retVal.set(Calendar.MINUTE, getMinute()); 646 retVal.set(Calendar.SECOND, getSecond()); 647 float fractSecond = getFractSecond(); 648 retVal.set(Calendar.MILLISECOND, (int) Math.round(fractSecond * 1000.0)); 649 650 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 return getValueAsCalendar().getTime(); 664 } 665 666 /** 667 * Returns the hour as an integer. 668 */ 669 public int getHour() { 670 return hour; 671 } //end method 672 673 /** 674 * Returns the minute as an integer. 675 */ 676 public int getMinute() { 677 return minute; 678 } //end method 679 680 /** 681 * Returns the second as an integer. 682 */ 683 public int getSecond() { 684 return second; 685 } //end method 686 687 /** 688 * Returns the fractional second value as a float. 689 */ 690 public float getFractSecond() { 691 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 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 String val = ""; 707 try { 708 //set the input cal object so that it can report errors 709 //on it's value 710 cal.setLenient(false); 711 int calHour = cal.get(GregorianCalendar.HOUR_OF_DAY); 712 int calMin = cal.get(GregorianCalendar.MINUTE); 713 int calSec = cal.get(GregorianCalendar.SECOND); 714 int calMilli = cal.get(GregorianCalendar.MILLISECOND); 715 //the inputs seconds and milli seconds should be combined into a float type 716 float fractSec = calMilli / 1000F; 717 float calSecFloat = calSec + fractSec; 718 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 if (calOffset < 0) { 723 offSetSignInt = -1; 724 } 725 else { 726 offSetSignInt = 1; 727 } 728 //get the absolute value of the gmtOffSet 729 int absGmtOffSet = Math.abs(calOffset); 730 int gmtOffSetHours = absGmtOffSet / (3600 * 1000); 731 int gmtOffSetMin = (absGmtOffSet / 60000) % (60); 732 //reset calOffset 733 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 CommonTM tm = new CommonTM(); 737 tm.setHourMinSecondPrecision(calHour, calMin, calSecFloat); 738 tm.setOffset(calOffset); 739 val = tm.getValue(); 740 } // end try 741 742 catch (DataTypeException e) { 743 throw e; 744 } //end catch 745 746 catch (Exception e) { 747 throw new DataTypeException(e); 748 } //end catch 749 return val; 750 } //end method 751 752} //end class