Birthdate conversion seems to lose time and zone information

235 views
Skip to first unread message

bobsl...@gmail.com

unread,
Jan 13, 2016, 4:51:49 AM1/13/16
to HAPI FHIR
I've put a patient as subject into a composition like this:

Patient patient = new Patient();
String BIRTHDATE = "19811018083212";
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");

    final Date date = sdf.parse(BIRTHDATE);    
    patient.setBirthDate(new DateDt(date));
compositionBuilder.getComposition().setSubject(new ResourceReferenceDt(patient));

Debugging into this composition I find a fastTime of 372238332000 representing the date 19811018083212 in milliseconds (mySubject -> myResource -> mybirthdate -> myCoercedValue). Time zone is properly filled (myTimeZone).
Now I put this composition into a REST-call and debug into it again on server side finding the amount of milliseconds reduced by the amount representing the time, now 372207600000 (means date 19811018000000). Time zone is null now.

I am wondering if this behaviour would cause any problems in the meaning of having the birthdate changed by one day in cases where server and client are located in different time zones. Or am I missing something?

James Agnew

unread,
Jan 13, 2016, 10:06:51 AM1/13/16
to bobsl...@gmail.com, HAPI FHIR
Hi there,

Thinking about this, I think you're right. It could in theory cause an issue.

The FHIR data datatype is serialized over the wire as yyyyMMdd only, and never gets serialized with a time or timezone. So, when you feed it the fast-time of 372238332000 you're actually giving it more precision than it needs. DateDt simply figures out what Y/M/D that fast-time represents in the system local timezone and converts it to that representation.

Then as the date goes over the wire to your server it's just represented as the string "19811018", so when you again pull it out as a fast-time it has lost the additional precision you fed in.

An example of where I could see the type of thing you're describing causing an issue would be this: Suppose a FHIR system is running in Toronto. It has a date/time/timezone of birth for someone who was born at 01:00 in London (which is 20:00 the day before in Toronto), stored as a Java Date (with a timezone stored separately). If someone were to create a DateDt using that Date object on the server running in Toronto, it's going to end up serializing it as the day before the day the patient was actually born in their local timezone.

So, I wonder what's the right thing to do here? The HAPI primitive datatypes all have a Java type that they use internally as their "native" representation. We could certainly switch DateDt to use GregorianCalendar instead of Date. Another option might just be to add constructors which take in Calendar objects and maybe just a few ints (year, month, date). I guess at a minimum better documentation on DateDt about this risk would be a good thing.

Anyone have any opinions?

Cheers,
James



--
You received this message because you are subscribed to the Google Groups "HAPI FHIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hapi-fhir+...@googlegroups.com.
To post to this group, send email to hapi...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/hapi-fhir/f272f399-7e46-4347-8a6a-0f01b2660373%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alexander Kley

unread,
Jan 13, 2016, 10:19:56 AM1/13/16
to HAPI FHIR
Hi guys,

really teh parsing ist strange:

I set birthdate on patient with some code snip:

 final Calendar cal = Calendar.getInstance();
 cal.setTimeZone(TimeZone.getTimeZone("UTC"));
 cal.set(1990, Calendar.JANUARY, 1, 0, 0, 0);
 patient.setBirthDate(new DateDt(cal.getTime()));

pat.getBirthDate().getTime() is 631152000030

The xml parse creates: <birthDate value="1990-01-01"/>
The reverse parsing to patient resource change the long to 631148400000 - Thats a bug, because this long is 31 Dec 1989 23:00:00 GMT (UTC)

@ James:
So I think the error located in the parsing of xml/json string value to java.util.date, the inner type if DateDt.
If you convert the String  to date, you must notice the local timezone where HAPI is running. And I think, that does not happen.

Concat birthDate value with "00:00:00.000", parse to java.util.Calendar and set timezone to UTC like cal.setTimeZone(TimeZone.getTimeZone("UTC"));

I think thats it!

Cheers,
Alex

Kevin Mayfield

unread,
Jan 13, 2016, 10:29:42 AM1/13/16
to James Agnew, bobsl...@gmail.com, HAPI FHIR
When I've dealt with this previously (military health system) you end up two date of births. 

A short form which is just dd/MM/yyyy which has no timezone and so doesn't change with timezone (as per the Patient resource).

