MyHealtheVet PHR FHIR API
0.3.9-current - ci-build
MyHealtheVet PHR FHIR API, published by VA Digital Services. This guide is not an authorized publication; it is the continuous build for version 0.3.9-current built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/department-of-veterans-affairs/mhv-fhir-phr-mapping/ and changes regularly. See the Directory of published versions
Page standards status: Informative |
There appears to be different formats of timestamps. First is Fileman Date, HL7 date time, and ClinicalProcedureTO.timestamp
For MVP we will focus on "Best Effort" translation into a FHIR DateTime datatype. The specific problem that we have is that often the data comes to us without a TimeZone, and FHIR requires that a timezone is given if a time is given. Within the source Vista it is understood what timezone would be used. Yet even a given timezone for a given Vista is not sufficient given that some Vista servers span timezones.
st6aid is the medical center divisions. under one VAMC you can have multiple divisions. kind of one to many relationship. THE PROBLEM THAT we encounter (most of the times) is that not all st6aids live under the same TZ to which their parent facilities are living. e.g. Nashville TN is in Central but Knoxville, TN is in Eastern. but Knoxville falls under Nashville. Thats why st2aid's TZ info is so vital.
Future might be different
The examples in this publication have not been adjusted to proper timezones with this logic. Thus most of the times will be "Z" time.
Input: Fileman Date
Return: FHIR DateTime
Given that the Fileman date is slightly different than HL7. The conversion is simple. The most important part is that the first three digits are the number of years since 1700.
See FileMan date
Here is XSLT
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" >
<xsl:template name="fileman-to-datetime">
<xsl:param name="fileman-date" />
<!-- only handles 3 digit year based on 1700 -->
<xsl:variable name="year" select="format-number(number(substring($fileman-date, 1, 3)) + 1700, '0000')" />
<xsl:variable name="month" select="substring($fileman-date, 4, 2)" />
<xsl:variable name="day" select="substring($fileman-date, 6, 2)" />
<xsl:choose>
<xsl:when test="not(string-length($fileman-date) > 8)">
<xsl:value-of select="concat($year, '-', $month, '-', $day)" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="time">
<xsl:value-of select="format-number(number(substring($fileman-date, 9, 2)), '00')" />
<xsl:choose>
<xsl:when test="string-length($fileman-date) > 10">
<xsl:text>:</xsl:text>
<xsl:value-of select="format-number(number(substring($fileman-date, 11, 2)), '00')" />
<xsl:choose>
<xsl:when test="string-length($fileman-date) > 12">
<xsl:text>:</xsl:text>
<xsl:value-of select="format-number(number(substring($fileman-date, 13, 2)), '00')" />
</xsl:when>
<xsl:otherwise>
<xsl:text>:00</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:text>:00:00</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="concat($year, '-', $month, '-', $day, 'T', $time, 'Z')" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:transform>
Chem-Hem literal timestamps are following HL7 and do include a timezone offset.
<reportCompleteDate>
<literal>20201029132952-0500</literal>
</reportCompleteDate>
This seems to be formatted starting with three character month:
<timestamp>DEC 2,1998@10:01:13</timestamp>
Experience with the production system there are many other date/time formats we must consider. Consider that this does not include the above formats
private static final MHVDateFormat FORMATS[] = {
new MHVDateFormat("yyyyMMddHHmmss",false),
new MHVDateFormat("yyyyMMddHHmm",false),
new MHVDateFormat("yyyyMMddHHmmssZ", false),
new MHVDateFormat("yyyyMMddHHmmZ", false),
new MHVDateFormat("yyyyMMdd", true),
new MHVDateFormat("MM/dd/yyyy", true),
new MHVDateFormat("M/d/yyyy", true),
new MHVDateFormat("MMddyyyy", true),
new MHVDateFormat("M-d-yyyy", true),
new MHVDateFormat("yyyy-MM-dd", true),
new MHVDateFormat("MMM d yyyy", true),
new MHVDateFormat("d MMM yyyy", true),
new MHVDateFormat("MMM d, yyyy", true),
new MHVDateFormat("MMM d,yyyy", true),
new MHVDateFormat("MMMMM d yyyy", true),
new MHVDateFormat("d MMMMM yyyy", true),
new MHVDateFormat("dd-MMM-yyyy", true),
new MHVDateFormat("SyyMMdd.HHmmss", false),
new MHVDateFormat("yyyyMMdd.HHmmss", false),
new MHVDateFormat("SyyMMdd.kkmmss", false),
new MHVDateFormat("MMM d,yyyy@HH:mm:ss", false),
new MHVDateFormat("MMM d,yyyy@HH:mm:ss", false),//MAR 8,2005@15:09:02 (EKG)
new MHVDateFormat("dd MMM yyyy @ HHmm", false)//21 Jun 2012 @ 1200
};
When there is no timezone, it was local time for that station on that Vista. Use the algorithm that MHV has used for many years. Based on the station, if it is known. Based on the Vista if the station is not known.