View Javadoc

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     public CommonTS() {
121     } //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     public CommonTS(String val) throws DataTypeException {
129         this.setValue(val);
130     } //end constructor
131 
132     /**
133      * Returns the day as an integer.
134      */
135     public int getDay() {
136         int day = 0;
137         if (dt != null) {
138             day = dt.getDay();
139         } //end if
140         return day;
141     } //end method
142 
143     /**
144      * Returns the fractional second value as a float.
145      */
146     public float getFractSecond() {
147         float fractionOfSec = 0;
148         if (tm != null) {
149             fractionOfSec = tm.getFractSecond();
150         } //end if
151         return fractionOfSec;
152     } //end method
153 
154     /**
155      * Returns the GMT offset value as an integer.
156      */
157     public int getGMTOffset() {
158         int offSet = 0;
159         if (tm != null) {
160         	offSet = tm.getGMTOffset();
161         } //end if
162         return offSet;
163     } //end method
164 
165     /**
166      * Returns the hour as an integer.
167      */
168     public int getHour() {
169         int hour = 0;
170         if (tm != null) {
171             hour = tm.getHour();
172         } //end if
173         return hour;
174     } //end method
175 
176     /**
177      * Returns the minute as an integer.
178      */
179     public int getMinute() {
180         int minute = 0;
181         if (tm != null) {
182             minute = tm.getMinute();
183         } //end if
184         return minute;
185     } //end method
186 
187     /**
188      * Returns the month as an integer.
189      */
190     public int getMonth() {
191         int month = 0;
192         if (dt != null) {
193             month = dt.getMonth();
194         } //end if
195         return month;
196     } //end method
197 
198     /**
199      * Returns the second as an integer.
200      */
201     public int getSecond() {
202         int seconds = 0;
203         if (tm != null) {
204             seconds = tm.getSecond();
205         } //end if
206         return seconds;
207     } //end method
208 
209     /**
210      * Returns the HL7 TS string value.
211      */
212     public String getValue() {
213         String value = null;
214         if (dt != null) {
215             value = dt.getValue();
216         } //end if
217         if (tm != null && value != null && !value.equals("")) {
218             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                 if (tm.getValue().equals("\"\"") && dt.getValue().equals("\"\"")) {
221                     //set value to the delete value ("")
222                     value = "\"\"";
223                 }
224                 else{
225                     //set value to date concatonated with time value
226                     value = value + tm.getValue();
227                 }                
228             } //end if
229             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                 int offset = tm.getGMTOffset();
233                 String offsetStr = "";
234                 if (offset != CommonTM.GMT_OFFSET_NOT_SET_VALUE) {
235                     offsetStr = DataTypeUtil.preAppendZeroes(Math.abs(offset), 4);
236                     if (tm.getGMTOffset() >= 0) {
237                         offsetStr = "+" + offsetStr;
238                     } //end if
239                     else {
240                         offsetStr = "-" + offsetStr;
241                     } //end else
242                 }
243                 value = value + offsetStr;
244             } //end if
245         } //end if
246         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     	if (getValue() == null) {
257     		return null;
258     	}
259     	
260         Calendar retVal = tm.getValueAsCalendar();
261 
262         retVal.set(Calendar.YEAR, getYear());
263         retVal.set(Calendar.MONTH, getMonth() - 1);
264         retVal.set(Calendar.DATE, getDay());
265         
266         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     	if (getValue() == null) {
277     		return null;
278     	}
279 
280     	return getValueAsCalendar().getTime();
281     }
282     
283     /**
284      * Returns the year as an integer.
285      */
286     public int getYear() {
287         int year = 0;
288         if (dt != null) {
289             year = dt.getYear();
290         } //end if
291         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             this.setDatePrecision(yr, mnth, dy);
304             //create new time object is there isn't one
305             if (tm == null) {
306                 tm = new CommonTM();
307             }
308             //set the value of the time object to the minute precision with the input values
309             tm.setHourMinutePrecision(hr, min);
310         } //end try
311 
312         catch (DataTypeException e) {
313             throw e;
314         } //end catch
315 
316         catch (Exception e) {
317             throw new DataTypeException(e);
318         } //end catch
319     } //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             if (dt == null) {
332                 dt = new CommonDT();
333             }
334             //set the value of the date object to the input date value
335             dt.setYearMonthDayPrecision(yr, mnth, dy);
336             //clear the time value object
337             tm = null;
338         } //end try
339 
340         catch (DataTypeException e) {
341             throw e;
342         } //end catch
343 
344         catch (Exception e) {
345             throw new DataTypeException(e);
346         } //end catch
347     } //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             this.setDatePrecision(yr, mnth, dy);
364             //create new time object is there isn't one
365             if (tm == null) {
366                 tm = new CommonTM();
367             }
368             //set the value of the time object to the second precision with the input values
369             tm.setHourMinSecondPrecision(hr, min, sec);
370         } //end try
371 
372         catch (DataTypeException e) {
373             throw e;
374         } //end catch
375 
376         catch (Exception e) {
377             throw new DataTypeException(e);
378         } //end catch
379     } //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             if (tm == null) {
389                 tm = new CommonTM();
390             }
391             //set the offset value of the time object to the input value
392             tm.setOffset(signedOffset);
393         }
394 
395         catch (DataTypeException e) {
396             throw e;
397         } //end catch
398 
399         catch (Exception e) {
400             throw new DataTypeException(e);
401         } //end catch
402     } //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 		if (theCalendar == null) {
414 			setValue((String)null);
415 			return;
416 		}
417 
418 		int yr = theCalendar.get(Calendar.YEAR);
419         int mnth = theCalendar.get(Calendar.MONTH) + 1;
420         int dy = theCalendar.get(Calendar.DATE);
421         int hr = theCalendar.get(Calendar.HOUR_OF_DAY);
422         int min = theCalendar.get(Calendar.MINUTE);
423         float sec = theCalendar.get(Calendar.SECOND) + (theCalendar.get(Calendar.MILLISECOND) / 1000.0F);
424         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         int timeZoneOffset = theCalendar.get(Calendar.ZONE_OFFSET);
428         int hourOffset= timeZoneOffset / (1000 * 60 * 60);   
429         int minuteOffset = (timeZoneOffset / (1000 * 60)) % 60;
430         int zoneOffset = hourOffset * 100 + minuteOffset;
431         setOffset(zoneOffset);
432     }
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 		if (theDate == null) {
445 			setValue((String)null);
446 			return;
447 		}
448 
449 		GregorianCalendar cal = new GregorianCalendar();
450 		cal.setTime(theDate);
451 		setValue(cal);
452 	}
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         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                 if (val.length() < 4) {
470                     String msg = "The length of the TS datatype value must be at least 4 characters in length.";
471                     DataTypeException e = new DataTypeException(msg);
472                     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                 if (val.length() > 24) {
478                     String msg = "The length of the TS datatype value must not be more than 24 characters in length.";
479                     DataTypeException e = new DataTypeException(msg);
480                     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                 String dateVal = null;
486                 String timeVal = null;
487                 String timeValLessOffset = null;
488                 int sp = val.indexOf("+");
489                 int sm = val.indexOf("-");
490                 int indexOfSign = -1;
491                 boolean offsetExists = false;
492                 boolean timeValIsOffsetOnly = false;
493                 if ((sp != -1) || (sm != -1)) {
494                     offsetExists = true;
495                 }
496                 if (sp != -1)
497                     indexOfSign = sp;
498                 if (sm != -1)
499                     indexOfSign = sm;
500 
501                 if (offsetExists == false) {
502                     if (val.length() <= 8) {
503                         dateVal = val;
504                     }
505                     else {
506                         //here we know that a time value is present
507                         dateVal = val.substring(0, 8);
508                         timeVal = val.substring(8);
509                         timeValLessOffset = timeVal;
510                     }
511                 } //offset not exist
512 
513                 if (offsetExists == true) {
514                     if (indexOfSign > 8) {
515                         dateVal = val.substring(0, 8);
516                         timeVal = val.substring(8);
517                         timeValLessOffset = val.substring(8, indexOfSign);
518                     }
519                     else {
520                         //we know that the time val is simply the offset
521                         dateVal = val.substring(0, indexOfSign);
522                         timeVal = val.substring(indexOfSign);
523                         timeValIsOffsetOnly = true;
524                     }
525                 } //offset exists
526 
527                 //create date object
528                 dt = new CommonDT();
529                 //set the value of the date object to the input date value
530                 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                 if (timeVal == null && offsetExists == false) {
534 //                    int defaultOffset = DataTypeUtil.getLocalGMTOffset();
535                     tm = new CommonTM();
536                     //tm.setOffset(defaultOffset);
537                     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                 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                     if (timeValLessOffset.length() < 2) {
547                         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                         DataTypeException e = new DataTypeException(msg);
552                         throw e;
553                     } //end if
554                     tm = new CommonTM();
555                     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                 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                     if (timeVal.length() != 5) {
565                         String msg =
566                             "The length of the GMT offset for the TM datatype value does"
567                                 + " not conform to the allowable format [+/-ZZZZ]";
568                         DataTypeException e = new DataTypeException(msg);
569                         throw e;
570                     } //end if 
571                     tm = new CommonTM();
572                     //first extract the + sign from the offset value string if it exists
573                     if (timeVal.indexOf("+") == 0) {
574                         timeVal = timeVal.substring(1);
575                     } //end if
576                     int signedOffset = Integer.parseInt(timeVal);
577                     tm.setOffset(signedOffset);
578                 } //end if
579             } //end try
580 
581             catch (DataTypeException e) {
582                 throw e;
583             } //end catch
584 
585             catch (Exception e) {
586                 throw new DataTypeException(e);
587             } //end catch
588         } //end if
589         else {
590             //set the private value field to null or empty space.
591             if (val == null) {
592                 dt = null;
593                 tm = null;
594             } //end if
595             if (val != null && val.equals("")) {
596                 dt = new CommonDT();
597                 dt.setValue("");
598                 tm = new CommonTM();
599                 tm.setValue("");
600             } //end if
601             if (val != null && val.equals("\"\"")) {
602                 dt = new CommonDT();
603                 dt.setValue("\"\"");
604                 tm = new CommonTM();
605                 tm.setValue("\"\"");
606             } //end if
607         } //end else    
608 
609     } // 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 		if (theCalendar == null) {
621 			setValue((String)null);
622 			return;
623 		}
624 
625     	int yr = theCalendar.get(Calendar.YEAR);
626         int mnth = theCalendar.get(Calendar.MONTH) + 1;
627         int dy = theCalendar.get(Calendar.DATE);
628         int hr = theCalendar.get(Calendar.HOUR_OF_DAY);
629         int min = theCalendar.get(Calendar.MINUTE);
630         setDateMinutePrecision(yr, mnth, dy, hr, min);
631         
632     }
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 		if (theDate == null) {
644 			setValue((String)null);
645 			return;
646 		}
647 
648 		Calendar calendar = Calendar.getInstance();
649         calendar.setTime(theDate);
650         setValueToMinute(calendar);
651     }
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 		if (theCalendar == null) {
663 			setValue((String)null);
664 			return;
665 		}
666 
667         int yr = theCalendar.get(Calendar.YEAR);
668         int mnth = theCalendar.get(Calendar.MONTH) + 1;
669         int dy = theCalendar.get(Calendar.DATE);
670         int hr = theCalendar.get(Calendar.HOUR_OF_DAY);
671         int min = theCalendar.get(Calendar.MINUTE);
672         int sec = theCalendar.get(Calendar.SECOND);
673         setDateSecondPrecision(yr, mnth, dy, hr, min, sec);
674     }
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 		if (theDate == null) {
686 			setValue((String)null);
687 			return;
688 		}
689 
690 		Calendar calendar = Calendar.getInstance();
691         calendar.setTime(theDate);
692         setValueToSecond(calendar);
693     }
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         String val = "";
701         try {
702             //set the input cal object so that it can report errors
703             //on it's value
704             cal.setLenient(false);
705             int calYear = cal.get(GregorianCalendar.YEAR);
706             int calMonth = cal.get(GregorianCalendar.MONTH) + 1;
707             int calDay = cal.get(GregorianCalendar.DAY_OF_MONTH);
708             int calHour = cal.get(GregorianCalendar.HOUR_OF_DAY);
709             int calMin = cal.get(GregorianCalendar.MINUTE);
710             int calSec = cal.get(GregorianCalendar.SECOND);
711             int calMilli = cal.get(GregorianCalendar.MILLISECOND);
712             //the inputs seconds and milli seconds should be combined into a float type
713             float fractSec = calMilli / 1000F;
714             float calSecFloat = calSec + fractSec;
715             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             if (calOffset < 0) {
720                 offSetSignInt = -1;
721             }
722             else {
723                 offSetSignInt = 1;
724             }
725             //get the absolute value of the gmtOffSet
726             int absGmtOffSet = Math.abs(calOffset);
727             int gmtOffSetHours = absGmtOffSet / (3600 * 1000);
728             int gmtOffSetMin = (absGmtOffSet / 60000) % (60);
729             //reset calOffset
730             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             CommonTS ts = new CommonTS();
734             ts.setDateSecondPrecision(calYear, calMonth, calDay, calHour, calMin, calSecFloat);
735             ts.setOffset(calOffset);
736             val = ts.getValue();
737         } // end try
738 
739         catch (DataTypeException e) {
740             throw e;
741         } //end catch
742 
743         catch (Exception e) {
744             throw new DataTypeException(e);
745         } //end catch
746         return val;
747     } //end method
748 
749     
750     public static void main(String[] args) throws DataTypeException {
751     	
752     	CommonTS ts = new CommonTS();
753     	ts.setValue("1984");
754     	
755     	System.out.println(ts.getValue());
756     	
757     }
758     
759     
760 } //end class