001/* 002 * #%L 003 * HAPI FHIR - Core Library 004 * %% 005 * Copyright (C) 2014 - 2024 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.model.primitive; 021 022import ca.uhn.fhir.model.api.TemporalPrecisionEnum; 023import ca.uhn.fhir.model.api.annotation.DatatypeDef; 024import ca.uhn.fhir.model.api.annotation.SimpleSetter; 025import ca.uhn.fhir.parser.DataFormatException; 026 027import java.util.Calendar; 028import java.util.Date; 029import java.util.TimeZone; 030 031/** 032 * Represents a FHIR instant datatype. Valid precisions values for this type are: 033 * <ul> 034 * <li>{@link TemporalPrecisionEnum#SECOND} 035 * <li>{@link TemporalPrecisionEnum#MILLI} 036 * </ul> 037 */ 038@DatatypeDef(name = "instant") 039public class InstantDt extends BaseDateTimeDt { 040 041 /** 042 * The default precision for this type 043 */ 044 public static final TemporalPrecisionEnum DEFAULT_PRECISION = TemporalPrecisionEnum.MILLI; 045 046 /** 047 * Constructor which creates an InstantDt with <b>no timne value</b>. Note 048 * that unlike the default constructor for the Java {@link Date} or 049 * {@link Calendar} objects, this constructor does not initialize the object 050 * with the current time. 051 * 052 * @see #withCurrentTime() to create a new object that has been initialized 053 * with the current time. 054 */ 055 public InstantDt() { 056 super(); 057 } 058 059 /** 060 * Create a new DateTimeDt 061 */ 062 public InstantDt(Calendar theCalendar) { 063 super(theCalendar.getTime(), DEFAULT_PRECISION, theCalendar.getTimeZone()); 064 } 065 066 /** 067 * Create a new instance using the given date, precision level, and time zone 068 * 069 * @throws DataFormatException 070 * If the specified precision is not allowed for this type 071 */ 072 public InstantDt(Date theDate, TemporalPrecisionEnum thePrecision, TimeZone theTimezone) { 073 super(theDate, thePrecision, theTimezone); 074 } 075 076 /** 077 * Create a new DateTimeDt using an existing value. <b>Use this constructor with caution</b>, 078 * as it may create more precision than warranted (since for example it is possible to pass in 079 * a DateTime with only a year, and this constructor will convert to an InstantDt with 080 * milliseconds precision). 081 */ 082 public InstantDt(BaseDateTimeDt theDateTime) { 083 // Do not call super(foo) here, we don't want to trigger a DataFormatException 084 setValue(theDateTime.getValue()); 085 setPrecision(DEFAULT_PRECISION); 086 setTimeZone(theDateTime.getTimeZone()); 087 } 088 089 /** 090 * Create a new DateTimeDt with the given date/time and {@link TemporalPrecisionEnum#MILLI} precision 091 */ 092 @SimpleSetter(suffix = "WithMillisPrecision") 093 public InstantDt(@SimpleSetter.Parameter(name = "theDate") Date theDate) { 094 super(theDate, DEFAULT_PRECISION, TimeZone.getDefault()); 095 } 096 097 /** 098 * Constructor which accepts a date value and a precision value. Valid 099 * precisions values for this type are: 100 * <ul> 101 * <li>{@link TemporalPrecisionEnum#SECOND} 102 * <li>{@link TemporalPrecisionEnum#MILLI} 103 * </ul> 104 */ 105 @SimpleSetter 106 public InstantDt( 107 @SimpleSetter.Parameter(name = "theDate") Date theDate, 108 @SimpleSetter.Parameter(name = "thePrecision") TemporalPrecisionEnum thePrecision) { 109 setValue(theDate); 110 setPrecision(thePrecision); 111 setTimeZone(TimeZone.getDefault()); 112 } 113 114 /** 115 * Create a new InstantDt from a string value 116 * 117 * @param theString 118 * The string representation of the string. Must be in a valid 119 * format according to the FHIR specification 120 * @throws DataFormatException 121 */ 122 public InstantDt(String theString) { 123 super(theString); 124 } 125 126 /** 127 * Invokes {@link Date#after(Date)} on the contained Date against the given 128 * date 129 * 130 * @throws NullPointerException 131 * If the {@link #getValue() contained Date} is null 132 */ 133 public boolean after(Date theDate) { 134 return getValue().after(theDate); 135 } 136 137 /** 138 * Invokes {@link Date#before(Date)} on the contained Date against the given 139 * date 140 * 141 * @throws NullPointerException 142 * If the {@link #getValue() contained Date} is null 143 */ 144 public boolean before(Date theDate) { 145 return getValue().before(theDate); 146 } 147 148 /** 149 * Sets the value of this instant to the current time (from the system 150 * clock) and the local/default timezone (as retrieved using 151 * {@link TimeZone#getDefault()}. This TimeZone is generally obtained from 152 * the underlying OS. 153 */ 154 public void setToCurrentTimeInLocalTimeZone() { 155 setValue(new Date()); 156 setTimeZone(TimeZone.getDefault()); 157 } 158 159 @Override 160 protected boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision) { 161 switch (thePrecision) { 162 case SECOND: 163 case MILLI: 164 return true; 165 default: 166 return false; 167 } 168 } 169 170 /** 171 * Factory method which creates a new InstantDt with millisecond precision and initializes it with the 172 * current time and the system local timezone. 173 */ 174 public static InstantDt withCurrentTime() { 175 return new InstantDt(new Date(), TemporalPrecisionEnum.MILLI, TimeZone.getDefault()); 176 } 177 178 /** 179 * Returns the default precision for this datatype 180 * 181 * @see #DEFAULT_PRECISION 182 */ 183 @Override 184 protected TemporalPrecisionEnum getDefaultPrecisionForDatatype() { 185 return DEFAULT_PRECISION; 186 } 187}