Coverage Report - ca.uhn.hl7v2.model.primitive.CommonTS
 
Classes in this File Line Coverage Branch Coverage Complexity
CommonTS
87%
239/273
80%
96/120
4.692
 
 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  
  *
 10  
  *
 11  
  * The Initial Developer of the Original Code is University Health Network. Copyright (C)
 12  
  * 2001.  All Rights Reserved.
 13  
  *
 14  
  * Contributor(s): ______________________________________.
 15  
  *
 16  
  * Alternatively, the contents of this file may be used under the terms of the
 17  
  * GNU General Public License (the "GPL"), in which case the provisions of the GPL are
 18  
  * applicable instead of those above.  If you wish to allow use of your version of this
 19  
  * file only under the terms of the GPL and not to allow others to use your version
 20  
  * of this file under the MPL, indicate your decision by deleting  the provisions above
 21  
  * and replace  them with the notice and other provisions required by the GPL License.
 22  
  * If you do not delete the provisions above, a recipient may use your version of
 23  
  * this file under either the MPL or the GPL.
 24  
  *
 25  
  */
 26  
 
 27  
 package ca.uhn.hl7v2.model.primitive;
 28  
 
 29  
 import java.util.Calendar;
 30  
 import java.util.Date;
 31  
 import java.util.GregorianCalendar;
 32  
 import java.io.Serializable;
 33  
 
 34  
 import ca.uhn.hl7v2.model.DataTypeException;
 35  
 import ca.uhn.hl7v2.model.DataTypeUtil;
 36  
 
 37  
 /**
 38  
  * <p>
 39  
  * This class contains functionality used by the TS class
 40  
  * in the version 2.3.0, 2.3.1, and 2.4 packages
 41  
  * </p>
 42  
  * 
 43  
  * <p>
 44  
  * Note: The class description below has been excerpted from the Hl7 2.4 documentation. Sectional
 45  
  * references made below also refer to the same documentation.
 46  
  * </p>
 47  
  *
 48  
  * <p>
 49  
  * Format: YYYY[MM[DD[HHMM[SS[.S[S[S[S]]]]]]]][+/-ZZZZ]^<degree of precision>
 50  
  * </p>
 51  
  * 
 52  
  * <p>
 53  
  * Contains the exact time of an event, including the date and time. The date portion of a time stamp follows the rules of a
 54  
  * date field and the time portion follows the rules of a time field. The time zone (+/-ZZZZ) is represented as +/-HHMM
 55  
  * offset from UTC (formerly Greenwich Mean Time (GMT)), where +0000 or -0000 both represent UTC (without offset).
 56  
  * The specific data representations used in the HL7 encoding rules are compatible with ISO 8824-1987(E).
 57  
  * In prior versions of HL7, an optional second component indicates the degree of precision of the time stamp (Y = year, L
 58  
  * = month, D = day, H = hour, M = minute, S = second). This optional second component is retained only for purposes of
 59  
  * backward compatibility.
 60  
  * </p>
 61  
  * 
 62  
  * <p>
 63  
  * By site-specific agreement, YYYYMMDD[HHMM[SS[.S[S[S[S]]]]]][+/-ZZZZ]^<degree of precision> may be used
 64  
  * where backward compatibility must be maintained.
 65  
  * In the current and future versions of HL7, the precision is indicated by limiting the number of digits used, unless the
 66  
  * optional second component is present. Thus, YYYY is used to specify a precision of "year," YYYYMM specifies a
 67  
  * precision of "month," YYYYMMDD specifies a precision of "day," YYYYMMDDHH is used to specify a precision of
 68  
  * "hour," YYYYMMDDHHMM is used to specify a precision of "minute," YYYYMMDDHHMMSS is used to specify a
 69  
  * precision of seconds, and YYYYMMDDHHMMSS.SSSS is used to specify a precision of ten thousandths of a second.
 70  
  * In each of these cases, the time zone is an optional component. Note that if the time zone is not included, the timezone
 71  
  * defaults to that of the local time zone of the sender. Also note that a TS valued field with the HHMM part set to "0000"
 72  
  * represents midnight of the night extending from the previous day to the day given by the YYYYMMDD part (see example
 73  
  * below). Maximum length of the time stamp is 26. 
 74  
  * </p>
 75  
  * <p>
 76  
  * Examples: <br/>
 77  
  * |19760704010159-0500|<br/>
 78  
  * 1:01:59 on July 4, 1976 in the Eastern Standard Time zone (USA).<br/>
 79  
  * |19760704010159-0400|<br/>
 80  
  * 1:01:59 on July 4, 1976 in the Eastern Daylight Saving Time zone (USA).<br/>
 81  
  * |198807050000|<br/>
 82  
  * Midnight of the night extending from July 4 to July 5, 1988 in the local time zone of the sender.<br/>
 83  
  * |19880705|<br/>
 84  
  * Same as prior example, but precision extends only to the day. Could be used for a birthdate, if the time of birth is
 85  
  * unknown.<br/>
 86  
  * |19981004010159+0100|<br/>
 87  
  * 1:01:59 on October 4, 1998 in Amsterdam, NL. (Time zone=+0100).<br/>
 88  
  * </p>
 89  
  * <p>
 90  
  * The HL7 Standard strongly recommends that all systems routinely send the time zone offset but does not require it. All
 91  
  * HL7 systems are required to accept the time zone offset, but its implementation is application specific. For many
 92  
  * applications the time of interest is the local time of the sender. For example, an application in the Eastern Standard Time
 93  
  * zone receiving notification of an admission that takes place at 11:00 PM in San Francisco on December 11 would prefer
 94  
  * to treat the admission as having occurred on December 11 rather than advancing the date to December 12.
 95  
  * </p>
 96  
  * <p>
 97  
  * Note: The time zone [+/-ZZZZ], when used, is restricted to legally-defined time zones and is represented in HHMM
 98  
  * format.
 99  
  * </p>
 100  
  * <p>
 101  
  * One exception to this rule would be a clinical system that processed patient data collected in a clinic and a nearby hospital
 102  
  * that happens to be in a different time zone. Such applications may choose to convert the data to a common
 103  
  * representation. Similar concerns apply to the transitions to and from daylight saving time. HL7 supports such requirements
 104  
  * by requiring that the time zone information be present when the information is sent. It does not, however, specify which of
 105  
  * the treatments discussed here will be applied by the receiving system.
 106  
  * </p>
 107  
  * @author Neal Acharya
 108  
  */
 109  
 
 110  
 @SuppressWarnings("serial")
 111  
 public class CommonTS implements Serializable {
 112  
 
 113  
     private CommonDT dt;
 114  
     private CommonTM tm;
 115  
 
 116  
     /** Creates new ValidTS
 117  
      * zero argument constructor.
 118  
      * Creates an uninitailized TS datatype
 119  
      */
 120  432
     public CommonTS() {
 121  432
     } //zero arg constructor
 122  
 
 123  
     /**
 124  
      * Constructs a TS object with the given value.
 125  
      * The stored value will be in the following
 126  
      * format YYYY[MM[DD[HHMM[SS[.S[S[S[S]]]]]]]][+/-ZZZZ]
 127  
      */
 128  32
     public CommonTS(String val) throws DataTypeException {
 129  32
         this.setValue(val);
 130  30
     } //end constructor
 131  
 
 132  
     /**
 133  
      * Returns the day as an integer.
 134  
      */
 135  
     public int getDay() {
 136  18
         int day = 0;
 137  18
         if (dt != null) {
 138  18
             day = dt.getDay();
 139  
         } //end if
 140  18
         return day;
 141  
     } //end method
 142  
 
 143  
     /**
 144  
      * Returns the fractional second value as a float.
 145  
      */
 146  
     public float getFractSecond() {
 147  1
         float fractionOfSec = 0;
 148  1
         if (tm != null) {
 149  1
             fractionOfSec = tm.getFractSecond();
 150  
         } //end if
 151  1
         return fractionOfSec;
 152  
     } //end method
 153  
 
 154  
     /**
 155  
      * Returns the GMT offset value as an integer.
 156  
      */
 157  
     public int getGMTOffset() {
 158  2
         int offSet = 0;
 159  2
         if (tm != null) {
 160  2
                 offSet = tm.getGMTOffset();
 161  
         } //end if
 162  2
         return offSet;
 163  
     } //end method
 164  
 
 165  
     /**
 166  
      * Returns the hour as an integer.
 167  
      */
 168  
     public int getHour() {
 169  1
         int hour = 0;
 170  1
         if (tm != null) {
 171  1
             hour = tm.getHour();
 172  
         } //end if
 173  1
         return hour;
 174  
     } //end method
 175  
 
 176  
     /**
 177  
      * Returns the minute as an integer.
 178  
      */
 179  
     public int getMinute() {
 180  1
         int minute = 0;
 181  1
         if (tm != null) {
 182  1
             minute = tm.getMinute();
 183  
         } //end if
 184  1
         return minute;
 185  
     } //end method
 186  
 
 187  
     /**
 188  
      * Returns the month as an integer.
 189  
      */
 190  
     public int getMonth() {
 191  18
         int month = 0;
 192  18
         if (dt != null) {
 193  18
             month = dt.getMonth();
 194  
         } //end if
 195  18
         return month;
 196  
     } //end method
 197  
 
 198  
     /**
 199  
      * Returns the second as an integer.
 200  
      */
 201  
     public int getSecond() {
 202  1
         int seconds = 0;
 203  1
         if (tm != null) {
 204  1
             seconds = tm.getSecond();
 205  
         } //end if
 206  1
         return seconds;
 207  
     } //end method
 208  
 
 209  
     /**
 210  
      * Returns the HL7 TS string value.
 211  
      */
 212  
     public String getValue() {
 213  370
         String value = null;
 214  370
         if (dt != null) {
 215  366
             value = dt.getValue();
 216  
         } //end if
 217  370
         if (tm != null && value != null && !value.equals("")) {
 218  355
             if (tm.getValue() != null && !tm.getValue().equals("")) {
 219  
                 //here we know we have a delete value or separate date and the time values supplied
 220  330
                 if (tm.getValue().equals("\"\"") && dt.getValue().equals("\"\"")) {
 221  
                     //set value to the delete value ("")
 222  1
                     value = "\"\"";
 223  
                 }
 224  
                 else{
 225  
                     //set value to date concatonated with time value
 226  329
                     value = value + tm.getValue();
 227  
                 }                
 228  
             } //end if
 229  355
             if (tm.getValue() == null || tm.getValue().equals("")) {
 230  
                 //here we know we both have the date and just the time offset value
 231  
                 //change the offset value from an integer to a signed string
 232  25
                 int offset = tm.getGMTOffset();
 233  25
                 String offsetStr = "";
 234  25
                 if (offset != CommonTM.GMT_OFFSET_NOT_SET_VALUE) {
 235  18
                     offsetStr = DataTypeUtil.preAppendZeroes(Math.abs(offset), 4);
 236  18
                     if (tm.getGMTOffset() >= 0) {
 237  12
                         offsetStr = "+" + offsetStr;
 238  
                     } //end if
 239  
                     else {
 240  6
                         offsetStr = "-" + offsetStr;
 241  
                     } //end else
 242  
                 }
 243  25
                 value = value + offsetStr;
 244  
             } //end if
 245  
         } //end if
 246  370
         return value;
 247  
     } //end method
 248  
     
 249  
     /**
 250  
      * Return the value as a calendar object. If the value is null (e.g. no value has
 251  
      * been set), returns null
 252  
      * 
 253  
      * @since 1.1 
 254  
      */
 255  
     public Calendar getValueAsCalendar() {
 256  18
             if (getValue() == null) {
 257  1
                     return null;
 258  
             }
 259  
             
 260  17
         Calendar retVal = tm.getValueAsCalendar();
 261  
 
 262  17
         retVal.set(Calendar.YEAR, getYear());
 263  17
         retVal.set(Calendar.MONTH, getMonth() - 1);
 264  17
         retVal.set(Calendar.DATE, getDay());
 265  
         
 266  17
         return retVal;
 267  
     }
 268  
 
 269  
     /**
 270  
      * Return the value as a date objectIf the value is null (e.g. no value has
 271  
      * been set), returns null
 272  
      * 
 273  
      * @since 1.1 
 274  
      */
 275  
     public Date getValueAsDate() {
 276  11
             if (getValue() == null) {
 277  1
                     return null;
 278  
             }
 279  
 
 280  10
             return getValueAsCalendar().getTime();
 281  
     }
 282  
     
 283  
     /**
 284  
      * Returns the year as an integer.
 285  
      */
 286  
     public int getYear() {
 287  18
         int year = 0;
 288  18
         if (dt != null) {
 289  18
             year = dt.getYear();
 290  
         } //end if
 291  18
         return year;
 292  
     } //end method
 293  
 
 294  
     
 295  
     /**
 296  
      * This method takes in integer values for the year, month, day, hour
 297  
      * and minute and performs validations, it then sets the value in the object
 298  
      * formatted as an HL7 Time Stamp value with year&month&day&hour&minute precision (YYYYMMDDHHMM).
 299  
      */
 300  
     public void setDateMinutePrecision(int yr, int mnth, int dy, int hr, int min) throws DataTypeException {
 301  
         try {
 302  
             //set the value of the date object to the input date value
 303  32
             this.setDatePrecision(yr, mnth, dy);
 304  
             //create new time object is there isn't one
 305  21
             if (tm == null) {
 306  21
                 tm = new CommonTM();
 307  
             }
 308  
             //set the value of the time object to the minute precision with the input values
 309  21
             tm.setHourMinutePrecision(hr, min);
 310  
         } //end try
 311  
 
 312  16
         catch (DataTypeException e) {
 313  16
             throw e;
 314  
         } //end catch
 315  
 
 316  0
         catch (Exception e) {
 317  0
             throw new DataTypeException(e);
 318  16
         } //end catch
 319  16
     } //end method
 320  
     
 321  
     
 322  
     /**
 323  
      * This method takes in integer values for the year and month and day
 324  
      * and performs validations, it then sets the value in the object
 325  
      * formatted as an HL7 Time Stamp value with year&month&day precision (YYYYMMDD).
 326  
      *
 327  
      */
 328  
     public void setDatePrecision(int yr, int mnth, int dy) throws DataTypeException {
 329  
         try {
 330  
             //create date object if there isn't one
 331  314
             if (dt == null) {
 332  314
                 dt = new CommonDT();
 333  
             }
 334  
             //set the value of the date object to the input date value
 335  314
             dt.setYearMonthDayPrecision(yr, mnth, dy);
 336  
             //clear the time value object
 337  282
             tm = null;
 338  
         } //end try
 339  
 
 340  32
         catch (DataTypeException e) {
 341  32
             throw e;
 342  
         } //end catch
 343  
 
 344  0
         catch (Exception e) {
 345  0
             throw new DataTypeException(e);
 346  282
         } //end catch
 347  282
     } //end method
 348  
 
 349  
     /**
 350  
      * This method takes in integer values for the year, month, day, hour, minute, seconds,
 351  
      * and fractional seconds (going to the tenthousandths precision).
 352  
      * The method performs validations and then sets the value in the object formatted as an
 353  
      * HL7 time value with a precision that starts from the year and goes down to the tenthousandths
 354  
      * of a second (YYYYMMDDHHMMSS.SSSS).
 355  
      * The Gmt Offset will not be effected.
 356  
      * Note: all of the precisions from tenths down to
 357  
      * tenthousandths of a second are optional. If the precision goes below tenthousandths
 358  
      * of a second then the second value will be rounded to the nearest tenthousandths of a second.
 359  
      */
 360  
     public void setDateSecondPrecision(int yr, int mnth, int dy, int hr, int min, float sec) throws DataTypeException {
 361  
         try {
 362  
             //set the value of the date object to the input date value
 363  261
             this.setDatePrecision(yr, mnth, dy);
 364  
             //create new time object is there isn't one
 365  251
             if (tm == null) {
 366  251
                 tm = new CommonTM();
 367  
             }
 368  
             //set the value of the time object to the second precision with the input values
 369  251
             tm.setHourMinSecondPrecision(hr, min, sec);
 370  
         } //end try
 371  
 
 372  19
         catch (DataTypeException e) {
 373  19
             throw e;
 374  
         } //end catch
 375  
 
 376  0
         catch (Exception e) {
 377  0
             throw new DataTypeException(e);
 378  242
         } //end catch
 379  242
     } //end method
 380  
 
 381  
     /**
 382  
      * This method takes in the four digit (signed) GMT offset and sets the offset
 383  
      * field
 384  
      */
 385  
     public void setOffset(int signedOffset) throws DataTypeException {
 386  
         try {
 387  
             //create new time object is there isn't one
 388  227
             if (tm == null) {
 389  0
                 tm = new CommonTM();
 390  
             }
 391  
             //set the offset value of the time object to the input value
 392  227
             tm.setOffset(signedOffset);
 393  
         }
 394  
 
 395  2
         catch (DataTypeException e) {
 396  2
             throw e;
 397  
         } //end catch
 398  
 
 399  0
         catch (Exception e) {
 400  0
             throw new DataTypeException(e);
 401  225
         } //end catch
 402  225
     } //end method
 403  
 
 404  
     /**
 405  
      * Convenience setter which sets the value using a {@link Calendar} object. Passing in <code>null</code> clears any existing value.
 406  
      * 
 407  
      * Note: Sets fields using precision up to the millisecond, including timezone offset
 408  
      * 
 409  
      * @param theCalendar The calendar object from which to retrieve values 
 410  
      * @since 1.1 
 411  
      */
 412  
     public void setValue(Calendar theCalendar) throws DataTypeException {
 413  9
                 if (theCalendar == null) {
 414  0
                         setValue((String)null);
 415  0
                         return;
 416  
                 }
 417  
 
 418  9
                 int yr = theCalendar.get(Calendar.YEAR);
 419  9
         int mnth = theCalendar.get(Calendar.MONTH) + 1;
 420  9
         int dy = theCalendar.get(Calendar.DATE);
 421  9
         int hr = theCalendar.get(Calendar.HOUR_OF_DAY);
 422  9
         int min = theCalendar.get(Calendar.MINUTE);
 423  9
         float sec = theCalendar.get(Calendar.SECOND) + (theCalendar.get(Calendar.MILLISECOND) / 1000.0F);
 424  9
         setDateSecondPrecision(yr, mnth, dy, hr, min, sec);
 425  
         
 426  
         // 3410095: care for integer overflow and timezones not at the full hour, e.g. India
 427  9
         int timeZoneOffset = theCalendar.get(Calendar.ZONE_OFFSET);
 428  9
         int hourOffset= timeZoneOffset / (1000 * 60 * 60);   
 429  9
         int minuteOffset = (timeZoneOffset / (1000 * 60)) % 60;
 430  9
         int zoneOffset = hourOffset * 100 + minuteOffset;
 431  9
         setOffset(zoneOffset);
 432  9
     }
 433  
 
 434  
     /**
 435  
      * Convenience setter which sets the value using a {@link Calendar} object. Passing in <code>null</code> clears any existing value.
 436  
      * 
 437  
      * Note: Sets fields using precision up to the millisecond, and sets the timezone offset to
 438  
      * the current system offset
 439  
      * 
 440  
      * @param theDate The calendar object from which to retrieve values 
 441  
      * @since 1.1 
 442  
      */
 443  
         public void setValue(Date theDate) throws DataTypeException {
 444  2
                 if (theDate == null) {
 445  0
                         setValue((String)null);
 446  0
                         return;
 447  
                 }
 448  
 
 449  2
                 GregorianCalendar cal = new GregorianCalendar();
 450  2
                 cal.setTime(theDate);
 451  2
                 setValue(cal);
 452  2
         }
 453  
 
 454  
     /**
 455  
      * This method takes in a string HL7 Time Stamp value and performs validations.
 456  
      * The stored value will be in the following
 457  
      * format YYYY[MM[DD[HHMM[SS[.S[S[S[S]]]]]]]][+/-ZZZZ].
 458  
      * Note: Trailing zeros supplied in the time value (HHMM[SS[.S[S[S[S]]]]]])
 459  
      * and GMT offset ([+/-ZZZZ]) will be preserved.
 460  
      * Note: If the GMT offset is not supplied then the local
 461  
      * time zone (using standard time zone format which is not modified for daylight savings)
 462  
      * will be stored as a default. Passing in <code>null</code> clears any existing value.
 463  
      */
 464  
     public void setValue(String val) throws DataTypeException {
 465  156
         if (val != null && !val.equals("") && !val.equals("\"\"")) {
 466  
             try {
 467  
                 //check the length of the input value, ensure that it is no less than
 468  
                 //8 characters in length
 469  144
                 if (val.length() < 4) {
 470  4
                     String msg = "The length of the TS datatype value must be at least 4 characters in length.";
 471  4
                     DataTypeException e = new DataTypeException(msg);
 472  4
                     throw e;
 473  
                 }
 474  
 
 475  
                 //check the length of the input value, ensure that it is not greater
 476  
                 //than 24 characters in length
 477  140
                 if (val.length() > 24) {
 478  0
                     String msg = "The length of the TS datatype value must not be more than 24 characters in length.";
 479  0
                     DataTypeException e = new DataTypeException(msg);
 480  0
                     throw e;
 481  
                 }
 482  
 
 483  
                 //at this point we know that we have a value that should conform to the DT
 484  
                 //datatype and possibly a value that should conform to the TM datatype
 485  140
                 String dateVal = null;
 486  140
                 String timeVal = null;
 487  140
                 String timeValLessOffset = null;
 488  140
                 int sp = val.indexOf("+");
 489  140
                 int sm = val.indexOf("-");
 490  140
                 int indexOfSign = -1;
 491  140
                 boolean offsetExists = false;
 492  140
                 boolean timeValIsOffsetOnly = false;
 493  140
                 if ((sp != -1) || (sm != -1)) {
 494  97
                     offsetExists = true;
 495  
                 }
 496  140
                 if (sp != -1)
 497  34
                     indexOfSign = sp;
 498  140
                 if (sm != -1)
 499  63
                     indexOfSign = sm;
 500  
 
 501  140
                 if (offsetExists == false) {
 502  43
                     if (val.length() <= 8) {
 503  12
                         dateVal = val;
 504  
                     }
 505  
                     else {
 506  
                         //here we know that a time value is present
 507  31
                         dateVal = val.substring(0, 8);
 508  31
                         timeVal = val.substring(8);
 509  31
                         timeValLessOffset = timeVal;
 510  
                     }
 511  
                 } //offset not exist
 512  
 
 513  140
                 if (offsetExists == true) {
 514  97
                     if (indexOfSign > 8) {
 515  60
                         dateVal = val.substring(0, 8);
 516  60
                         timeVal = val.substring(8);
 517  60
                         timeValLessOffset = val.substring(8, indexOfSign);
 518  
                     }
 519  
                     else {
 520  
                         //we know that the time val is simply the offset
 521  37
                         dateVal = val.substring(0, indexOfSign);
 522  37
                         timeVal = val.substring(indexOfSign);
 523  37
                         timeValIsOffsetOnly = true;
 524  
                     }
 525  
                 } //offset exists
 526  
 
 527  
                 //create date object
 528  140
                 dt = new CommonDT();
 529  
                 //set the value of the date object to the input date value
 530  140
                 dt.setValue(dateVal);
 531  
                 //if the offset does not exist and a timvalue does not exist then
 532  
                 //we must provide a default offset = to the local time zone
 533  132
                 if (timeVal == null && offsetExists == false) {
 534  
 //                    int defaultOffset = DataTypeUtil.getLocalGMTOffset();
 535  6
                     tm = new CommonTM();
 536  
                     //tm.setOffset(defaultOffset);
 537  6
                     tm.setValue("");
 538  
                 } //end if
 539  
 
 540  
                 //if we have a time value then make a new time object and set it to the
 541  
                 //input time value (as long as the time val has time + offset or just time only)
 542  132
                 if (timeVal != null && timeValIsOffsetOnly == false) {
 543  
                     // must make sure that the time component contains both hours 
 544  
                     // at the very least -- must be at least 2 chars in length.
 545  
                         // Note: this changed as of v2.5, before hours AND minutes were required.
 546  89
                     if (timeValLessOffset.length() < 2) {
 547  1
                         String msg =
 548  
                             "The length of the time component for the TM datatype"
 549  
                                 + " value does not conform to the allowable format"
 550  
                                 + " YYYY[MM[DD[HH[MM[SS[.S[S[S[S]]]]]]]]][+/-ZZZZ].";
 551  1
                         DataTypeException e = new DataTypeException(msg);
 552  1
                         throw e;
 553  
                     } //end if
 554  88
                     tm = new CommonTM();
 555  88
                     tm.setValue(timeVal);
 556  
                 } //end if
 557  
 
 558  
                 //if we have a time value and it only has the offset then make a new
 559  
                 //time object and set the offset value to the input value
 560  104
                 if (timeVal != null && timeValIsOffsetOnly == true) {
 561  
                     //we know that the time value is just the offset so we
 562  
                     //must check to see if it is the right length before setting the
 563  
                     //offset field in the tm object
 564  37
                     if (timeVal.length() != 5) {
 565  12
                         String msg =
 566  
                             "The length of the GMT offset for the TM datatype value does"
 567  
                                 + " not conform to the allowable format [+/-ZZZZ]";
 568  12
                         DataTypeException e = new DataTypeException(msg);
 569  12
                         throw e;
 570  
                     } //end if 
 571  25
                     tm = new CommonTM();
 572  
                     //first extract the + sign from the offset value string if it exists
 573  25
                     if (timeVal.indexOf("+") == 0) {
 574  13
                         timeVal = timeVal.substring(1);
 575  
                     } //end if
 576  25
                     int signedOffset = Integer.parseInt(timeVal);
 577  25
                     tm.setOffset(signedOffset);
 578  
                 } //end if
 579  
             } //end try
 580  
 
 581  58
             catch (DataTypeException e) {
 582  58
                 throw e;
 583  
             } //end catch
 584  
 
 585  0
             catch (Exception e) {
 586  0
                 throw new DataTypeException(e);
 587  86
             } //end catch
 588  
         } //end if
 589  
         else {
 590  
             //set the private value field to null or empty space.
 591  12
             if (val == null) {
 592  9
                 dt = null;
 593  9
                 tm = null;
 594  
             } //end if
 595  12
             if (val != null && val.equals("")) {
 596  1
                 dt = new CommonDT();
 597  1
                 dt.setValue("");
 598  1
                 tm = new CommonTM();
 599  1
                 tm.setValue("");
 600  
             } //end if
 601  12
             if (val != null && val.equals("\"\"")) {
 602  2
                 dt = new CommonDT();
 603  2
                 dt.setValue("\"\"");
 604  2
                 tm = new CommonTM();
 605  2
                 tm.setValue("\"\"");
 606  
             } //end if
 607  
         } //end else    
 608  
 
 609  98
     } // end method
 610  
 
 611  
     /**
 612  
      * Convenience setter which sets the value using a {@link Calendar} object. Passing in <code>null</code> clears any existing value.
 613  
      * 
 614  
      * Note: Sets fields using precision up to the minute
 615  
      * 
 616  
      * @param theCalendar The calendar object from which to retrieve values 
 617  
      * @since 1.1 
 618  
      */
 619  
     public void setValueToMinute(Calendar theCalendar) throws DataTypeException {
 620  4
                 if (theCalendar == null) {
 621  0
                         setValue((String)null);
 622  0
                         return;
 623  
                 }
 624  
 
 625  4
             int yr = theCalendar.get(Calendar.YEAR);
 626  4
         int mnth = theCalendar.get(Calendar.MONTH) + 1;
 627  4
         int dy = theCalendar.get(Calendar.DATE);
 628  4
         int hr = theCalendar.get(Calendar.HOUR_OF_DAY);
 629  4
         int min = theCalendar.get(Calendar.MINUTE);
 630  4
         setDateMinutePrecision(yr, mnth, dy, hr, min);
 631  
         
 632  4
     }
 633  
 
 634  
     /**
 635  
      * Convenience setter which sets the value using a {@link Date} object. Passing in <code>null</code> clears any existing value.
 636  
      * 
 637  
      * Note: Sets fields using precision up to the minute
 638  
      * 
 639  
      * @param theDate The date object from which to retrieve values
 640  
      * @since 1.1 
 641  
      */
 642  
     public void setValueToMinute(Date theDate) throws DataTypeException {
 643  2
                 if (theDate == null) {
 644  0
                         setValue((String)null);
 645  0
                         return;
 646  
                 }
 647  
 
 648  2
                 Calendar calendar = Calendar.getInstance();
 649  2
         calendar.setTime(theDate);
 650  2
         setValueToMinute(calendar);
 651  2
     }
 652  
 
 653  
     /**
 654  
      * Convenience setter which sets the value using a {@link Calendar} object. Passing in <code>null</code> clears any existing value.
 655  
      * 
 656  
      * Note: Sets fields using precision up to the second
 657  
      * 
 658  
      * @param theCalendar The calendar object from which to retrieve values 
 659  
      * @since 1.1 
 660  
      */
 661  
     public void setValueToSecond(Calendar theCalendar) throws DataTypeException {
 662  4
                 if (theCalendar == null) {
 663  0
                         setValue((String)null);
 664  0
                         return;
 665  
                 }
 666  
 
 667  4
         int yr = theCalendar.get(Calendar.YEAR);
 668  4
         int mnth = theCalendar.get(Calendar.MONTH) + 1;
 669  4
         int dy = theCalendar.get(Calendar.DATE);
 670  4
         int hr = theCalendar.get(Calendar.HOUR_OF_DAY);
 671  4
         int min = theCalendar.get(Calendar.MINUTE);
 672  4
         int sec = theCalendar.get(Calendar.SECOND);
 673  4
         setDateSecondPrecision(yr, mnth, dy, hr, min, sec);
 674  4
     }
 675  
 
 676  
     /**
 677  
      * Convenience setter which sets the value using a {@link Date} object. Passing in <code>null</code> clears any existing value.
 678  
      * 
 679  
      * Note: Sets fields using precision up to the second
 680  
      * 
 681  
      * @param theDate The date object from which to retrieve values
 682  
      * @since 1.1 
 683  
      */
 684  
     public void setValueToSecond(Date theDate) throws DataTypeException {
 685  2
                 if (theDate == null) {
 686  0
                         setValue((String)null);
 687  0
                         return;
 688  
                 }
 689  
 
 690  2
                 Calendar calendar = Calendar.getInstance();
 691  2
         calendar.setTime(theDate);
 692  2
         setValueToSecond(calendar);
 693  2
     }
 694  
 
 695  
     /**
 696  
      * Returns a string value representing the input Gregorian Calendar object in
 697  
      * an Hl7 TimeStamp Format.
 698  
      */
 699  
     public static String toHl7TSFormat(GregorianCalendar cal) throws DataTypeException {
 700  209
         String val = "";
 701  
         try {
 702  
             //set the input cal object so that it can report errors
 703  
             //on it's value
 704  209
             cal.setLenient(false);
 705  209
             int calYear = cal.get(GregorianCalendar.YEAR);
 706  209
             int calMonth = cal.get(GregorianCalendar.MONTH) + 1;
 707  209
             int calDay = cal.get(GregorianCalendar.DAY_OF_MONTH);
 708  209
             int calHour = cal.get(GregorianCalendar.HOUR_OF_DAY);
 709  209
             int calMin = cal.get(GregorianCalendar.MINUTE);
 710  209
             int calSec = cal.get(GregorianCalendar.SECOND);
 711  209
             int calMilli = cal.get(GregorianCalendar.MILLISECOND);
 712  
             //the inputs seconds and milli seconds should be combined into a float type
 713  209
             float fractSec = calMilli / 1000F;
 714  209
             float calSecFloat = calSec + fractSec;
 715  209
             int calOffset = cal.get(GregorianCalendar.ZONE_OFFSET) + cal.get(GregorianCalendar.DST_OFFSET);
 716  
             //Note the input's Offset value is in milliseconds, we must convert it to
 717  
             //a 4 digit integer in the HL7 Offset format.
 718  
             int offSetSignInt;
 719  209
             if (calOffset < 0) {
 720  207
                 offSetSignInt = -1;
 721  
             }
 722  
             else {
 723  2
                 offSetSignInt = 1;
 724  
             }
 725  
             //get the absolute value of the gmtOffSet
 726  209
             int absGmtOffSet = Math.abs(calOffset);
 727  209
             int gmtOffSetHours = absGmtOffSet / (3600 * 1000);
 728  209
             int gmtOffSetMin = (absGmtOffSet / 60000) % (60);
 729  
             //reset calOffset
 730  209
             calOffset = ((gmtOffSetHours * 100) + gmtOffSetMin) * offSetSignInt;
 731  
             //Create an object of the TS class and populate it with the above values
 732  
             //then return the HL7 string value from the object
 733  209
             CommonTS ts = new CommonTS();
 734  209
             ts.setDateSecondPrecision(calYear, calMonth, calDay, calHour, calMin, calSecFloat);
 735  209
             ts.setOffset(calOffset);
 736  209
             val = ts.getValue();
 737  
         } // end try
 738  
 
 739  0
         catch (DataTypeException e) {
 740  0
             throw e;
 741  
         } //end catch
 742  
 
 743  0
         catch (Exception e) {
 744  0
             throw new DataTypeException(e);
 745  209
         } //end catch
 746  209
         return val;
 747  
     } //end method
 748  
 
 749  
     
 750  
     public static void main(String[] args) throws DataTypeException {
 751  
             
 752  0
             CommonTS ts = new CommonTS();
 753  0
             ts.setValue("1984");
 754  
             
 755  0
             System.out.println(ts.getValue());
 756  
             
 757  0
     }
 758  
     
 759  
     
 760  
 } //end class