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 "CommonDT.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    
028    package ca.uhn.hl7v2.model.primitive;
029    import java.util.GregorianCalendar;
030    
031    import ca.uhn.hl7v2.model.DataTypeException;
032    import ca.uhn.hl7v2.model.DataTypeUtil;
033    import ca.uhn.log.HapiLog;
034    import ca.uhn.log.HapiLogFactory;
035    
036    /**
037     * This class contains functionality used by the DT class
038     * in the version 2.3.0, 2.3.1, and 2.4 packages
039     *
040     * Note: The class description below has been excerpted from the Hl7 2.4 documentation. Sectional
041     * references made below also refer to the same documentation.
042     *
043     * Format: YYYY[MM[DD]]
044     * In prior versions of HL7, this data type was always specified to be in the format YYYYMMDD. In the current and future
045     * versions, the precision of a date may be expressed by limiting the number of digits used with the format specification
046     * YYYY[MM[DD]]. Thus, YYYY is used to specify a precision of "year," YYYYMM specifies a precision of "month,"
047     * and YYYYMMDD specifies a precision of "day."
048     * By site-specific agreement, YYYYMMDD may be used where backward compatibility must be maintained.
049     * Examples:   |19880704|  |199503|
050     * @author Neal Acharya
051     */
052    
053    public class CommonDT {
054    
055        private static final HapiLog log = HapiLogFactory.getHapiLog(CommonDT.class);
056    
057        private String value;
058        private int year;
059        private int month;
060        private int day;
061    
062        /**
063         * Constructs a DT datatype with fields initialzed to zero and value initialized
064         * to null.
065         */
066        public CommonDT() {
067            //initialize all DT fields
068            value = null;
069            year = 0;
070            month = 0;
071            day = 0;
072        } //end constructor
073    
074        /**
075         * Constructs a DT object with the given value.
076         * The stored value will be in the following
077         * format YYYY[MM[DD]].
078         */
079        public CommonDT(String val) throws DataTypeException {
080            this.setValue(val);
081        } //end constructor
082    
083        /**
084         * This method takes in a string HL7 date value and performs validations
085         * then sets the value field. The stored value will be in the following
086         * format YYYY[MM[DD]].
087         *
088         */
089        public void setValue(String val) throws DataTypeException {
090    
091            if (val != null && !val.equals("") && !val.equals("\"\"")){
092                try {
093                    GregorianCalendar cal = new GregorianCalendar();
094                    cal.clear();
095                    cal.setLenient(false);
096    
097                    //check the length, must be either four, six, or eight digits
098                    if ((val.length() != 4) && (val.length() != 6) && (val.length() != 8)) {
099                        String msg =
100                            "The length of the DT datatype value does not conform to an allowable"
101                                + " format. Format should conform to YYYY[MM[DD]]";
102                        DataTypeException e = new DataTypeException(msg);
103                        throw e;
104                    }
105    
106                    if (val.length() >= 4) {
107                        //extract the year from the input value
108                        int yrInt = Integer.parseInt(val.substring(0, 4));
109                        //check to see if the year is valid by creating a Gregorian calendar object with
110                        //this value.  If an error occurs then processing will stop in this try block
111                        cal.set(yrInt, 0, 1);
112                        cal.getTime(); //for error detection
113                        year = yrInt;
114                    }
115    
116                    if (val.length() >= 6) {
117                        //extract the month from the input value
118                        int mnthInt = Integer.parseInt(val.substring(4, 6));
119                        //check to see if the month is valid by creating a Gregorian calendar object with
120                        //this value.  If an error occurs then processing will stop in this try block
121                        cal.set(year, mnthInt - 1, 1);
122                        cal.getTime(); //for error detection
123                        month = mnthInt;
124    
125                    }
126    
127                    if (val.length() == 8) {
128                        //extract the day from the input value
129                        int dayInt = Integer.parseInt(val.substring(6, 8));
130                        //check to see if the day is valid by creating a Gregorian calendar object with
131                        //the year/month/day combination.  If an error occurs then processing will stop
132                        // in this try block
133                        cal.set(year, month - 1, dayInt);
134                        cal.getTime(); //for error detection
135                        day = dayInt;
136                    }
137                    //validations are complete now store the input value into the private value field
138                    value = val;
139                } //end try
140    
141                catch (DataTypeException e) {
142                    throw e;
143                } //end catch
144    
145                catch (Exception e) {
146                    throw new DataTypeException( e );
147                } //end catch
148            } //end if
149            else {
150                //set the private value field to null or empty space.
151                value = val;
152            } //end else       
153    
154        } //end method
155    
156        /**
157         * This method takes in an integer value for the year and performs validations,
158         * it then sets the value field formatted as an HL7 date.
159         * value with year precision (YYYY)
160         */
161        public void setYearPrecision(int yr) throws DataTypeException {
162            try {
163                GregorianCalendar cal = new GregorianCalendar();
164                cal.clear();
165                cal.setLenient(false);
166    
167                //ensure that the year field is four digits long
168                if (Integer.toString(yr).length() != 4) {
169                    String msg = "The input year value must be four digits long";
170                    DataTypeException e = new DataTypeException(msg);
171                    throw e;
172                }
173                //check is input year is valid
174                //GregorianCalendar cal = new GregorianCalendar(yr,0,1);
175                cal.set(yr, 0, 1);
176                cal.getTime(); //for error detection
177                year = yr;
178                month = 0;
179                day = 0;
180                value = Integer.toString(yr);
181            } //end try
182    
183            catch (DataTypeException e) {
184                throw e;
185            } //end catch
186    
187            catch (Exception e) {
188                throw new DataTypeException( e );
189            } //end catch
190    
191        } //end method
192    
193        /**
194         * This method takes in integer values for the year and month and performs validations,
195         * it then sets the value field formatted as an HL7 date
196         * value with year&month precision (YYYYMM).
197         * Note: The first month = 1 = January.
198         */
199        public void setYearMonthPrecision(int yr, int mnth) throws DataTypeException {
200            try {
201                GregorianCalendar cal = new GregorianCalendar();
202                cal.clear();
203                cal.setLenient(false);
204                //ensure that the year field is four digits long
205                if (Integer.toString(yr).length() != 4) {
206                    String msg = "The input year value must be four digits long";
207                    DataTypeException e = new DataTypeException(msg);
208                    throw e;
209                }
210                //validate the input month
211                //GregorianCalendar cal = new GregorianCalendar(yr,(mnth-1),1);
212                cal.set(yr, (mnth - 1), 1);
213                cal.getTime(); //for error detection
214                year = yr;
215                month = mnth;
216                day = 0;
217                value = Integer.toString(yr) + DataTypeUtil.preAppendZeroes(mnth, 2);
218            }
219    
220            catch (DataTypeException e) {
221                throw e;
222            } //end catch
223    
224            catch (Exception e) {
225                throw new DataTypeException( e );
226            } //end catch
227        } //end method
228    
229        /**
230         * This method takes in integer values for the year and month and day
231         * and performs validations, it then sets the value in the object
232         * formatted as an HL7 date value with year&month&day precision (YYYYMMDD).
233         */
234        public void setYearMonthDayPrecision(int yr, int mnth, int dy) throws DataTypeException {
235            try {
236                GregorianCalendar cal = new GregorianCalendar();
237                cal.clear();
238                cal.setLenient(false);
239    
240                //ensure that the year field is four digits long
241                if (Integer.toString(yr).length() != 4) {
242                    String msg = "The input year value must be four digits long";
243                    DataTypeException e = new DataTypeException(msg);
244                    throw e;
245                }
246                //validate the input month/day combination
247                cal.set(yr, (mnth - 1), dy);
248                cal.getTime(); //for error detection
249                year = yr;
250                month = mnth;
251                day = dy;
252                value = Integer.toString(yr) + DataTypeUtil.preAppendZeroes(mnth, 2) + DataTypeUtil.preAppendZeroes(dy, 2);
253            }
254    
255            catch (DataTypeException e) {
256                throw e;
257            } //end catch
258    
259            catch (Exception e) {
260                throw new DataTypeException( e );
261            } //end catch
262    
263        } //end method
264    
265        /**
266         * Returns the HL7 DT string value.
267         */
268        public String getValue() {
269            return value;
270        } //end method
271    
272        /**
273         * Returns the year as an integer.
274         */
275        public int getYear() {
276            return year;
277        } //end method
278    
279        /**
280         * Returns the month as an integer.
281         */
282        public int getMonth() {
283            return month;
284        } //end method
285    
286        /**
287         * Returns the day as an integer.
288         */
289        public int getDay() {
290            return day;
291        } //end method
292    
293        /**
294         * Returns a string value representing the input Gregorian Calendar object in
295         * an Hl7 Date Format.
296         */
297        public static String toHl7DTFormat(GregorianCalendar cal) throws DataTypeException {
298            String val = "";
299            try {
300                //set the input cal object so that it can report errors
301                //on it's value
302                cal.setLenient(false);
303                int calYear = cal.get(GregorianCalendar.YEAR);
304                int calMonth = cal.get(GregorianCalendar.MONTH) + 1;
305                int calDay = cal.get(GregorianCalendar.DAY_OF_MONTH);
306                CommonDT dt = new CommonDT();
307                dt.setYearMonthDayPrecision(calYear, calMonth, calDay);
308                val = dt.getValue();
309            } //end try
310    
311            catch (DataTypeException e) {
312                throw e;
313            } //end catch
314    
315            catch (Exception e) {
316                throw new DataTypeException( e );
317            } //end catch
318            return val;
319        } //end method
320    
321    } //end class