001package org.hl7.fhir.dstu3.model;
002
003/*
004  Copyright (c) 2011+, HL7, Inc.
005  All rights reserved.
006  
007  Redistribution and use in source and binary forms, with or without modification, 
008  are permitted provided that the following conditions are met:
009    
010   * Redistributions of source code must retain the above copyright notice, this 
011     list of conditions and the following disclaimer.
012   * Redistributions in binary form must reproduce the above copyright notice, 
013     this list of conditions and the following disclaimer in the documentation 
014     and/or other materials provided with the distribution.
015   * Neither the name of HL7 nor the names of its contributors may be used to 
016     endorse or promote products derived from this software without specific 
017     prior written permission.
018  
019  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
020  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
021  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
022  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
023  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
024  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
025  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
026  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
027  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
028  POSSIBILITY OF SUCH DAMAGE.
029  
030 */
031
032
033
034import java.util.Calendar;
035
036/**
037 * Primitive type "date" in FHIR: any day in a gregorian calendar
038 */
039
040import java.util.Date;
041import java.util.GregorianCalendar;
042import java.util.TimeZone;
043
044import org.apache.commons.lang3.Validate;
045
046import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
047import ca.uhn.fhir.model.api.annotation.DatatypeDef;
048
049/**
050 * Represents a FHIR date datatype. Valid precisions values for this type are:
051 * <ul>
052 * <li>{@link ca.uhn.fhir.model.api.TemporalPrecisionEnum#YEAR}
053 * <li>{@link ca.uhn.fhir.model.api.TemporalPrecisionEnum#MONTH}
054 * <li>{@link ca.uhn.fhir.model.api.TemporalPrecisionEnum#DAY}
055 * </ul>
056 */
057@DatatypeDef(name = "date")
058public class DateType extends BaseDateTimeType {
059
060        private static final long serialVersionUID = 3L;
061        
062        /**
063         * The default precision for this type
064         */
065        public static final TemporalPrecisionEnum DEFAULT_PRECISION = TemporalPrecisionEnum.DAY;
066
067        /**
068         * Constructor
069         */
070        public DateType() {
071                super();
072        }
073
074        /**
075         * Constructor which accepts a date value and uses the {@link #DEFAULT_PRECISION} for this type
076         */
077        public DateType(Date theDate) {
078                super(theDate, DEFAULT_PRECISION);
079        }
080
081        /**
082         * Constructor which accepts a date value and a precision value. Valid precisions values for this type are:
083         * <ul>
084         * <li>{@link ca.uhn.fhir.model.api.TemporalPrecisionEnum#YEAR}
085         * <li>{@link ca.uhn.fhir.model.api.TemporalPrecisionEnum#MONTH}
086         * <li>{@link ca.uhn.fhir.model.api.TemporalPrecisionEnum#DAY}
087         * </ul>
088         *
089         * @throws ca.uhn.fhir.parser.DataFormatException
090         *             If the specified precision is not allowed for this type
091         */
092        public DateType(Date theDate, TemporalPrecisionEnum thePrecision) {
093                super(theDate, thePrecision);
094        }
095
096        /**
097         * Constructor which accepts a date as a string in FHIR format
098         *
099         * @throws ca.uhn.fhir.parser.DataFormatException
100         *             If the precision in the date string is not allowed for this type
101         */
102        public DateType(String theDate) {
103                super(theDate);
104        }
105
106        /**
107         * Constructor which accepts a date value and uses the {@link #DEFAULT_PRECISION} for this type.
108         */
109        public DateType(Calendar theCalendar) {
110                super(theCalendar.getTime(), DEFAULT_PRECISION);
111                setTimeZone(theCalendar.getTimeZone());
112        }
113
114        /**
115         * Constructor which accepts a date value and uses the {@link #DEFAULT_PRECISION} for this type.
116         * <p>
117         * <b>Use caution when using this constructor</b>: The month is 0-indexed but the day is 1-indexed 
118         * in order to match the bahaviour of the Java {@link Calendar} type.
119         * </p>
120         * 
121         * @param theYear The year, e.g. 2015
122         * @param theMonth The month, e.g. 0 for January
123         * @param theDay The day (1 indexed) e.g. 1 for the first day of the month
124         */
125        public DateType(int theYear, int theMonth, int theDay) {
126                this(toCalendarZulu(theYear, theMonth, theDay));
127        }
128
129        private static GregorianCalendar toCalendarZulu(int theYear, int theMonth, int theDay) {
130                Validate.isTrue(theMonth >= 0, "theMonth must be between 0 and 11");
131                Validate.isTrue(theMonth <= 11, "theMonth must be between 0 and 11");
132                Validate.isTrue(theDay >= 1, "theDay must be between 1 and 31");
133                Validate.isTrue(theDay <= 31, "theDay must be between 1 and 31");
134                
135                GregorianCalendar retVal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
136                retVal.set(Calendar.YEAR, theYear);
137                retVal.set(Calendar.MONTH, theMonth);
138                retVal.set(Calendar.DATE, theDay);
139                return retVal;
140        }
141
142        @Override
143        boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision) {
144                switch (thePrecision) {
145                        case YEAR:
146                        case MONTH:
147                        case DAY:
148                                return true;
149                        default:
150                                return false;
151                }
152        }
153
154        /**
155         * Returns the default precision for this datatype
156         *
157         * @see #DEFAULT_PRECISION
158         */
159        @Override
160        protected TemporalPrecisionEnum getDefaultPrecisionForDatatype() {
161                return DEFAULT_PRECISION;
162        }
163
164        @Override
165        public DateType copy() {
166                return new DateType(getValueAsString());
167        }
168        
169        public static InstantType today() {
170                return new InstantType(new Date(), TemporalPrecisionEnum.DAY, TimeZone.getDefault());
171        }
172
173        /**
174         * Creates a new instance by parsing an HL7 v3 format date time string
175         */
176        public static DateType parseV3(String theV3String) {
177                DateType retVal = new DateType();
178                retVal.setValueAsV3String(theV3String);
179                return retVal;
180        }
181
182        @Override
183        public String fhirType() {
184                return "date";          
185        }
186}