001/* 002 * #%L 003 * HAPI FHIR - Core Library 004 * %% 005 * Copyright (C) 2014 - 2023 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 java.util.Calendar; 023 024import java.util.Date; 025import java.util.GregorianCalendar; 026import java.util.TimeZone; 027 028import ca.uhn.fhir.model.api.TemporalPrecisionEnum; 029import ca.uhn.fhir.model.api.annotation.DatatypeDef; 030import ca.uhn.fhir.model.api.annotation.SimpleSetter; 031import ca.uhn.fhir.parser.DataFormatException; 032 033/** 034 * Represents a FHIR date datatype. Valid precisions values for this type are: 035 * <ul> 036 * <li>{@link TemporalPrecisionEnum#YEAR} 037 * <li>{@link TemporalPrecisionEnum#MONTH} 038 * <li>{@link TemporalPrecisionEnum#DAY} 039 * </ul> 040 * 041 * <p> 042 * <b>Note on using Java Date objects:</b> This type stores the date as a Java Date. Note that 043 * the Java Date has more precision (millisecond precision), and does not store a timezone. As such, 044 * it could potentially cause issues. For example, if a Date contains the number of milliseconds at 045 * midnight in a timezone across the date line from your location, it might refer to a different date than 046 * intended. 047 * </p> 048 * <p> 049 * As such, it is recommended to use the <code>Calendar<code> or <code>int,int,int</code> constructors 050 * </p> 051 */ 052@DatatypeDef(name = "date") 053public class DateDt extends BaseDateTimeDt { 054 055 /** 056 * The default precision for this type 057 */ 058 public static final TemporalPrecisionEnum DEFAULT_PRECISION = TemporalPrecisionEnum.DAY; 059 060 /** 061 * Constructor 062 */ 063 public DateDt() { 064 super(); 065 } 066 067 /** 068 * Constructor which accepts a date value and uses the {@link #DEFAULT_PRECISION} for this type. 069 */ 070 public DateDt(Calendar theCalendar) { 071 super(theCalendar.getTime(), DEFAULT_PRECISION); 072 setTimeZone(theCalendar.getTimeZone()); 073 } 074 075 /** 076 * Constructor which accepts a date value and uses the {@link #DEFAULT_PRECISION} for this type. 077 * <b>Please see the note on timezones</b> on the {@link DateDt class documentation} for considerations 078 * when using this constructor! 079 */ 080 @SimpleSetter(suffix = "WithDayPrecision") 081 public DateDt(@SimpleSetter.Parameter(name = "theDate") Date theDate) { 082 super(theDate, DEFAULT_PRECISION); 083 } 084 085 /** 086 * Constructor which accepts a date value and a precision value. Valid precisions values for this type are: 087 * <ul> 088 * <li>{@link TemporalPrecisionEnum#YEAR} 089 * <li>{@link TemporalPrecisionEnum#MONTH} 090 * <li>{@link TemporalPrecisionEnum#DAY} 091 * </ul> 092 * <b>Please see the note on timezones</b> on the {@link DateDt class documentation} for considerations 093 * when using this constructor! 094 * 095 * @throws DataFormatException 096 * If the specified precision is not allowed for this type 097 */ 098 @SimpleSetter 099 public DateDt(@SimpleSetter.Parameter(name = "theDate") Date theDate, @SimpleSetter.Parameter(name = "thePrecision") TemporalPrecisionEnum thePrecision) { 100 super(theDate, thePrecision); 101 } 102 103 /** 104 * Constructor which accepts a date value and uses the {@link #DEFAULT_PRECISION} for this type. 105 * 106 * @param theYear The year, e.g. 2015 107 * @param theMonth The month, e.g. 0 for January 108 * @param theDay The day (1 indexed) e.g. 1 for the first day of the month 109 */ 110 public DateDt(int theYear, int theMonth, int theDay) { 111 this(toCalendarZulu(theYear, theMonth, theDay)); 112 } 113 114 /** 115 * Constructor which accepts a date as a string in FHIR format 116 * 117 * @throws DataFormatException 118 * If the precision in the date string is not allowed for this type 119 */ 120 public DateDt(String theDate) { 121 super(theDate); 122 } 123 124 /** 125 * Returns the default precision for this datatype 126 * 127 * @see #DEFAULT_PRECISION 128 */ 129 @Override 130 protected TemporalPrecisionEnum getDefaultPrecisionForDatatype() { 131 return DEFAULT_PRECISION; 132 } 133 134 @Override 135 protected boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision) { 136 switch (thePrecision) { 137 case YEAR: 138 case MONTH: 139 case DAY: 140 return true; 141 default: 142 return false; 143 } 144 } 145 146 private static GregorianCalendar toCalendarZulu(int theYear, int theMonth, int theDay) { 147 GregorianCalendar retVal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); 148 retVal.set(Calendar.YEAR, theYear); 149 retVal.set(Calendar.MONTH, theMonth); 150 retVal.set(Calendar.DATE, theDay); 151 return retVal; 152 } 153 154}