001package org.hl7.fhir.r4.model; 002 003import java.util.Calendar; 004import java.util.Date; 005import java.util.TimeZone; 006import java.util.zip.DataFormatException; 007 008import org.apache.commons.lang3.time.DateUtils; 009 010/* 011 Copyright (c) 2011+, HL7, Inc. 012 All rights reserved. 013 014 Redistribution and use in source and binary forms, with or without modification, 015 are permitted provided that the following conditions are met: 016 017 * Redistributions of source code must retain the above copyright notice, this 018 list of conditions and the following disclaimer. 019 * Redistributions in binary form must reproduce the above copyright notice, 020 this list of conditions and the following disclaimer in the documentation 021 and/or other materials provided with the distribution. 022 * Neither the name of HL7 nor the names of its contributors may be used to 023 endorse or promote products derived from this software without specific 024 prior written permission. 025 026 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 027 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 028 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 029 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 030 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 031 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 032 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 033 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 034 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 035 POSSIBILITY OF SUCH DAMAGE. 036 037 */ 038 039import ca.uhn.fhir.model.api.TemporalPrecisionEnum; 040import ca.uhn.fhir.model.api.annotation.DatatypeDef; 041 042/** 043 * Represents a FHIR dateTime datatype. Valid precisions values for this type 044 * are: 045 * <ul> 046 * <li>{@link TemporalPrecisionEnum#YEAR} 047 * <li>{@link TemporalPrecisionEnum#MONTH} 048 * <li>{@link TemporalPrecisionEnum#DAY} 049 * <li>{@link TemporalPrecisionEnum#SECOND} 050 * <li>{@link TemporalPrecisionEnum#MILLI} 051 * </ul> 052 */ 053@DatatypeDef(name = "dateTime") 054public class DateTimeType extends BaseDateTimeType { 055 056 private static final long serialVersionUID = 3L; 057 058 /** 059 * The default precision for this type 060 */ 061 public static final TemporalPrecisionEnum DEFAULT_PRECISION = TemporalPrecisionEnum.SECOND; 062 063 /** 064 * Constructor 065 */ 066 public DateTimeType() { 067 super(); 068 } 069 070 /** 071 * Create a new DateTimeDt with seconds precision and the local time zone 072 */ 073 public DateTimeType(Date theDate) { 074 super(theDate, DEFAULT_PRECISION, TimeZone.getDefault()); 075 } 076 077 /** 078 * Constructor which accepts a date value and a precision value. Valid 079 * precisions values for this type are: 080 * <ul> 081 * <li>{@link TemporalPrecisionEnum#YEAR} 082 * <li>{@link TemporalPrecisionEnum#MONTH} 083 * <li>{@link TemporalPrecisionEnum#DAY} 084 * <li>{@link TemporalPrecisionEnum#SECOND} 085 * <li>{@link TemporalPrecisionEnum#MILLI} 086 * </ul> 087 * 088 * @throws DataFormatException If the specified precision is not allowed for 089 * this type 090 */ 091 public DateTimeType(Date theDate, TemporalPrecisionEnum thePrecision) { 092 super(theDate, thePrecision, TimeZone.getDefault()); 093 } 094 095 /** 096 * Create a new instance using a string date/time 097 * 098 * @throws DataFormatException If the specified precision is not allowed for 099 * this type 100 */ 101 public DateTimeType(String theValue) { 102 super(theValue); 103 } 104 105 /** 106 * Constructor which accepts a date value, precision value, and time zone. Valid 107 * precisions values for this type are: 108 * <ul> 109 * <li>{@link TemporalPrecisionEnum#YEAR} 110 * <li>{@link TemporalPrecisionEnum#MONTH} 111 * <li>{@link TemporalPrecisionEnum#DAY} 112 * <li>{@link TemporalPrecisionEnum#SECOND} 113 * <li>{@link TemporalPrecisionEnum#MILLI} 114 * </ul> 115 */ 116 public DateTimeType(Date theDate, TemporalPrecisionEnum thePrecision, TimeZone theTimezone) { 117 super(theDate, thePrecision, theTimezone); 118 } 119 120 /** 121 * Constructor 122 */ 123 public DateTimeType(Calendar theCalendar) { 124 if (theCalendar != null) { 125 setValue(theCalendar.getTime()); 126 setPrecision(DEFAULT_PRECISION); 127 setTimeZone(theCalendar.getTimeZone()); 128 } 129 } 130 131 @Override 132 boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision) { 133 switch (thePrecision) { 134 case YEAR: 135 case MONTH: 136 case DAY: 137 case SECOND: 138 case MILLI: 139 return true; 140 default: 141 return false; 142 } 143 } 144 145 /** 146 * Returns a new instance of DateTimeType with the current system time and 147 * SECOND precision and the system local time zone 148 */ 149 public static DateTimeType now() { 150 return new DateTimeType(new Date(), TemporalPrecisionEnum.SECOND, TimeZone.getDefault()); 151 } 152 153 /** 154 * Returns the default precision for this datatype 155 * 156 * @see #DEFAULT_PRECISION 157 */ 158 @Override 159 protected TemporalPrecisionEnum getDefaultPrecisionForDatatype() { 160 return DEFAULT_PRECISION; 161 } 162 163 @Override 164 public DateTimeType copy() { 165 DateTimeType ret = new DateTimeType(getValueAsString()); 166 copyValues(ret); 167 return ret; 168 } 169 170 /** 171 * Creates a new instance by parsing an HL7 v3 format date time string 172 */ 173 public static DateTimeType parseV3(String theV3String) { 174 DateTimeType retVal = new DateTimeType(); 175 retVal.setValueAsV3String(theV3String); 176 return retVal; 177 } 178 179 public static DateTimeType today() { 180 DateTimeType retVal = now(); 181 retVal.setPrecision(TemporalPrecisionEnum.DAY); 182 return retVal; 183 } 184 185 public boolean getTzSign() { 186 return getTimeZone().getRawOffset() >= 0; 187 } 188 189 public int getTzHour() { 190 return (int) (getTimeZone().getRawOffset() / DateUtils.MILLIS_PER_MINUTE) / 60; 191 } 192 193 public int getTzMin() { 194 return (int) (getTimeZone().getRawOffset() / DateUtils.MILLIS_PER_MINUTE) % 60; 195 } 196 197 public String fhirType() { 198 return "dateTime"; 199 } 200 201 public String getAsV3() { 202 String r = getValueAsString(); 203 r = stripChar(r, 16, ':'); 204 r = stripChar(r, 13, ':'); 205 r = stripChar(r, 10, 'T'); 206 r = stripChar(r, 7, '-'); 207 r = stripChar(r, 4, '-'); 208 r = r.replaceAll(":", ""); // might be in the timezone 209 return r; 210 } 211 212 private String stripChar(String r, int i, char c) { 213 if (r.length() <= i || r.charAt(i) != c) 214 return r; 215 return r.substring(0, i) + r.substring(i + 1); 216 } 217 218 @Override 219 public boolean isDateTime() { 220 return true; 221 } 222 223}