There are two interesting data types in the HL7v3 DT specification which can be used for describing sets of things, they are IVL (interval) and PIVL (periodic interval). In an attempt to make Everest data types even richer, we’ve added some functions that make dealing with these types easier.
First, lets deal with IVL. In Everest, the IVL class allows the specification of an Interval or range of values. For example, if I want to describe an interval with a range of 0 L to 10 L, I would use this code:
IVL<PQ> range = new IVL<PQ>(
new PQ(0, "L"),
new PQ(10, "L")
) { LowIncluded = true, HighIncluded = true };
Now, for example, let’s say I want to test if 1 L is a valid measure according to this range, I can use the new Contains() method:
PQ test = new PQ(1, "L");
bool isInRange = range.Contains(test); // result is true
New to Everest as well is the concept of IUnitConverters, an IUnitConverter implementation allows the PQ data type to convert values between units of measure. Since we didn’t want to infringe upon license issues we’re just including a simple SI Unit converter (that can only handle basic SI units like L, m, and g) with Everest 1.0 (that an PQ can natively convert dates/times). With an assigned unit converter, we can test if 100 mL is valid in this range:
PQ.UnitConverters.Add(new SimpleSiUnitConverter());
PQ test = new PQ(100, "mL");
bool isInRange = range.Contains(test); // result is true because 0.1 L is in range
This functionality is also extended to another quite useful class, PIVL. Before I describe PIVL, I should mention that the Contains() method on PIVL requires that the phase be translatable by the period (ie: The template parameter T must implement IPqTranslatable<T>).
PIVL allows us to repeat an interval over a specified period. This is best illustrated with time, so lets do a simple PIVL that describes Fridays between 9:00 am and 5:00 pm:
IVL<TS> nineToFive = new IVL<TS>(
DateTime.Parse("2011-09-02 09:00 AM"),
DateTime.Parse("2011-09-02 05:00 PM")
);
PIVL<TS> repeated = new PIVL<TS>(
nineToFive,
new PQ(1, "wk")
);
Notice to get the “every Friday 9 - 5″, I repeat a Friday (Fri Sept 2, 2011) every week. Now, lets test if 11:30 AM on Saturday January 1, 2000 meets the criteria of the PIVL:
TS y2kLunch = DateTime.Parse("2000-01-01 11:30 AM");
bool isIncluded = repeated.Contains(y2kLunch ); // Returns false
To get TRUE from the contains method, we’d need to pick a Friday (any Friday) in the time range specified. I’ve picked 2:15 PM on Friday, December 29, 1989:
TS randomFriday = DateTime.Parse("1989-12-29 2:15 PM");
bool b = repeated.Contains(randomFriday); // returns true
We think that by putting these functions into Everest, we’re making it more useful for developers to interact with some of the more complex data types.
One last note, the conversion functions for time were actually tricky in the PQ type. The conversions are based on the number of Ticks in each of the time units. The reason this decision was made is that a PQ instance may have no knowledge of “which” time period it is bound to (for example “1 mon” may mean 28, 30 or 31 days).
This means that PQ’s convert method is reliable for any unit where ticks are predictable (us, ms, s, min, hr, d, and wk). When ticks aren’t predictable we’ve used very basic math (example: mon = a / 12). The A (annum) value is fixed to 315,569,260,000,000 ticks (the number of ticks in a non-leap year) which means there is some drifting when calculating over very long periods of time.
Of course, it is always possible to write a better IUnitConverter for time