The second date of birth is a full datetime including timezone, this is the clinical event



James Agnew

unread,
Jan 13, 2016, 11:34:11 AM1/13/16
to Kevin Mayfield, bobsl...@gmail.com, HAPI FHIR
> When I've dealt with this previously (military health system) you end up two date of births.

For what it's worth, FHIR does support both of those concepts. Patient.birthDate is intended to be the "short form" one, where it represents only the Y/M/D for the patient and is understood to represent the date wherever the person was when they were born. FHIR also defines an extension called "birthTime" that can be used to represent the clinical event version (point in time with a timezone) if that is needed. So this issue really stems from us using a native type (Java Date, which is point in time with no timezone) which has more precision than the concept it's trying to convey (FHIR date, which is Y/M/D with no timezone).

I replicated Alex's code and I do also see the same behaviour here. Ultimately I think there are two issues here:

1. The constructor for DateDt (and for that matter, any of the other date/time types) doesn't accept a TimeZone. Alex's issue would be solved if he passed in TimeZone.getTimeZone("UTC") to the date instance.
2. The serialization in BaseDateTimeDt needs to respect the timezone even when serializing a date/time that doesn't include a time component. (e.g. if we have a Date that represents midnight on some date UTC, we need to serialize the Y/M/D part of that date using UTC as the timezone).

I also wonder if DateDt should switch to using String as its native type. Date seems misleading for this purpose...

Cheers,
James

Bob Dannehl

unread,
Jan 13, 2016, 11:48:49 AM1/13/16
to HAPI FHIR, mayfiel...@gmail.com, bobsl...@gmail.com
Hi James,
your last sentence describes exactly what I had in mind when I first got in contact with this issue yesterday. In my opinion a patients birthdate is a fixed value irrespective of a servers location, therefore more a String than a (time zone dependent) date.

Best regards,
bob

Alexander Kley

unread,
Jan 13, 2016, 12:04:34 PM1/13/16
to HAPI FHIR, mayfiel...@gmail.com, bobsl...@gmail.com
James, I think you missunderstood me. I think the problem is located on HAPI's XmlParser birthdate create block. The XmlParser got a string with attribute birthdate and value "1990-01-01". So what does the XmlParser? Notice the XmlParser the local timezone or set it to UTC ? I think it's doesn't set the UTC timezone explicit.
So what can do the
XmlParser to create a Date without time component? Set to zero. But if the XmlParser is setting the time component to zero the util.Date parse method get the local timezone from jvm. If XmlParser doesn't set to UTC explicit, the unix timestamp is changed, and XmlParser created a different (wrong) date value.
Thats my oppinion. Please correct my if I'm wrong!


Cheers,
Alex



Am Mittwoch, 13. Januar 2016 17:34:11 UTC+1 schrieb James Agnew:

Alexander Kley

unread,
Jan 13, 2016, 12:15:43 PM1/13/16
to HAPI FHIR, mayfiel...@gmail.com, bobsl...@gmail.com
By the way I think DateDt serialization in general is affected. The handling as String-only like Bob's proposal seems to be a good idea.


Cheers,
Alex

Am Mittwoch, 13. Januar 2016 17:34:11 UTC+1 schrieb James Agnew:

James Agnew

unread,
Jan 13, 2016, 2:09:07 PM1/13/16
to Alexander Kley, HAPI FHIR, Kevin Mayfield, bobsl...@gmail.com
Hi Alex,

The distinction here is that it's not actually the XmlParser or JsonParser that handle serialization for date/times. It's actually the BaseDateTimeDt.getValueAsString() method and BaseDateTimeDt.setValueAsString(String).. So ultimately the fix for this issue needs to be in that class.

I am going to have a go at switching DateDt to use a String.

Cheers,
James

Alexander Kley

unread,
Jan 14, 2016, 2:35:06 AM1/14/16
to HAPI FHIR, alexand...@gmail.com, mayfiel...@gmail.com, bobsl...@gmail.com
Hi James,

Ok, it was not entirely clear which class is involved. But your proposal seems to be a good idea to solve the problem.
But I'm wondering why the problem has not already occurred earlier.

Cheers,
Alex
Reply all
Reply to author
Forward
0 new messages