Add unit test for BaseDateTimeDt
This commit is contained in:
parent
df2011388c
commit
e2d59ef5ba
|
@ -23,9 +23,12 @@ package ca.uhn.fhir.model.primitive;
|
||||||
import static ca.uhn.fhir.model.api.TemporalPrecisionEnum.*;
|
import static ca.uhn.fhir.model.api.TemporalPrecisionEnum.*;
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.List;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -39,6 +42,10 @@ import ca.uhn.fhir.parser.DataFormatException;
|
||||||
|
|
||||||
public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add any new formatters to the static block below!!
|
||||||
|
*/
|
||||||
|
private static final List<FastDateFormat> ourFormatters;
|
||||||
private static final Pattern ourYearDashMonthDashDayPattern = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}");
|
private static final Pattern ourYearDashMonthDashDayPattern = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}");
|
||||||
private static final Pattern ourYearDashMonthPattern = Pattern.compile("[0-9]{4}-[0-9]{2}");
|
private static final Pattern ourYearDashMonthPattern = Pattern.compile("[0-9]{4}-[0-9]{2}");
|
||||||
private static final FastDateFormat ourYearFormat = FastDateFormat.getInstance("yyyy");
|
private static final FastDateFormat ourYearFormat = FastDateFormat.getInstance("yyyy");
|
||||||
|
@ -47,23 +54,43 @@ public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
||||||
private static final Pattern ourYearMonthDayPattern = Pattern.compile("[0-9]{4}[0-9]{2}[0-9]{2}");
|
private static final Pattern ourYearMonthDayPattern = Pattern.compile("[0-9]{4}[0-9]{2}[0-9]{2}");
|
||||||
private static final FastDateFormat ourYearMonthDayTimeFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss");
|
private static final FastDateFormat ourYearMonthDayTimeFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss");
|
||||||
private static final FastDateFormat ourYearMonthDayTimeMilliFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSS");
|
private static final FastDateFormat ourYearMonthDayTimeMilliFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSS");
|
||||||
private static final FastDateFormat ourYearMonthDayTimeUTCZFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("UTC"));
|
|
||||||
private static final FastDateFormat ourYearMonthDayTimeMilliUTCZFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", TimeZone.getTimeZone("UTC"));
|
private static final FastDateFormat ourYearMonthDayTimeMilliUTCZFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", TimeZone.getTimeZone("UTC"));
|
||||||
private static final FastDateFormat ourYearMonthDayTimeMilliZoneFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSSZZ");
|
private static final FastDateFormat ourYearMonthDayTimeMilliZoneFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSSZZ");
|
||||||
|
private static final FastDateFormat ourYearMonthDayTimeUTCZFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("UTC"));
|
||||||
private static final FastDateFormat ourYearMonthDayTimeZoneFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ssZZ");
|
private static final FastDateFormat ourYearMonthDayTimeZoneFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ssZZ");
|
||||||
private static final FastDateFormat ourYearMonthFormat = FastDateFormat.getInstance("yyyy-MM");
|
private static final FastDateFormat ourYearMonthFormat = FastDateFormat.getInstance("yyyy-MM");
|
||||||
private static final FastDateFormat ourYearMonthNoDashesFormat = FastDateFormat.getInstance("yyyyMM");
|
private static final FastDateFormat ourYearMonthNoDashesFormat = FastDateFormat.getInstance("yyyyMM");
|
||||||
private static final Pattern ourYearMonthPattern = Pattern.compile("[0-9]{4}[0-9]{2}");
|
private static final Pattern ourYearMonthPattern = Pattern.compile("[0-9]{4}[0-9]{2}");
|
||||||
private static final Pattern ourYearPattern = Pattern.compile("[0-9]{4}");
|
private static final Pattern ourYearPattern = Pattern.compile("[0-9]{4}");
|
||||||
|
|
||||||
|
static {
|
||||||
|
ArrayList<FastDateFormat> formatters = new ArrayList<FastDateFormat>();
|
||||||
|
formatters.add(ourYearFormat);
|
||||||
|
formatters.add(ourYearMonthDayFormat);
|
||||||
|
formatters.add(ourYearMonthDayNoDashesFormat);
|
||||||
|
formatters.add(ourYearMonthDayTimeFormat);
|
||||||
|
formatters.add(ourYearMonthDayTimeMilliFormat);
|
||||||
|
formatters.add(ourYearMonthDayTimeUTCZFormat);
|
||||||
|
formatters.add(ourYearMonthDayTimeMilliUTCZFormat);
|
||||||
|
formatters.add(ourYearMonthDayTimeMilliZoneFormat);
|
||||||
|
formatters.add(ourYearMonthDayTimeZoneFormat);
|
||||||
|
formatters.add(ourYearMonthFormat);
|
||||||
|
formatters.add(ourYearMonthNoDashesFormat);
|
||||||
|
ourFormatters = Collections.unmodifiableList(formatters);
|
||||||
|
}
|
||||||
private TemporalPrecisionEnum myPrecision = TemporalPrecisionEnum.SECOND;
|
private TemporalPrecisionEnum myPrecision = TemporalPrecisionEnum.SECOND;
|
||||||
|
|
||||||
private TimeZone myTimeZone;
|
private TimeZone myTimeZone;
|
||||||
private boolean myTimeZoneZulu = false;
|
private boolean myTimeZoneZulu = false;
|
||||||
private Date myValue;
|
private Date myValue;
|
||||||
|
|
||||||
|
private void clearTimeZone() {
|
||||||
|
myTimeZone = null;
|
||||||
|
myTimeZoneZulu = false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the precision for this datatype using field values from {@link Calendar}, such as {@link Calendar#MONTH}.
|
* Gets the precision for this datatype using field values from {@link Calendar}, such as {@link Calendar#MONTH}. Default is {@link Calendar#DAY_OF_MONTH}
|
||||||
* Default is {@link Calendar#DAY_OF_MONTH}
|
|
||||||
*
|
*
|
||||||
* @see #setPrecision(int)
|
* @see #setPrecision(int)
|
||||||
*/
|
*/
|
||||||
|
@ -121,6 +148,11 @@ public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To be implemented by subclasses to indicate whether the given precision is allowed by this type
|
||||||
|
*/
|
||||||
|
abstract boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision);
|
||||||
|
|
||||||
public boolean isTimeZoneZulu() {
|
public boolean isTimeZoneZulu() {
|
||||||
return myTimeZoneZulu;
|
return myTimeZoneZulu;
|
||||||
}
|
}
|
||||||
|
@ -154,6 +186,20 @@ public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
||||||
myPrecision = thePrecision;
|
myPrecision = thePrecision;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setTimeZone(String theValueString, boolean hasMillis) {
|
||||||
|
clearTimeZone();
|
||||||
|
int timeZoneStart = 19;
|
||||||
|
if (hasMillis)
|
||||||
|
timeZoneStart += 4;
|
||||||
|
if (theValueString.endsWith("Z")) {
|
||||||
|
setTimeZoneZulu(true);
|
||||||
|
} else if (theValueString.indexOf("GMT", timeZoneStart) != -1) {
|
||||||
|
setTimeZone(TimeZone.getTimeZone(theValueString.substring(timeZoneStart)));
|
||||||
|
} else if (theValueString.indexOf('+', timeZoneStart) != -1 || theValueString.indexOf('-', timeZoneStart) != -1) {
|
||||||
|
setTimeZone(TimeZone.getTimeZone("GMT" + theValueString.substring(timeZoneStart)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setTimeZone(TimeZone theTimeZone) {
|
public void setTimeZone(TimeZone theTimeZone) {
|
||||||
myTimeZone = theTimeZone;
|
myTimeZone = theTimeZone;
|
||||||
}
|
}
|
||||||
|
@ -217,7 +263,7 @@ public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
||||||
} else {
|
} else {
|
||||||
throw new DataFormatException("Invalid date/time string (datatype " + getClass().getSimpleName() + " does not support DAY precision): " + theValue);
|
throw new DataFormatException("Invalid date/time string (datatype " + getClass().getSimpleName() + " does not support DAY precision): " + theValue);
|
||||||
}
|
}
|
||||||
} else if (theValue.length() >= 18) { //date and time with possible time zone
|
} else if (theValue.length() >= 18) { // date and time with possible time zone
|
||||||
int dotIndex = theValue.indexOf('.', 18);
|
int dotIndex = theValue.indexOf('.', 18);
|
||||||
boolean hasMillis = dotIndex > -1;
|
boolean hasMillis = dotIndex > -1;
|
||||||
|
|
||||||
|
@ -227,34 +273,32 @@ public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
||||||
throw new DataFormatException("Invalid date/time string (data type " + getClass().getSimpleName() + " does not support MILLIS precision):" + theValue);
|
throw new DataFormatException("Invalid date/time string (data type " + getClass().getSimpleName() + " does not support MILLIS precision):" + theValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hasMillis){
|
if (hasMillis) {
|
||||||
try {
|
try {
|
||||||
|
if (hasOffset(theValue)) {
|
||||||
myValue = ourYearMonthDayTimeMilliZoneFormat.parse(theValue);
|
myValue = ourYearMonthDayTimeMilliZoneFormat.parse(theValue);
|
||||||
} catch (ParseException p){
|
} else if (theValue.endsWith("Z"))
|
||||||
try{
|
|
||||||
if(theValue.endsWith("Z"))
|
|
||||||
myValue = ourYearMonthDayTimeMilliUTCZFormat.parse(theValue);
|
myValue = ourYearMonthDayTimeMilliUTCZFormat.parse(theValue);
|
||||||
else
|
else
|
||||||
myValue = ourYearMonthDayTimeMilliFormat.parse(theValue);
|
myValue = ourYearMonthDayTimeMilliFormat.parse(theValue);
|
||||||
}catch(ParseException p2){
|
} catch (ParseException p2) {
|
||||||
throw new DataFormatException("Invalid data/time string (" + p2.getMessage() + "): " + theValue);
|
throw new DataFormatException("Invalid data/time string (" + p2.getMessage() + "): " + theValue);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
setTimeZone(theValue, hasMillis);
|
setTimeZone(theValue, hasMillis);
|
||||||
setPrecision(TemporalPrecisionEnum.MILLI);
|
setPrecision(TemporalPrecisionEnum.MILLI);
|
||||||
}else{
|
} else {
|
||||||
try{
|
try {
|
||||||
|
if (hasOffset(theValue)) {
|
||||||
myValue = ourYearMonthDayTimeZoneFormat.parse(theValue);
|
myValue = ourYearMonthDayTimeZoneFormat.parse(theValue);
|
||||||
}catch(ParseException p){
|
} else if (theValue.endsWith("Z")) {
|
||||||
try{
|
|
||||||
if(theValue.endsWith("Z"))
|
|
||||||
myValue = ourYearMonthDayTimeUTCZFormat.parse(theValue);
|
myValue = ourYearMonthDayTimeUTCZFormat.parse(theValue);
|
||||||
else
|
} else {
|
||||||
myValue = ourYearMonthDayTimeFormat.parse(theValue);
|
myValue = ourYearMonthDayTimeFormat.parse(theValue);
|
||||||
}catch(ParseException p2){
|
}
|
||||||
|
} catch (ParseException p2) {
|
||||||
throw new DataFormatException("Invalid data/time string (" + p2.getMessage() + "): " + theValue);
|
throw new DataFormatException("Invalid data/time string (" + p2.getMessage() + "): " + theValue);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
setTimeZone(theValue, hasMillis);
|
setTimeZone(theValue, hasMillis);
|
||||||
setPrecision(TemporalPrecisionEnum.SECOND);
|
setPrecision(TemporalPrecisionEnum.SECOND);
|
||||||
}
|
}
|
||||||
|
@ -266,27 +310,29 @@ public abstract class BaseDateTimeDt extends BasePrimitive<Date> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTimeZone(String theValueString, boolean hasMillis) {
|
private boolean hasOffset(String theValue) {
|
||||||
clearTimeZone();
|
boolean inTime = false;
|
||||||
int timeZoneStart = 19;
|
for (int i = 0; i < theValue.length(); i++) {
|
||||||
if(hasMillis) timeZoneStart += 4;
|
switch (theValue.charAt(i)) {
|
||||||
if (theValueString.endsWith("Z")) {
|
case 'T':
|
||||||
setTimeZoneZulu(true);
|
inTime = true;
|
||||||
} else if (theValueString.indexOf("GMT", timeZoneStart) != -1) {
|
break;
|
||||||
setTimeZone(TimeZone.getTimeZone(theValueString.substring(timeZoneStart)));
|
case '+':
|
||||||
} else if (theValueString.indexOf('+', timeZoneStart) != -1 || theValueString.indexOf('-', timeZoneStart) != -1) {
|
case '-':
|
||||||
setTimeZone(TimeZone.getTimeZone("GMT"+theValueString.substring(timeZoneStart)));
|
if (inTime) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
private void clearTimeZone() {
|
|
||||||
myTimeZone = null;
|
|
||||||
myTimeZoneZulu = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To be implemented by subclasses to indicate whether the given precision is allowed by this type
|
* For unit tests only
|
||||||
*/
|
*/
|
||||||
abstract boolean isPrecisionAllowed(TemporalPrecisionEnum thePrecision);
|
static List<FastDateFormat> getFormatters() {
|
||||||
|
return ourFormatters;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,11 @@ package ca.uhn.fhir.model.primitive;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.apache.commons.lang3.time.FastDateFormat;
|
import org.apache.commons.lang3.time.FastDateFormat;
|
||||||
|
@ -15,6 +19,7 @@ import ca.uhn.fhir.parser.DataFormatException;
|
||||||
public class BaseDateTimeDtTest {
|
public class BaseDateTimeDtTest {
|
||||||
private SimpleDateFormat myDateInstantParser;
|
private SimpleDateFormat myDateInstantParser;
|
||||||
private FastDateFormat myDateInstantZoneParser;
|
private FastDateFormat myDateInstantZoneParser;
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseDateTimeDtTest.class);
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() {
|
public void before() {
|
||||||
|
@ -22,6 +27,24 @@ public class BaseDateTimeDtTest {
|
||||||
myDateInstantZoneParser = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss.SSSZ", TimeZone.getTimeZone("GMT-02:00"));
|
myDateInstantZoneParser = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss.SSSZ", TimeZone.getTimeZone("GMT-02:00"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFormats() throws Exception {
|
||||||
|
Date instant = myDateInstantParser.parse("2001-02-03 13:01:02.555");
|
||||||
|
for (FastDateFormat next : BaseDateTimeDt.getFormatters()) {
|
||||||
|
|
||||||
|
GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("EST"));
|
||||||
|
cal.setTime(instant);
|
||||||
|
String value = next.format(cal);
|
||||||
|
ourLog.info("String: {}", value);
|
||||||
|
|
||||||
|
DateTimeDt dt = new DateTimeDt(value);
|
||||||
|
String reEncoded = next.format(dt.getValue());
|
||||||
|
|
||||||
|
assertEquals(value, reEncoded);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseYear() throws DataFormatException {
|
public void testParseYear() throws DataFormatException {
|
||||||
DateTimeDt dt = new DateTimeDt();
|
DateTimeDt dt = new DateTimeDt();
|
||||||
|
|
Loading…
Reference in New Issue