001package org.hl7.fhir.r4.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
032import java.util.Calendar;
033import java.util.Date;
034import java.util.TimeZone;
035import java.util.zip.DataFormatException;
036
037import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
038import ca.uhn.fhir.model.api.annotation.DatatypeDef;
039
040/**
041 * Represents a FHIR instant datatype. Valid precisions values for this type
042 * are:
043 * <ul>
044 * <li>{@link TemporalPrecisionEnum#SECOND}
045 * <li>{@link TemporalPrecisionEnum#MILLI}
046 * </ul>
047 */
048@DatatypeDef(name = "instant")
049public class InstantType extends BaseDateTimeType {
050
051  private static final long serialVersionUID = 3L;
052
053  /**
054   * The default precision for this type
055   */
056  public static final TemporalPrecisionEnum DEFAULT_PRECISION = TemporalPrecisionEnum.MILLI;
057
058  /**
059   * Constructor which creates an InstantDt with <b>no timne value</b>. Note that
060   * unlike the default constructor for the Java {@link Date} or {@link Calendar}
061   * objects, this constructor does not initialize the object with the current
062   * time.
063   * 
064   * @see #withCurrentTime() to create a new object that has been initialized with
065   *      the current time.
066   */
067  public InstantType() {
068    super();
069  }
070
071  /**
072   * Create a new DateTimeDt
073   */
074  public InstantType(Calendar theCalendar) {
075    super(theCalendar.getTime(), DEFAULT_PRECISION, theCalendar.getTimeZone());
076  }
077
078  /**
079   * Create a new instance using the given date, precision level, and time zone
080   * 
081   * @throws DataFormatException If the specified precision is not allowed for
082   *                             this type
083   */
084  public InstantType(Date theDate, TemporalPrecisionEnum thePrecision, TimeZone theTimezone) {
085    super(theDate, thePrecision, theTimezone);
086  }
087
088  /**
089   * Create a new DateTimeDt using an existing value. <b>Use this constructor with
090   * caution</b>, as it may create more precision than warranted (since for
091   * example it is possible to pass in a DateTime with only a year, and this
092   * constructor will convert to an InstantDt with milliseconds precision).
093   */
094  public InstantType(BaseDateTimeType theDateTime) {
095    // Do not call super(foo) here, we don't want to trigger a DataFormatException
096    setValue(theDateTime.getValue());
097    setPrecision(DEFAULT_PRECISION);
098    setTimeZone(theDateTime.getTimeZone());
099  }
100
101  /**
102   * Create a new DateTimeDt with the given date/time and
103   * {@link TemporalPrecisionEnum#MILLI} precision
104   */
105  public InstantType(Date theDate) {
106    super(theDate, DEFAULT_PRECISION, TimeZone.getDefault());
107  }
108
109  /**
110   * Constructor which accepts a date value and a precision value. Valid
111   * precisions values for this type are:
112   * <ul>
113   * <li>{@link TemporalPrecisionEnum#SECOND}
114   * <li>{@link TemporalPrecisionEnum#MILLI}
115   * </ul>
116   */
117  public InstantType(Date theDate, TemporalPrecisionEnum thePrecision) {
118    setValue(theDate);
119    setPrecision(thePrecision);
120    setTimeZone(TimeZone.getDefault());
121  }
122
123  /**
124   * Create a new InstantDt from a string value
125   * 
126   * @param theString The string representation of the string. Must be in a valid
127   *                  format according to the FHIR specification
128   * @throws DataFormatException
129   */
130  public InstantType(String theString) {
131    super(theString);
132  }
133
134  /**
135   * Invokes {@link Date#after(Date)} on the contained Date against the given date
136   * 
137   * @throws NullPointerException If the {@link #getValue() contained Date} is
138   *                              null
139   */
140  public boolean after(Date theDate) {
141    return getValue().after(theDate);
142  }
143
144  /**
145   * Invokes {@link Date#before(Date)} on the contained Date against the given
146   * date
147   * 
148   * @throws NullPointerException If the {@link #getValue() contained Date} is
149   *                              null
150   */
151  public boolean before(Date theDate) {
152    return getValue().before(theDate);
153  }
154
155  /**
156   * Sets the value of this instant to the current time (from the system clock)
157   * and the local/default timezone (as retrieved using
158   * {@link TimeZone#getDefault()}. This TimeZone is generally obtained from the
159   * underlying OS.
160   */
161  public void setToCurrentTimeInLocalTimeZone() {
162    setValue(new Date());
163    setTimeZone(TimeZone.getDefault());
164  }
165
166  @Override
167  boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision) {
168    switch (thePrecision) {
169    case SECOND:
170    case MILLI:
171      return true;
172    default:
173      return false;
174    }
175  }
176
177  /**
178   * Factory method which creates a new InstantDt with millisecond precision and
179   * initializes it with the current time and the system local timezone.
180   */
181  public static InstantType withCurrentTime() {
182    return new InstantType(new Date(), TemporalPrecisionEnum.MILLI, TimeZone.getDefault());
183  }
184
185  /**
186   * Returns the default precision for this datatype
187   * 
188   * @see #DEFAULT_PRECISION
189   */
190  @Override
191  protected TemporalPrecisionEnum getDefaultPrecisionForDatatype() {
192    return DEFAULT_PRECISION;
193  }
194
195  @Override
196  public InstantType copy() {
197    InstantType ret = new InstantType();
198    ret.setValueAsString(getValueAsString());
199    copyValues(ret);
200    return ret;
201  }
202
203  /**
204   * Returns a new instance of DateTimeType with the current system time and MILLI
205   * precision and the system local time zone
206   */
207  public static InstantType now() {
208    return new InstantType(new Date(), TemporalPrecisionEnum.MILLI, TimeZone.getDefault());
209  }
210
211  /**
212   * Creates a new instance by parsing an HL7 v3 format date time string
213   */
214  public static InstantType parseV3(String theV3String) {
215    InstantType retVal = new InstantType();
216    retVal.setValueAsV3String(theV3String);
217    return retVal;
218  }
219
220  public String fhirType() {
221    return "instant";
222  }
223}