001/*
002Copyright (c) 2011+, HL7, Inc
003All rights reserved.
004
005Redistribution and use in source and binary forms, with or without modification, 
006are permitted provided that the following conditions are met:
007
008 * Redistributions of source code must retain the above copyright notice, this 
009   list of conditions and the following disclaimer.
010 * Redistributions in binary form must reproduce the above copyright notice, 
011   this list of conditions and the following disclaimer in the documentation 
012   and/or other materials provided with the distribution.
013 * Neither the name of HL7 nor the names of its contributors may be used to 
014   endorse or promote products derived from this software without specific 
015   prior written permission.
016
017THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
018ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
019WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
020IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
021INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
022NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
023PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
024WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
025ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
026POSSIBILITY OF SUCH DAMAGE.
027
028*/
029/**
030 *
031 */
032package org.hl7.fhir.r4.model;
033
034import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
035import ca.uhn.fhir.model.api.annotation.DatatypeDef;
036
037import java.util.Calendar;
038import java.util.Date;
039import java.util.TimeZone;
040import java.util.zip.DataFormatException;
041
042/**
043 * Represents a FHIR instant datatype. Valid precisions values for this type are:
044 * <ul>
045 * <li>{@link TemporalPrecisionEnum#SECOND}
046 * <li>{@link TemporalPrecisionEnum#MILLI}
047 * </ul>
048 */
049@DatatypeDef(name = "instant")
050public class InstantType extends BaseDateTimeType {
051
052  /**
053   * The default precision for this type
054   */
055  public static final TemporalPrecisionEnum DEFAULT_PRECISION = TemporalPrecisionEnum.MILLI;
056  private static final long serialVersionUID = 3L;
057
058  /**
059   * Constructor which creates an InstantDt with <b>no timne value</b>. Note
060   * that unlike the default constructor for the Java {@link Date} or
061   * {@link Calendar} objects, this constructor does not initialize the object
062   * with the current time.
063   *
064   * @see #withCurrentTime() to create a new object that has been initialized
065   * with 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 this type
082   */
083  public InstantType(Date theDate, TemporalPrecisionEnum thePrecision, TimeZone theTimezone) {
084    super(theDate, thePrecision, theTimezone);
085  }
086
087
088  /**
089   * Create a new DateTimeDt using an existing value. <b>Use this constructor with caution</b>,
090   * as it may create more precision than warranted (since for example it is possible to pass in
091   * a DateTime with only a year, and this constructor will convert to an InstantDt with
092   * 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 {@link TemporalPrecisionEnum#MILLI} precision
103   */
104  public InstantType(Date theDate) {
105    super(theDate, DEFAULT_PRECISION, TimeZone.getDefault());
106  }
107
108  /**
109   * Constructor which accepts a date value and a precision value. Valid
110   * precisions values for this type are:
111   * <ul>
112   * <li>{@link TemporalPrecisionEnum#SECOND}
113   * <li>{@link TemporalPrecisionEnum#MILLI}
114   * </ul>
115   */
116  public InstantType(Date theDate, TemporalPrecisionEnum thePrecision) {
117    setValue(theDate);
118    setPrecision(thePrecision);
119    setTimeZone(TimeZone.getDefault());
120  }
121
122  /**
123   * Create a new InstantDt from a string value
124   *
125   * @param theString The string representation of the string. Must be in a valid
126   *                  format according to the FHIR specification
127   * @throws DataFormatException
128   */
129  public InstantType(String theString) {
130    super(theString);
131  }
132
133  /**
134   * Invokes {@link Date#after(Date)} on the contained Date against the given
135   * date
136   *
137   * @throws NullPointerException If the {@link #getValue() contained Date} is null
138   */
139  public boolean after(Date theDate) {
140    return getValue().after(theDate);
141  }
142
143  /**
144   * Invokes {@link Date#before(Date)} on the contained Date against the given
145   * date
146   *
147   * @throws NullPointerException If the {@link #getValue() contained Date} is null
148   */
149  public boolean before(Date theDate) {
150    return getValue().before(theDate);
151  }
152
153  @Override
154  public InstantType copy() {
155    return new InstantType(getValueAsString());
156  }
157
158  public String fhirType() {
159    return "instant";
160  }
161
162  /**
163   * Returns the default precision for this datatype
164   *
165   * @see #DEFAULT_PRECISION
166   */
167  @Override
168  protected TemporalPrecisionEnum getDefaultPrecisionForDatatype() {
169    return DEFAULT_PRECISION;
170  }
171
172  @Override
173  boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision) {
174    switch (thePrecision) {
175      case SECOND:
176      case MILLI:
177        return true;
178      default:
179        return false;
180    }
181  }
182
183  /**
184   * Sets the value of this instant to the current time (from the system
185   * clock) and the local/default timezone (as retrieved using
186   * {@link TimeZone#getDefault()}. This TimeZone is generally obtained from
187   * the underlying OS.
188   */
189  public void setToCurrentTimeInLocalTimeZone() {
190    setValue(new Date());
191    setTimeZone(TimeZone.getDefault());
192  }
193
194  /**
195   * Returns a new instance of DateTimeType with the current system time and MILLI precision and the system local time
196   * zone
197   */
198  public static InstantType now() {
199    return new InstantType(new Date(), TemporalPrecisionEnum.MILLI, TimeZone.getDefault());
200  }
201
202  /**
203   * Creates a new instance by parsing an HL7 v3 format date time string
204   */
205  public static InstantType parseV3(String theV3String) {
206    InstantType retVal = new InstantType();
207    retVal.setValueAsV3String(theV3String);
208    return retVal;
209  }
210
211  /**
212   * Factory method which creates a new InstantDt with millisecond precision and initializes it with the
213   * current time and the system local timezone.
214   */
215  public static InstantType withCurrentTime() {
216    return new InstantType(new Date(), TemporalPrecisionEnum.MILLI, TimeZone.getDefault());
217  }
218}