Commit a9d96ac4 authored by R.W.Majeed's avatar R.W.Majeed

backed value of DateTimeAccuracy changed from LocalDateTime to Instant. Fixes some conversions.

parent 76204594
......@@ -57,48 +57,40 @@ public class DateTimeAccuracy implements Temporal, Comparable<DateTimeAccuracy>
static final DateTimeFormatter PARTIAL_FORMATTER = DateTimeFormatter.ofPattern(PARTIAL_FORMATTER_PATTERN);
// TODO why not use instant, since we always calculate UTC? or Offset/ZonedDateTime?
private LocalDateTime dateTime;
private Instant instant;
private ChronoUnit accuracy;
/**
* Create date time with accuracy to seconds.
* @param dateTime timestamp
*/
public DateTimeAccuracy(LocalDateTime dateTime){
this.dateTime = dateTime;
public DateTimeAccuracy(Instant instant){
this.instant = instant;
this.accuracy = ChronoUnit.SECONDS;
}
public DateTimeAccuracy(int year) {
dateTime = LocalDateTime.of(year, 1, 1, 0, 0);
instant = LocalDateTime.of(year, 1, 1, 0, 0).toInstant(ZoneOffset.UTC);
accuracy = ChronoUnit.YEARS;
// truncation works only up to days
dateTime.truncatedTo(ChronoUnit.DAYS);
}
public DateTimeAccuracy(int year, int month) {
dateTime = LocalDateTime.of(year, month, 1, 0, 0);
instant = LocalDateTime.of(year, month, 1, 0, 0).toInstant(ZoneOffset.UTC);
accuracy = ChronoUnit.MONTHS;
// truncation works only up to days
dateTime.truncatedTo(ChronoUnit.DAYS);
}
public DateTimeAccuracy(int year, int month, int day) {
dateTime = LocalDateTime.of(year, month, day, 0, 0);
instant = LocalDateTime.of(year, month, day, 0, 0).toInstant(ZoneOffset.UTC);
accuracy = ChronoUnit.DAYS;
dateTime.truncatedTo(accuracy);
}
public DateTimeAccuracy(int year, int month, int day, int hours) {
dateTime = LocalDateTime.of(year, month, day, hours, 0);
instant = LocalDateTime.of(year, month, day, hours, 0).toInstant(ZoneOffset.UTC);
accuracy = ChronoUnit.HOURS;
dateTime.truncatedTo(accuracy);
}
public DateTimeAccuracy(int year, int month, int day, int hours, int mins) {
dateTime = LocalDateTime.of(year, month, day, hours, mins);
instant = LocalDateTime.of(year, month, day, hours, mins).toInstant(ZoneOffset.UTC);
accuracy = ChronoUnit.MINUTES;
dateTime.truncatedTo(accuracy);
}
public DateTimeAccuracy(int year, int month, int day, int hours, int mins, int secs) {
dateTime = LocalDateTime.of(year, month, day, hours, mins, secs);
instant = LocalDateTime.of(year, month, day, hours, mins, secs).toInstant(ZoneOffset.UTC);
accuracy = ChronoUnit.SECONDS;
dateTime.truncatedTo(accuracy);
}
/**
......@@ -108,23 +100,24 @@ public class DateTimeAccuracy implements Temporal, Comparable<DateTimeAccuracy>
* @return minimum instant within the given accuracy
*/
public Instant toInstantMin(){
return dateTime.toInstant(ZoneOffset.UTC);
return instant;
}
// TODO toInstantMax() (increase field at accuracy and subtract one millisecond)
// Temporal interface behaves like underlaying dateTime
// Temporal interface behaves like underlaying instant
// TODO verify that these methods make sense with given accuracy
@Override
public long getLong(TemporalField arg0) {return dateTime.getLong(arg0);}
public long getLong(TemporalField arg0) {return instant.getLong(arg0);}
@Override
public boolean isSupported(TemporalField arg0) {return dateTime.isSupported(arg0);}
public boolean isSupported(TemporalField arg0) {return instant.isSupported(arg0);}
@Override
public boolean isSupported(TemporalUnit unit) {return dateTime.isSupported(unit);}
public boolean isSupported(TemporalUnit unit) {return instant.isSupported(unit);}
@Override
public Temporal plus(long amountToAdd, TemporalUnit unit) {return dateTime.plus(amountToAdd,unit);}
public Temporal plus(long amountToAdd, TemporalUnit unit) {return instant.plus(amountToAdd,unit);}
@Override
public long until(Temporal endExclusive, TemporalUnit unit) {return dateTime.until(endExclusive, unit);}
public long until(Temporal endExclusive, TemporalUnit unit) {return instant.until(endExclusive, unit);}
@Override
public Temporal with(TemporalField field, long newValue) {return dateTime.with(field,newValue);}
public Temporal with(TemporalField field, long newValue) {return instant.with(field,newValue);}
/**
* Get the accuracy for the date time object.
......@@ -156,11 +149,10 @@ public class DateTimeAccuracy implements Temporal, Comparable<DateTimeAccuracy>
* Get the local time
* @return local time
*/
public LocalDateTime getLocal(){ return dateTime; }
//public LocalDateTime getLocal(){ return instant.at; }
public void set(Date timestamp, ChronoUnit accuracy){
dateTime = LocalDateTime.from(timestamp.toInstant());
dateTime.truncatedTo(accuracy);
instant = timestamp.toInstant();
this.accuracy = accuracy;
}
......@@ -208,16 +200,16 @@ public class DateTimeAccuracy implements Temporal, Comparable<DateTimeAccuracy>
*/
public String toPartialIso8601(ZoneId tz){
StringBuilder b = new StringBuilder(20);
if( dateTime == null )return "null";
if( instant == null )return "null";
TemporalAccessor dt;
if( tz != null ){
// use timezone information.
// Assume that dateTime is given in UTC. For output convert to destination timezone.
dt = dateTime.atOffset(ZoneOffset.UTC).atZoneSameInstant(tz);
dt = instant.atOffset(ZoneOffset.UTC).atZoneSameInstant(tz);
}else{
// no zone info, output will not have offset
dt = dateTime;
dt = instant.atOffset(ZoneOffset.UTC).toLocalDateTime();
}
char[] prefixes = {0,'-','-','T',':',':'};
......@@ -327,15 +319,22 @@ public class DateTimeAccuracy implements Temporal, Comparable<DateTimeAccuracy>
}
// check for zone offset
ZoneOffset off = null;
Instant inst;
if( a.isSupported(ChronoField.OFFSET_SECONDS) ){
off = ZoneOffset.ofTotalSeconds(a.get(ChronoField.OFFSET_SECONDS));
// adjust to UTC
dateTime = dateTime.atOffset(off).withOffsetSameInstant(ZoneOffset.UTC).toLocalDateTime();
//inst = dateTime.atOffset(off).withOffsetSameInstant(ZoneOffset.UTC).toInstant();
inst = dateTime.atOffset(off).toInstant();
}else if( localZone != null ){
// use specified local zone
dateTime = dateTime.atZone(localZone).toOffsetDateTime().withOffsetSameInstant(ZoneOffset.UTC).toLocalDateTime();
//dateTime = dateTime.atZone(localZone).toOffsetDateTime().withOffsetSameInstant(ZoneOffset.UTC).toLocalDateTime();
inst = dateTime.atZone(localZone).toInstant();
}else{
// no zone in input and no default zone
// treat as UTC
inst = dateTime.atOffset(ZoneOffset.UTC).toInstant();
}
DateTimeAccuracy me = new DateTimeAccuracy(dateTime);
DateTimeAccuracy me = new DateTimeAccuracy(inst);
me.accuracy = accuracy;
return me;
}
......@@ -397,7 +396,7 @@ public class DateTimeAccuracy implements Temporal, Comparable<DateTimeAccuracy>
}
@Override
public int compareTo(DateTimeAccuracy o) {
return dateTime.compareTo(o.dateTime);
return instant.compareTo(o.instant);
}
@Override
......@@ -405,7 +404,7 @@ public class DateTimeAccuracy implements Temporal, Comparable<DateTimeAccuracy>
final int prime = 37;
int result = 1;
result = prime * result + ((accuracy == null) ? 0 : accuracy.hashCode());
result = prime * result + ((dateTime == null) ? 0 : dateTime.hashCode());
result = prime * result + ((instant == null) ? 0 : instant.hashCode());
return result;
}
@Override
......@@ -414,7 +413,7 @@ public class DateTimeAccuracy implements Temporal, Comparable<DateTimeAccuracy>
if( other.getClass() != DateTimeAccuracy.class )return false;
DateTimeAccuracy o = (DateTimeAccuracy)other;
if( !o.accuracy.equals(this.accuracy) )return false;
return dateTime.equals(o.dateTime);
return instant.equals(o.instant);
}
}
......@@ -28,8 +28,6 @@ import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Hashtable;
import java.util.Map;
import java.util.logging.Logger;
......@@ -242,7 +240,7 @@ public class FlatObservationSupplier extends AbstractObservationParser implement
}
private DateTimeAccuracy getSourceDateTime(){
return new DateTimeAccuracy(LocalDateTime.ofInstant(sourceTimestamp, ZoneId.systemDefault()));
return new DateTimeAccuracy(sourceTimestamp);
}
private void lazyCreatePatient(String patientId){
if( currentPatient == null || !currentPatient.getId().equals(patientId) ){
......
......@@ -2,6 +2,7 @@ package de.sekmi.histream;
import java.text.ParseException;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.format.ResolverStyle;
......@@ -24,8 +25,9 @@ public class TestDateTimeAccuracy {
String text = "02.2003";
DateTimeAccuracy a = DateTimeAccuracy.parse(formatter, text);
Assert.assertEquals(ChronoUnit.MONTHS,a.getAccuracy());
Assert.assertEquals(2, a.get(ChronoField.MONTH_OF_YEAR));
Assert.assertEquals(2003, a.get(ChronoField.YEAR));
TemporalAccessor ac = a.toInstantMin().atOffset(ZoneOffset.UTC);
Assert.assertEquals(2, ac.get(ChronoField.MONTH_OF_YEAR));
Assert.assertEquals(2003, ac.get(ChronoField.YEAR));
}
@Test
......@@ -122,7 +124,8 @@ public class TestDateTimeAccuracy {
DateTimeAccuracy.parsePartialIso8601("2003-02-01T04:05:06Z");
DateTimeAccuracy a = DateTimeAccuracy.parsePartialIso8601("2003-02-01T04:05:06+0100");
// make sure the date is adjusted to UTC
Assert.assertEquals(3, a.get(ChronoField.HOUR_OF_DAY));
TemporalAccessor ac = a.toInstantMin().atOffset(ZoneOffset.UTC);
Assert.assertEquals(3, ac.get(ChronoField.HOUR_OF_DAY));
}
@Test
public void verifyParseExceptionBehavior(){
......
package de.sekmi.histream.impl;
import java.text.ParseException;
import java.time.ZoneOffset;
/*
* #%L
......@@ -36,9 +37,9 @@ public class TestDateTimeAccuracy {
static ChronoField[] fields = {ChronoField.YEAR, ChronoField.MONTH_OF_YEAR, ChronoField.DAY_OF_MONTH, ChronoField.HOUR_OF_DAY, ChronoField.MINUTE_OF_HOUR, ChronoField.SECOND_OF_MINUTE, ChronoField.MILLI_OF_SECOND};
private void assertFieldValues(Temporal temporal, int[] values){
private void assertFieldValues(DateTimeAccuracy a, int[] values){
for( int i=0; i<values.length; i++ ){
Assert.assertEquals(values[i], temporal.get(fields[i]));
Assert.assertEquals(values[i], a.toInstantMin().atOffset(ZoneOffset.UTC).get(fields[i]));
}
}
@Test
......
......@@ -24,6 +24,7 @@ package de.sekmi.histream.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.time.ZoneOffset;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.util.Iterator;
......@@ -77,7 +78,7 @@ public class FileObservationProviderTest {
(Observation o) -> {
Assert.assertEquals("T:date:secs", o.getConceptId());
Assert.assertEquals(ChronoUnit.SECONDS, o.getStartTime().getAccuracy());
Assert.assertEquals(3, o.getStartTime().getLong(ChronoField.SECOND_OF_MINUTE));
Assert.assertEquals(3, o.getStartTime().toInstantMin().atOffset(ZoneOffset.UTC).getLong(ChronoField.SECOND_OF_MINUTE));
Patient p = o.getExtension(Patient.class);
Assert.assertNotNull("Patient extension required", p);
Assert.assertEquals("XX12345", p.getId());
......@@ -113,27 +114,27 @@ public class FileObservationProviderTest {
(Observation o) -> {
Assert.assertEquals("T:date:mins", o.getConceptId());
Assert.assertEquals(ChronoUnit.MINUTES, o.getStartTime().getAccuracy());
Assert.assertEquals(40, o.getStartTime().getLong(ChronoField.MINUTE_OF_HOUR));
Assert.assertEquals(40, o.getStartTime().toInstantMin().atOffset(ZoneOffset.UTC).getLong(ChronoField.MINUTE_OF_HOUR));
},
(Observation o) -> {
Assert.assertEquals("T:date:hours", o.getConceptId());
Assert.assertEquals(ChronoUnit.HOURS, o.getStartTime().getAccuracy());
Assert.assertEquals(10, o.getStartTime().getLong(ChronoField.HOUR_OF_DAY));
Assert.assertEquals(10, o.getStartTime().toInstantMin().atOffset(ZoneOffset.UTC).getLong(ChronoField.HOUR_OF_DAY));
},
(Observation o) -> {
Assert.assertEquals("T:date:day", o.getConceptId());
Assert.assertEquals(ChronoUnit.DAYS, o.getStartTime().getAccuracy());
Assert.assertEquals(7, o.getStartTime().getLong(ChronoField.DAY_OF_MONTH));
Assert.assertEquals(7, o.getStartTime().toInstantMin().atOffset(ZoneOffset.UTC).getLong(ChronoField.DAY_OF_MONTH));
},
(Observation o) -> {
Assert.assertEquals("T:date:month", o.getConceptId());
Assert.assertEquals(ChronoUnit.MONTHS, o.getStartTime().getAccuracy());
Assert.assertEquals(9, o.getStartTime().getLong(ChronoField.MONTH_OF_YEAR));
Assert.assertEquals(9, o.getStartTime().toInstantMin().atOffset(ZoneOffset.UTC).getLong(ChronoField.MONTH_OF_YEAR));
},
(Observation o) -> {
Assert.assertEquals("T:date:year", o.getConceptId());
Assert.assertEquals(ChronoUnit.YEARS, o.getStartTime().getAccuracy());
Assert.assertEquals(2014, o.getStartTime().getLong(ChronoField.YEAR));
Assert.assertEquals(2014, o.getStartTime().toInstantMin().atOffset(ZoneOffset.UTC).getLong(ChronoField.YEAR));
},
(Observation o) -> {
Assert.assertEquals("T:type:str", o.getConceptId());
......@@ -158,10 +159,10 @@ public class FileObservationProviderTest {
Assert.assertEquals("mm", o.getValue().getUnits());
Assert.assertEquals(ChronoUnit.YEARS, o.getStartTime().getAccuracy());
Assert.assertEquals(2010, o.getStartTime().getLong(ChronoField.YEAR));
Assert.assertEquals(2010, o.getStartTime().toInstantMin().atOffset(ZoneOffset.UTC).getLong(ChronoField.YEAR));
Assert.assertEquals(ChronoUnit.YEARS, o.getEndTime().getAccuracy());
Assert.assertEquals(2011, o.getEndTime().getLong(ChronoField.YEAR));
Assert.assertEquals(2011, o.getEndTime().toInstantMin().atOffset(ZoneOffset.UTC).getLong(ChronoField.YEAR));
Assert.assertEquals("T:LOC", o.getLocationId());
// TODO test provider, flag
......
......@@ -159,7 +159,7 @@ public class I2b2Extractor implements ObservationSupplier {
}
Observation o = factory.getObservationFactory().createObservation(patientId, row.cid, new DateTimeAccuracy(row.start.toLocalDateTime()));
Observation o = factory.getObservationFactory().createObservation(patientId, row.cid, new DateTimeAccuracy(row.start.toInstant()));
if( patient != null ){
o.setExtension(Patient.class, patient);
}
......@@ -180,7 +180,7 @@ public class I2b2Extractor implements ObservationSupplier {
if( row.end != null ){
o.setEndTime(new DateTimeAccuracy(row.end.toLocalDateTime()));
o.setEndTime(new DateTimeAccuracy(row.end.toInstant()));
}
o.setValue(createValue(row));
if( row.lid != null ){
......
......@@ -273,7 +273,7 @@ public class I2b2Inserter extends AbstractObservationHandler implements Observat
insertFact.setString(4, dialect.encodeProviderId(o.getProviderId()));
// start_date
Objects.requireNonNull(o.getStartTime());
insertFact.setTimestamp(5, Timestamp.valueOf(o.getStartTime().getLocal()));
insertFact.setTimestamp(5, Timestamp.from(o.getStartTime().toInstantMin()));
insertFact.setString(6, (m==null)?dialect.getNullModifierCd():m.getConceptId());
insertFact.setInt(7, instanceNum);
......@@ -324,7 +324,7 @@ public class I2b2Inserter extends AbstractObservationHandler implements Observat
if( o.getEndTime() == null ){
insertFact.setTimestamp(13, null);
}else{
insertFact.setTimestamp(13, Timestamp.valueOf(o.getEndTime().getLocal()));
insertFact.setTimestamp(13, Timestamp.from(o.getEndTime().toInstantMin()));
}
// location_cd
insertFact.setString(14, dialect.encodeLocationCd(o.getLocationId()));
......
......@@ -94,7 +94,7 @@ public abstract class PostgresExtension<T> implements Extension<T> {
public static Timestamp inaccurateSqlTimestamp(DateTimeAccuracy dateTime){
if( dateTime == null )return null;
else return Timestamp.valueOf(dateTime.getLocal());
else return Timestamp.from(dateTime.toInstantMin());
}
......
......@@ -428,12 +428,12 @@ public class PostgresPatientStore extends PostgresExtension<I2b2Patient> impleme
// birth date
Timestamp ts = rs.getTimestamp(3);
if( ts != null ){
birthDate = new DateTimeAccuracy(ts.toLocalDateTime());
birthDate = new DateTimeAccuracy(ts.toInstant());
}
// death date
ts = rs.getTimestamp(4);
if( ts != null ){
deathDate = new DateTimeAccuracy(ts.toLocalDateTime());
deathDate = new DateTimeAccuracy(ts.toInstant());
}
// load sex
......
......@@ -378,12 +378,12 @@ public class PostgresVisitStore extends PostgresExtension<I2b2Visit> implements
// birth date
Timestamp ts = rs.getTimestamp(4);
if( ts != null ){
startDate = new DateTimeAccuracy(ts.toLocalDateTime());
startDate = new DateTimeAccuracy(ts.toInstant());
}
// death date
ts = rs.getTimestamp(5);
if( ts != null ){
endDate = new DateTimeAccuracy(ts.toLocalDateTime());
endDate = new DateTimeAccuracy(ts.toInstant());
}
// load sex
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment