The TS (Time Stamp) data type is the legacy HL7 v2 timestamp. It originated in v2.1 as a date/time primitive and was the dominant timestamp type through v2.4. In v2.5 it was restructured into a composite — TS.1 carrying the date/time value (as a new primitive that later became DTM) and TS.2 carrying a degree-of-precision indicator. From v2.5.1 onwards, DTM is the preferred form for new fields, but TS remains in the standard for backward compatibility, and many real-world senders — particularly hospital information systems frozen at v2.3 or v2.4 — continue to emit TS in fields like MSH-7, EVN-2, and OBX-14.
Purpose
TS exists for two distinct reasons in modern HL7 v2 traffic. In pre-v2.5 messages, TS is the primary timestamp primitive — there is no DTM and no alternative. In v2.5+ messages, TS is a backwards-compatibility composite that allows v2.5+ receivers to keep parsing fields originally typed TS without forcing every sender to upgrade to DTM in lockstep. A v2.8.1 engine still has to be fluent in TS because legacy traffic is everywhere.
Format and constraints
TS's format depends on the version:
As a primitive (v2.1 through v2.4):
The form is YYYY[MM[DD[HH[MM[SS[.S[S[S[S]]]]]]]]][+/-ZZZZ] — identical to what DTM later standardized. The precision-truncation rule, the four-decimal-digit cap, and the +/-HHMM offset all apply exactly as for DTM.
As a composite (v2.5+):
TS.1— Time (DTM): the timestamp value itself, in the same format as DTM.TS.2— Degree of Precision: a single-character code indicating the precision of TS.1. Values:Y— YearL— Month (the L is historical; not M, to avoid colliding with Minute in earlier drafts)D— DayH— HourM— MinuteS— Second
TS.2 was deprecated and ultimately withdrawn in later v2.x revisions because the precision is already implicit in the length of TS.1; in practice many v2.5+ senders leave TS.2 empty and rely on TS.1's length to convey precision. Receivers should accept either form.
Within TS.1, the same rules as DTM apply: only digits, optional decimal point, optional +/-HHMM offset, no ISO 8601 separators, fractional seconds capped at 4 decimal places, no padding of missing components with zeros.
Where it's used
TS is found primarily in messages produced by senders on v2.3 or v2.4 profiles, and in v2.5+ messages where the receiving profile has not yet been upgraded to retype legacy fields. Common examples:
- MSH-7 — Date/Time Of Message in v2.1–v2.6 (retyped to DTM in v2.7+).
- EVN-2 / EVN-6 — Event Recorded / Event Occurred in pre-v2.5 messages.
- OBR-7 / OBR-8 — Observation Date/Time pair in pre-v2.5 messages.
- OBX-14 — Date/Time of the Observation in pre-v2.5 messages.
- ORC-9 — Date/Time of Transaction in pre-v2.5 messages.
- PV1-44 / PV1-45 — Admit Date/Time and Discharge Date/Time in pre-v2.5 messages.
- NTE-4 — comment date/time in older profiles.
In a v2.3 ADT message, every timestamp field is TS-typed; in a v2.8.1 ADT message, the same fields are DTM-typed.
Version differences
- v2.1 through v2.4 — TS is a primitive with the format
YYYY[MM[DD[HH[MM[SS[.SSSS]]]]]][+/-ZZZZ]. Used everywhere a date/time is needed. - v2.5 — TS restructured as a composite. TS.1 (new primitive
TSComponentOne, later renamed DTM) carries the value; TS.2 (degree of precision) carries the precision code. Existing fields keep type TS for compatibility. - v2.5.1 —
TSComponentOnerenamed DTM. DTM promoted to primary date/time primitive. TS retained for legacy. - v2.6 — TS.2 deprecated; precision is conveyed by the length of TS.1.
- v2.7+ — Many fields previously typed TS are retyped to DTM. TS remains defined for legacy support; conforming v2.7+ senders should emit DTM, not TS, in retyped fields.
- v2.8 / v2.8.1 / v2.8.2 — TS structure unchanged.
Common mistakes
- Emitting TS in v2.7+ messages where DTM is now required by profile. Receivers may accept it for compatibility but conformance tools will flag it.
- Populating TS.2 inconsistently with TS.1. Sending TS.1 =
20260624101500(second precision) with TS.2 =D(day precision) is an internal contradiction. - TZ stripping during routing of TS values, identical to the DTM hazard.
- Treating TS as a string field. TS in v2.5+ is a composite and must be parsed at the
^boundary; engines that grep TS values as flat strings break when TS.2 is populated. - Sending ISO 8601 inside TS.1, as for DTM.
- Synthesizing a TS.2 at the receiver that doesn't match TS.1's actual precision. If TS.2 is absent, infer from TS.1's length; don't fabricate a value.
Examples
Minimal value (primitive form, pre-v2.5):
20260624101500
Composite form with explicit precision (v2.5+):
20260624101500^S ; second precision
202606^L ; month precision
20260624^D ; day precision
Composite form with TS.2 omitted (typical v2.6+ usage):
20260624101500-0500^
Fully populated with fractional second and offset:
20260624101530.250-0500^S
In context — a v2.3 legacy MSH carrying TS in MSH-7:
MSH|^~&|EMR|MERCY|LIS|MERCY|20260624101530-0500||ADT^A04|MSG-ADT-9120|P|2.3
EVN|A04|20260624101530-0500
PID|1||MR884412^^^MERCY^MR||TESTPATIENT^ALEX^Q||19720508|F
In context — a v2.5 message using the composite form:
MSH|^~&|EMR|MERCY|LIS|MERCY|20260624101530-0500^S||ADT^A04^ADT_A01|MSG-ADT-9121|P|2.5
EVN|A04|20260624101530-0500^S
Common pitfall — TS.2 disagreeing with TS.1:
20260624101500^D ; WRONG: TS.1 is second-precision but TS.2 claims day precision
20260624^D ; correct
20260624101500^S ; correct
FHIR mapping
The v2-to-FHIR Implementation Guide publishes a per-datatype ConceptMap for TS:
datatype-ts-to-datetime— TS → FHIRdateTime. The mapping reads TS.1 (which is itself a DTM) as the value and uses TS.2 (degree of precision), when present, as a hint to set the output precision. When TS.2 is absent, precision is inferred from the length of TS.1.
For TS-as-primitive in pre-v2.5 messages, the conversion uses the value directly as if it were a DTM. The output FHIR dateTime carries the same precision and timezone offset as the source TS.
A reasonable implementation strategy is to convert every TS — primitive or composite — to a DTM-shaped intermediate at ingress, then apply the standard DTM-to-dateTime mapping. This collapses the two-flavor TS problem into a single code path.
Engine considerations
- Version-aware parsing. A TS field in a v2.3 message is a primitive; the same field in a v2.5 message is a composite. Parsers must dispatch on the message version, not just the field name.
- TS into a DTM-typed field. When a v2.5+ sender emits TS into a field that the receiver has retyped to DTM, most parsers will read TS.1 as the DTM value. Emitters should not rely on this behavior — conformance tools will flag it.
- TS.2 absence is not an error. From v2.6 onwards, TS.2 is deprecated; absence means "infer precision from TS.1's length."
- Composite delimiter collisions. TS.1 is a string of digits with an optional decimal and offset; the
^separator only appears between TS.1 and TS.2. Engines that aggressively split on^inside a flattened field name will break TS.1. - Offset preservation — identical to the DTM hazard. A TS value with
-0500that becomes2026-06-24T10:15:30Zdownstream is corrupted by 5 hours. - Legacy traffic dominance. Many production interfaces still negotiate v2.3 or v2.4 over MLLP. Don't assume v2.5+ at the boundary.
How Vorro parses and produces TS
Vorro normalizes every TS — primitive or composite — to its internal precision-tagged, offset-aware instant representation at ingress. The parser dispatches on the declared message version: in v2.4 and earlier, TS is read as a primitive; in v2.5+, TS.1 is read as a DTM and TS.2, when present, is treated as a precision hint. When TS.1's length and TS.2's code disagree, Vorro logs a soft warning, trusts TS.1's length (which is unambiguous), and routes the message to a curation queue if the discrepancy is large. Timezone offsets are always preserved.
On outbound, Vorro emits TS only when the receiving profile is pinned to a pre-v2.7 version that still uses TS in the target field; in v2.7+ profiles, Vorro emits DTM. When TS is emitted in v2.5 or v2.6, TS.2 is populated with a precision code matching the captured precision; in v2.6+, TS.2 is left empty by default unless the receiver's profile demands it. Conversion to FHIR dateTime always goes through the DTM intermediate, so the FHIR output is identical whether the source was TS or DTM.
