#Health Connect

0 Followers · 609 Posts

InterSystems HealthShare Health Connect is a healthcare integration engine that delivers high-volume transaction support, process management, and monitoring to support mission-critical applications. 

At the heart of Health Connect is a high-performance, multi-model data engine that seamlessly handles multiple forms of data at high speed. Health Connect easily scales from serving small clinics to handling the transaction volumes of the largest and most complex healthcare delivery systems in the world. Capabilities include:

  • Interoperability by design
  • Mirroring with fast failover recovery
  • Source control for HL7 schemas
  • Intuitive drag-and-drop HL7 schema editing
  • A flexible, adaptable security model and more
InterSystems staff + admins Hide everywhere
Hidden post for admin
InterSystems Official Dipak Bhujbal · Nov 10, 2025

Overview

This release introduces the FHIR Server 2025.10.0, delivering the latest standards compliance and performance improvements. It also enhances the Health Connect Cloud (HCC)upgrade process for greater reliability and adds new flexibility to Network Connect through prefix list support in VPN configurations.

New Features and Enhancements

0
0 19
InterSystems Official Aya Heshmat · Mar 27, 2025 4m read

The Interoperability user interface now includes modernized user experiences for the DTL Editor and Production Configuration applications that are available for opt-in in all interoperability products. You can switch between the modernized and standard views. All other Interoperability screens remain in the Standard user interface. Please note that changes are limited to these two applications and we identify below the functionality that is currently available. 

23
4 707
Article Ashok Kumar T · Oct 20, 2025 11m read

What is XML?

XML(eXtensible Markup Language) is a flexible, text-based, andplatform-independentformat used to store and transport data in a well-structured way that is both human- and machine-readable. XML permits users to define custom tags to describe the meaning and organization of their data. For example: <book><title>The Hitchhiker's Guide</title></book>.

3
5 163
Article Theo Stolker · Feb 17, 2025 2m read

For one of our customers I had to integrate with the AFAS imageconnector endpoint /imageconnector/{imageId}?format={format}. This endpoint returns in a json message with the image as a base64-encoded string property, in addition to the mimetype for the image:

/// Image Object
Class Mycustomer.Model.AfasGet.Image Extends (%SerialObject, %XML.Adaptor, %JSON.Adaptor)
{
/// file data (base64 encoded)
Property Filedata As %String(%JSONFIELDNAME = "filedata");

/// MimeType e.g. "image/jpeg"
Property MimeType As %String(%JSONFIELDNAME = "mimetype");
}

In the Message class, we tried handling this like:

Property Image As Mycustomer.Model.AfasGet.Image;

/// AFAS GetImage response
/// get /imageconnector/{imageId}?format={format}
Method LoadFromResponse(httpResponse As %Net.HttpResponse, caller As %String = "") As %Status
{
	Set sc = $$$OK

	If $$$LOWER($Piece(httpResponse.ContentType,";",1))="application/json",httpResponse.StatusCode = "200" {
		set ..Image = ##class(Mycustomer.Model.AfasGet.Image).%New()
		set ..status = ..Image.%JSONImport(httpResponse.Data)
	}

	Return sc
}

This all worked fine until at some point the size of the filedata became larger than the $$$MaxStringLength (3641144), in which case a MAXSTRING exception was raised.

The logical next step was to change the type of the filedata property to %Stream.GlobalCharacter:

/// Image Object
Class Mycustomer.Model.AfasGet.Image Extends (%SerialObject, %XML.Adaptor, %JSON.Adaptor)
{
/// file data (base64 encoded)
Property Filedata As %Stream.GlobalCharacter(%JSONFIELDNAME = "filedata");

/// MimeType e.g. "image/jpeg"
Property MimeType As %String(%JSONFIELDNAME = "mimetype");
}

But that didn't work, %JSONImport() would still raise a MAXSTRING error.

I then tried Python, but as I am not a python wizard, I gave up on that route eventually.

Thanks to the answer from https://community.intersystems.com/user/steven-hobbs on https://community.intersystems.com/post/maxstring-trying-read-string-json-object#comment-250216, I then learned that it is possible and straightforward to retrieve json string properties into a stream using image.%Get("filedata", , "stream")):

Method LoadFromResponse(httpResponse As %Net.HttpResponse, caller As %String = "") As %Status
{
	Set sc = $$$OK

	If $$$LOWER($Piece(httpResponse.ContentType,";",1))="application/json",httpResponse.StatusCode = "200" {
		set ..Image = ##class(Mycustomer.Model.AfasGet.Image).%New()
		set image = {}.%FromJSON(httpResponse.Data)
		set ..Image.MimeType = image.mimetype
		set ..Image.Filedata = ##class(%Stream.GlobalCharacter).%New()
		do ..Image.Filedata.CopyFrom(image.%Get("filedata", , "stream"))
	}

	Return sc
}

I am still puzzled as how I would be able to instruct the %JSON.Adaptor class and use the built-in logic to map to a stream. If there is anyone out there that knows how to do this, please let me know!

3
1 283
Article Timothy Scott · Feb 28, 2025 7m read

High-Performance Message Searching in Health Connect

The Problem

Have you ever tried to do a search in Message Viewer on a busy interface and had the query time out? This can become quite a problem as the amount of data increases. For context, the instance of Health Connect I am working with does roughly 155 million Message Headers per day with 21 day message retention. To try and help with search performance, we extended the built-in SearchTable with commonly used fields in hopes that indexing these fields would result in faster query times. Despite this, we still couldn't get some of these queries to finish at all.

More Info Defining a Search Table Class.

image

For those of us working as HL7 integrators, we know that troubleshooting and responding to issues on a day-to-day basis is a huge part of our role. Quickly identifying and resolving these issues is critical to ensuring that we are maintaining the steady and accurate flow of data. Due to the poor search performance, we would have to gather very detailed information about each specific issue to find examples in Health Connect. Without a very narrow time frame (within a few minutes), we often were unable to get Message Viewer search to return any results before timing out. This caused a significant delay both in determining what the actual problem was and resolving it moving forward.

The Solution

This was not acceptable, so we had to find a solution in order to best serve our customers. Enter WRC.

image

We created a ticket, and I am happy to report a fix was identified. This fix involved going through our custom SearchTable fields and identifying which fields were not unique enough to warrant being treated as an index by the Message Viewer search.

For example, in our environment, MSH.4 (or FacilityID) is used to denote which physical hospital location the HL7 message is associated with. While this field is important to have on the SearchTable for ease of filtering, many messages come through each day for each facility. This means that it is inefficient to use this field as an index in the Message Viewer search. Counter to this would be a field like PID.18 (or Patient Account Number). The number of messages associated with each account number is very small, so using this field as an index greatly increases the speed of the search.

Adding the Unselective parameter to the appropriate items tells message search which ones to treat as indexes. This in essence modifies the SQL used to pull the messages. Below you will find the difference in queries, based on fields being used as index or not, and how you can use these queries to determine which fields should be Unselective.

Index vs NoIndex Queries

Unselective="false" (Indexed) SQL Query Plan

image

This query is looping over the SearchTable values and, for each row, cross-referencing the MessageHeader table. For a value that is unique and doesn’t have many messages associated with it (i.e. Patient Account Number), this is more efficient.

Unselective="true" (%NOINDEX) SQL Query Plan

image

This query is looping over the MessageHeader table and, for each row, cross-referencing the SearchTable values. For a value that has many results associated with it (i.e. FacilityID), this method is faster to return the results.

How to Identify Problem Fields

The best way I have found to identify which fields need to be marked as Unselective is with Show Query. Create a separate search using each field in Message Viewer (adding the SearchTable field via Add Criterion) then click Show Query to show you the actual SQL being used by Message Viewer to pull the messages based on the filters selected.

image

Our first example is using a field from the SearchTable that does not have the Unselected parameter added. Notice the EnsLib_HL7.SearchTable.PropId = 19 and EnsLib_HL7.SearchTable.PropValue = '2009036'. This indicates the SearchTable field added as a filter and what value is being checked. Keep in mind that the ProdId will be unique to each search table field and may change from environment to environment.

image

How to Add Show Query to Message Viewer

If you don’t have the Show Query button enabled in Message Viewer, you can set the following Global in your given namespace.

set ^Ens.Debug("UtilEnsMessages","sql")=1

Viewing the SQL Query Used by the Message Viewer

SQL - Unselective=“false”

SELECT TOP 100 
head.ID As ID, {fn RIGHT(%EXTERNAL(head.TimeCreated),999 )} As TimeCreated, 
head.SessionId As Session, head.Status As Status, 
CASE head.IsError 
WHEN 1 
THEN 'Error' ELSE 'OK' END As Error, head.SourceConfigName As Source, 
head.TargetConfigName As Target, head.SourceConfigName, head.TargetConfigName, 
head.MessageBodyClassName As BodyClassname, 
(SELECT LIST(PropValue) 
FROM EnsLib_HL7.SearchTable 
WHERE (head.MessageBodyId = DocId) And PropId=19) As SchTbl_FacilityID, 
EnsLib_HL7.SearchTable.PropId As SchTbl_PropId 
FROM Ens.MessageHeader head, EnsLib_HL7.SearchTable 
WHERE (((head.SourceConfigName = 'component_name' OR head.TargetConfigName = 'component_name')) 
AND head.MessageBodyClassName=(('EnsLib.HL7.Message')) 
AND (head.MessageBodyId = EnsLib_HL7.SearchTable.DocId) 
AND EnsLib_HL7.SearchTable.PropId = 19 AND EnsLib_HL7.SearchTable.PropValue = '2009036') 
ORDER BY head.ID Desc

Next, take that query into SQL and manually modify it to add %NOINDEX. This is what is telling the query to not treat this value as an index.

SQL - Unselective=”true” - %NOINDEX

SELECT TOP 100 
head.ID As ID, {fn RIGHT(%EXTERNAL(head.TimeCreated),999 )} As TimeCreated, 
head.SessionId As Session, head.Status As Status, 
CASE head.IsError 
WHEN 1 
THEN 'Error' ELSE 'OK' END As Error, head.SourceConfigName As Source, 
head.TargetConfigName As Target, head.SourceConfigName, head.TargetConfigName, 
head.MessageBodyClassName As BodyClassname, 
(SELECT LIST(PropValue) 
FROM EnsLib_HL7.SearchTable 
WHERE (head.MessageBodyId = DocId) And PropId=19) As SchTbl_FacilityID, 
EnsLib_HL7.SearchTable.PropId As SchTbl_PropId 
FROM Ens.MessageHeader head, EnsLib_HL7.SearchTable 
WHERE (((head.SourceConfigName = 'component_name' OR head.TargetConfigName = 'component_name')) 
AND head.MessageBodyClassName='EnsLib.HL7.Message' 
AND (head.MessageBodyId = EnsLib_HL7.SearchTable.DocId) 
AND EnsLib_HL7.SearchTable.PropId = 19 AND %NOINDEX EnsLib_HL7.SearchTable.PropValue = (('2009036'))) 
ORDER BY head.ID Desc

If there is a significant difference in the amount of time needed to return the first and second queries, then you have found a field that should be modified. In our case, we went from queries timing out after a few minutes to an almost instantaneous return.

Applying the Fix - Modifying Your Code

Once you have identified which fields need to be fixed, you can add the Unselective="true" to each affected Item in your custom SearchTable class. See the below example.

Custom SearchTable Class

/// Custom HL7 Search Table adds additional fields to index.
Class CustomClasses.SearchTable.CustomSearchTable Extends EnsLib.HL7.SearchTable
{

XData SearchSpec [ XMLNamespace = "http://www.intersystems.com/EnsSearchTable" ]
{
<Items>
		// Increase performance by setting Unselective="true" on fields that are not highly unique.
		// This essentially tells Message Search to not use an index on these fields.

		// facility ID in MSH.4
   		<Item DocType=""	PropName="FacilityID" Unselective="true">		[MSH:4]		</Item>
   		// Event Reason in EVN.4
   		<Item DocType=""	PropName="EventReason" Unselective="true">		[EVN:4]		</Item>
   		// Patient Account (Add PV1.19 to prebuilt PID.18 search)
   		<Item DocType=""	PropName="PatientAcct">		[PV1:19]	</Item>
   		// Document type
   		<Item DocType=""	PropName="DocumentType" Unselective="true">	[TXA:2]		</Item>
   		// Placer Order ID
   		<Item DocType=""	PropName="PlacerOrderID">	[OBR:2.1]	</Item>
   		// Filler Order ID
   		<Item DocType=""	PropName="FillerOrderID">	[OBR:3.1]	</Item>
   		// Universal Service ID
   		<Item DocType=""	PropName="ServiceID" Unselective="true">		[OBR:4.1]	</Item>
   		// Universal Service ID
   		<Item DocType=""	PropName="ProcedureName" Unselective="true">	[OBR:4.2]	</Item>		
   		// Diagnostic Service Section
   		<Item DocType=""	PropName="ServiceSectID" Unselective="true">	[OBR:24]	</Item>
   		// Appointment ID
   		<Item DocType=""	PropName="AppointmentID">	[SCH:2]		</Item>
   		// Provider Fields
   		<Item DocType=""	PropName="ProviderNameMFN">	[STF:3()]		</Item>
   		<Item DocType=""	PropName="ProviderIDsMFN">	[MFE:4().1]		</Item>
   		<Item DocType=""	PropName="ProviderIDsMFN">	[STF:1().1]		</Item>
   		<Item DocType=""	PropName="ProviderIDsMFN">	[PRA:6().1]		</Item>
	</Items>
}

Storage Default
{
<Type>%Storage.Persistent</Type>
}

}

Summary

Quick message searching is vital to day-to-day integration operations. By utilizing the Unselective property, it is now possible to maintain this functionality, despite an ever-growing database. With this quick and easy-to-implement change, you will be back on track to confidently providing service and troubleshooting issues in your Health Connect environment.

1
8 219
Announcement Larry Finlayson · Nov 3, 2025
    Using InterSystems Embedded Analytics – Virtual December 1-5, 2025

    Embed analytics capabilities in applications and create the supporting business intelligence cubes.
    This 5-day course teaches developers and business intelligence users how to embed real-time analytics capabilities in their applications using InterSystems IRIS® Business Intelligence.
    This course presents the basics of building data models from transactional data using the InterSystems IRIS BI Architect, exploring those models and building pivot tables and charts using the InterSystems IRIS BI Analyzer, as well as creating

0
0 21
Article Eric Fortenberry · Feb 19, 2025 19m read

What is TLS?

TLS, the successor to SSL, stands for Transport Layer Security and provides security (i.e. encryption and authentication) over a TCP/IP connection. If you have ever noticed the "s" on "https" URLs, you have recognized an HTTP connection "secured" by SSL/TLS. In the past, only login/authorization pages on the web would use TLS, but in today's hostile internet environment, best practice indicates that we should secure all connections with TLS.

Why use TLS?

So, why would you implement TLS for HL7 connections? As data breaches, ransomware, and vulnerabilities continue to rise, every measure you take to add security to these valuable data feeds becomes more crucial. TLS is a proven, well-understood method of protecting data in transit.

TLS provides two main features that are beneficial to us: 1) encryption and 2) authentication.

Encryption

Encryption transforms the data in transit so that only the two parties in the conversation can read/understand the information being exchanged. In most cases, only the application processes involved in the TLS connection can interpret the data being transferred. This means that any bad actors on the communicating servers or networks will not be able to read the data, even if they happen to capture the raw TCP packets with a packet sniffer (think wiretapping, wireshark, tcpdump, etc.).

Without TLS

Authentication

Authentication insures that each side is communicating with their intended party and not an impostor. By relying on the exchange of certificates (and the associated proof-of-ownership verification that occurs during a TLS handshake), when using TLS, you can be certain that you are exchanging data with a trusted party. There are several attacks that involve tricking a server into communicating with a bad actor by redirecting traffic to the wrong server (for instance, DNS and ARP poisoning). When TLS is involved, the impostors would not only have to redirect traffic, but they would also have to steal the certificates and keys belonging to the trusted party.

Authentication not only protects against intentional attacks by hackers/bad actors, but it can also protect against accidental misconfigurations that could send data to the wrong system(s). For example, if you accidentally change the IP address of an HL7 connection to a server that is not using the expected certificate, the TLS handshake will fail verification before sending any data to the incorrect server.

Host Verification

When performing verification, a client has the option of performing host verification. This verification compares the IP or hostname used in the connection with the IPs and hostnames embedded in the certificate. If enabled and the connection IP/host does not match an IP/host found in the certificate, the TLS handshake will not succeed. You can find the IPs and hostnames in the "Subject" and "Subject Alternative Name" X.509 fields that are discussed below.

Proving Ownership of a Certificate with a Private Key

To prove ownership of the certificates exchanged with TLS, you also need access to the private key tied to the public key embedded in the certificate. We won't discuss the cryptography used to prove ownership with a private key, but you need to realize that access to your certificate's private key is necessary during the TLS handshake.

Mutual TLS

With most https connections made by your web browser, only the web server's authenticity/certificate is verified. Web servers typically do not authenticate the client with certificates. Instead, most web servers rely upon application-level client authentication (login forms, cookies, passwords, etc.).

With HL7, it is preferred that both sides of the connection are authenticated. When both sides are authenticated, it is called "mutual TLS". With mutual TLS, both the server and the client exchange their certificates and the other side verifies the provided certificates before continuing with the connection and exchanging data.

X.509 Certificates

X.509 Certificate Fields

To provide encryption and authentication, information about each party's public key and identity is exchanged in X.509 certificates. Below are some of the common fields of an X.509 certificate that we will focus on:

  • Serial Number: A number unique to a CA that identifies this specific certificate
  • Subject Public Key Info: Public key of the owner
  • Subject: Distinguished name (DN) of the server/service this certificate represents
    • This can be blank, if Subject Alternative Names are provided.
  • Issuer: Distinguished name (DN) of the CA that issued/signed this certificate
  • Validity Not Before: Start date that this certificate becomes valid
  • Validity Not After: Expiration date when this certificate becomes invalid
  • Basic Constraints: Indicates whether this is a CA or not
  • Key Usage: The intended usage of the public key provided by this certificate
    • Example values: digitalSignature, contentCommitment, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, cRLSign, encipherOnly, decipherOnly
  • Extended Key Usage: Additional intended usages of the public key provided by this certificate
    • Example values: serverAuth, clientAuth, codeSigning, emailProtection, timeStamping, OCSPSigning, ipsecIKE, msCodeInd, msCodeCom, msCTLSign, msEFS
    • Both serverAuth and clientAuth usages are needed for mutual TLS connections.
  • Subject Key Identifier: Identifies the subject's public key provided by this certificate
  • Authority Key Identifier: Identifies the issuer's public key used to verify this certificate
  • Subject Alternative Name: Contains one or more alternative names for this subject
    • DNS names and IP addresses are common alternative names provided in this field.
    • Subject Alternative Name is sometimes abbreviated SAN.
    • The DNS name or IP address used in the connection should be in this list or the Subject's Common Name for host verification to be successful.

Distinguished Names

The Subject and Issuer fields of an X.509 certificate are defined as Distinguished Names (DN). Distinguished names are made up of multiple attributes, where each attribute has the format <attr>=<value>. While not an exhaustive list, here are several common attributes found in Subject and Issuer fields:

AbbreviationNameExampleNotes
CNCommon NameCN=server1.domain.comUsually, the Fully Qualified Domain Name (FQDN) of a server/service
CCountryC=USTwo-Character Country Code
STState (or Province)ST=MassachusettsFull State/Province Name
LLocalityL=CambridgeCity, County, Region, etc.
OOrganizationO=Best CorporationOrganization's Name
OUOrganizational UnitOU=FinanceDepartment, Division, etc.

Given the examples in the table above, the full DN for this example would be C=US, ST=Massachusetts, L=Cambridge, O=Best Corporation, OU=Finance, CN=server1.domain.com

Note that the Common Name found in the Subject is used during host verification and normally matches the fully qualified domain name (FQDN) of the server or service associated with the certificate. The Subject Alternative Names from the certificate can also be used during host verification.

Certificate Expiration

The Validity Not Before and Validity Not After fields in the certificate provide a range of dates, between which, the given certificate is valid.

Typically, leaf certificates are valid for a year or two (though there is a push for web sites to reduce their expiration windows to much shorter ranges). Certificate authorities tend to have an expiration window of several years.

Certificate expiration is a necessary but inconvenient feature of TLS. Before adding TLS to your HL7 connections, be sure to have a plan for replacing the certificates prior to their expiration. Once a certificate expires, you will no longer be able to establish a TLS connection with it.

X.509 Certificate Formats

These X.509 certificate fields (along with others) are arranged in ASN.1 format and typically saved to file in one of the following formats:

  • DER (binary format)
  • PEM (base64)

An example PEM-encoding of an X.509 certificate:

-----BEGIN CERTIFICATE-----
MIIEVTCCAz2gAwIBAgIQMm4hDSrdNjwKZtu3NtAA9DANBgkqhkiG9w0BAQsFADA7
MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZpY2VzMQww
CgYDVQQDEwNXUjIwHhcNMjUwMTIwMDgzNzU0WhcNMjUwNDE0MDgzNzUzWjAZMRcw
FQYDVQQDEw53d3cuZ29vZ2xlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA
BDx/pIz8HwLWsWg16BG6YqeIYBGof9fn6z6QwQ2v6skSaJ9+0UaduP4J3K61Vn2v
US108M0Uo1R1PGkTvVlo+C+jggJAMIICPDAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0l
BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU3rId2EvtObeF
NL+Beadr56BlVZYwHwYDVR0jBBgwFoAU3hse7XkV1D43JMMhu+w0OW1CsjAwWAYI
KwYBBQUHAQEETDBKMCEGCCsGAQUFBzABhhVodHRwOi8vby5wa2kuZ29vZy93cjIw
JQYIKwYBBQUHMAKGGWh0dHA6Ly9pLnBraS5nb29nL3dyMi5jcnQwGQYDVR0RBBIw
EIIOd3d3Lmdvb2dsZS5jb20wEwYDVR0gBAwwCjAIBgZngQwBAgEwNgYDVR0fBC8w
LTAroCmgJ4YlaHR0cDovL2MucGtpLmdvb2cvd3IyLzlVVmJOMHc1RTZZLmNybDCC
AQMGCisGAQQB1nkCBAIEgfQEgfEA7wB2AE51oydcmhDDOFts1N8/Uusd8OCOG41p
wLH6ZLFimjnfAAABlIMTadcAAAQDAEcwRQIgf6SEH+xVO+nGDd0wHlOyVTbmCwUH
ADj7BJaSQDR1imsCIQDjJjt0NunwXS4IVp8BP0+1sx1BH6vaxgMFOATepoVlCwB1
AObSMWNAd4zBEEEG13G5zsHSQPaWhIb7uocyHf0eN45QAAABlIMTaeUAAAQDAEYw
RAIgBNtbWviWZQGIXLj6AIEoFKYQW4pmwjEfkQfB1txFV20CIHeouBJ1pYp6HY/n
3FqtzC34hFbgdMhhzosXRC8+9qfGMA0GCSqGSIb3DQEBCwUAA4IBAQCHB09Uz2gM
A/gRNfsyUYvFJ9J2lHCaUg/FT0OncW1WYqfnYjCxTlS6agVUPV7oIsLal52ZfYZU
lNZPu3r012S9C/gIAfdmnnpJEG7QmbDQZyjF7L59nEoJ80c/D3Rdk9iH45sFIdYK
USAO1VeH6O+kAtFN5/UYxyHJB5sDJ9Cl0Y1t91O1vZ4/PFdMv0HvlTA2nyCsGHu9
9PKS0tM1+uAT6/9abtqCBgojVp6/1jpx3sx3FqMtBSiB8QhsIiMa3X0Pu4t0HZ5j
YcAkxtIVpNJ8h50L/52PySJhW4gKm77xNCnAhAYCdX0sx76eKBxB4NqMdCR945HW
tDUHX+LWiuJX
-----END CERTIFICATE-----

As you can see, PEM encoding wraps the base64-encoded ASN.1 data of the certificate with -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----.

Building Trust with Certicate Authorities

On the open internet, it would be impossible for your web browser to know about and trust every website's certificate. There are just too many!

To get around this problem, your web browser delegates trust to a pre-determined set of certificate authorities (CAs). Certificate authorities are entities which verify that a person requesting a certificate for a web site or domain actually owns and is responsible for the server, domain, or business associated with the certificate request. Once the CA has verified an owner, it is able to issue the requested certificate.

Each certificate authority is represented by one or more X.509 certificates. These CA certificates are used to sign any certificates issued by the CA. If you look in the Issuer field of an X.509 certificate, you will find a reference to the CA certificate that created and signed this certificate.

If a certificate is created without a certificate authority, the certificate is called a self-signed certificate. You know a certificate is self-signed if the Subject and Issuer fields of the certificate match.

Generally, the CA will create a self-signed root certificate with a long expiration window. This root certificate will then be used to generate a couple of intermediate certificate authorities, that have a slightly shorter expiration window. The root CA will be securely locked down and rarely be used after creating the intermediate CAs. The intermediate CAs will be used to issue and sign leaf certificates on a day-to-day basis.

The reason for creating intermediate CAs instead of using the root CA directly is to minimize impact in the case of a breach or mishandled certificate. If a single intermediate CA is compromised, the company will still have the other CAs available to continue providing service.

Certificate Chains

A connection's certificate and all of the CA certificates involved in issuing and signing this certificate can be arranged into a structure called a certificate chain. This certificate chain (as described below) will be used to verify and trust the connection's certificate.

If you follow a connection's leaf certificate to the issuing CA (using the Issuer field), and then from that CA walk to its issuer (and so on, until you reach a self-signed root certifcate) you would have walked the certificate chain.

Building a Certificate Chain

Trusting a Certificate

Your web browser and operating system typically maintains a list of trusted certificate authorities. When configuring an HL7 interface or other application, you will likely point your interface to a CA-bundle file that contains a list of trusted CAs. This file will usually contain a list of one or more CA certificates encoded in PEM format. For example:

# Maybe an Intermediate CA
-----BEGIN CERTIFICATE-----
MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
...
rqXRfboQnoZsG4q5WTP468SQvvG5
-----END CERTIFICATE-----

# Maybe the Root CA
-----BEGIN CERTIFICATE-----
MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV
...
WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
-----END CERTIFICATE-----

When your web browser (or HL7 interface) attempts to make a TLS connection, it will use this list of trusted CA certificates to determine if it trusts the certificate exchanged during the TLS handshake.

The process will start at the leaf certificate and traverse the certificate chain to next CA certificate. If the CA certificate is not found in the trust store or CA-bundle, then the leaf certificate is not trusted, and the TLS connection fails.

If the CA certificate is found in the trust store or CA-bundle file, then the process continues walking up the certificate chain, verifying that each CA along the way is in the trust store. Once the root CA certificate at the top of the chain is verified (along with all of the intermediate CA certificates along the way), the process can trust the server's leaf certificate.

Determining Trust

The TLS Handshake

To add TLS to a TCP/IP connection (such as an HL7 feed), the client and server must perform a TLS handshake after the TCP/IP connection has been established. This handshake involves agreeing on encryption ciphers/methods, agreeing on TLS version, exchanging X.509 certificates, proving ownership of these certificates, and validating that each side trusts the other.

The high-level steps of a TLS handshake are:

  1. Client makes TCP/IP connection to the server.
  2. Client starts the TLS handshake.
  3. Server sends it's certificate (and proof-of-ownership) to the client.
  4. Client verifies the server certificate.
  5. If mutual TLS, the client sends it's certificate (and proof-of-ownership) to the server.
  6. If mutual TLS, the server verifies the client certificate.
  7. Client and server send encrypted data back and forth.

TLS Handshake

1. Client makes TCP/IP connection to the server.

During step #1, the client and server perform a TCP 3-way handshake to establish a TCP/IP connection between them. In a 3-way handshake:

  1. The client sends a SYN packet.
  2. The server sends a SYN-ACK packet.
  3. The client sends an ACK packet.

Once this handshake is complete, the TCP/IP connection is established. The next step is to start the TLS handshake.

2. Client starts the TLS handshake.

After a TCP connection is established, one of the sides must act as the client and start the TLS handshake. Typically, the process that initiated the TCP connection also is responsible for initiating the TLS handshake, but this can be flipped in rare cases.

To start the TLS handshake, the client sends a ClientHello message to the server. This message contains various options used to negotiate the security settings of the connection with the server.

3. Server sends it's certificate (and proof-of-ownership) to the client.

After receiving the client's ClientHello message, the server in turn responds with a ServerHello message. This includes the negotiated security settings.

Following the ServerHello message, the server will also send a Certificate and CertificateVerify message to the client. This shares the X.509 certificate chain with the client and provides proof-of-ownership of the associated private key for the certificate.

4. Client verifies the server certificate.

Once the client receives the ServerHello, Certificate, and CertificateVerify messages, the client will verify that the certificate is valid and trusted (by comparing the CAs to trusted CA-bundle files, the operating system certificate store, or web browser certificate store). The client will also do any host verification (see above) to make sure the connection address matches the certificate addresses/IPs.

5. If mutual TLS, the client sends it's certificate (and proof-of-ownership) to the server.

If this is a mutual TLS connection (determined by the server sending a CertificateRequest message), the client will send a Certificate message including its certificate chain and then a CertificateVerify message to prove ownership of the associated private key.

6. If mutual TLS, the server verifies the client certificate.

Again, if this is a mutual TLS connection, the server will verify that certificate chain sent by the client is valid and trusted.

7. Client and server send encrypted data back and forth.

If the TLS handshake makes it this far without failing, the client and server will exchange Finished messages to complete the handshake. After this, encrypted data can be sent back-and-forth between the client and the server.

Setting Up TLS on HL7 Interfaces

Congratulations on making it this far! Now that you know about TLS, how would you go about implementing TLS on your HL7 connections? In general, here are the steps that you will need to perform to setup TLS on your HL7 connections.

  1. Choose a certificate authority.
  2. Create a key and certificate signing request.
  3. Obtain your certificate from your CA.
  4. Obtain the certificate chain for your peer.
  5. Create an SSL config for the connection.
  6. Add the SSL config to the interface, bounce the interface, and verify message flow.

1. Choose a certificate authority.

The process you use to obtain a certificate and key for your server will greatly depend upon the security policies of your company. In most scenarios, you will end up with one of the following CAs signing your certificate:

  1. An internal, company CA will sign your certificate.
  • This is my favorite option, as your company already has the infrastructure in place to maintain certificates and CAs. You just need to work with the team that owns this infrastructure to get your own certificate for your HL7 interfaces.
  1. A public CA will sign your certificate.
  • This option is nice in the sense that the public CA also has all of the infrastructure in place to maintain certificates and CAs. This option is probably overkill for most HL7 interfaces, as public CAs typically provide certificates for the open internet; HL7 interfaces tend to connect over private intranet, not the public internet.
  • Obtaining certificates from a public CA may incur a cost, as well.
  1. A CA you create and maintain will sign your certificate.
  • This option may work well for you, but unfortunately, this means you bear the burden of maintaining and securing your CA configuration and software.
  • Use at your own risk!
  • This option is the most complex. Get ready for a steep learning curve.
  • You can use open source, proven software packages for managing your CA and certificates. The OpenSSL suite is a great option. Other options are EJBCA, step-ca, and cfssl.

2. Create a key and certificate signing request.

After you have chosen your CA, your next step is to create a private key and certificate signing request (CSR). How you generate the key and CSR will depend upon your company policy and the CA that you chose. For now, we'll just talk about the steps from a high-level.

When generating a private key, the associated public key is also generated. The public key will be embedded within your CSR and your signed certificate. These two keys will be used to prove ownership of your signed certificate when establishing a TLS connection.

CAUTION! Make sure that you save your private key in a secure location (preferably in a password-protected format). If you lose this key, your certificate will no longer be usable. If someone else gains access to this key, they will be able to impersonate your server.

The certificate signing request will include information about your server, your company, your public key, how you will use the certificate, etc. It will also include proof that you own the associated private key. This CSR will then be provided to your CA to generate and sign your certificate.

NOTE: When creating the CSR, make sure that you request an Extended Key Usage of both serverAuth and clientAuth, if you are using mutual TLS. Most CAs are used to signing certificates with only serverAuth key usage. Unfortunately, this means that the certificate can not be used as a client certificate in a mutual TLS connection.

3. Obtain your certificate from your CA.

After creating your key and CSR, submit the CSR to your certificate authority. After performing several checks, your CA should be able to provide you with a signed certificate and the associated certificate chain. You will want this certificate and chain saved in PEM format. If the CA provided your certificate in a different format, you will need to convert it using a tool like OpenSSL.

4. Obtain the certificate chain for your peer.

The previous steps were focused on obtaining a certificate for your server. You should be able to use this certificate (and the associated key) with each HL7 connection to/from this server. You will also have to obtain the certificate chains for each of the systems/peers to which you will be connecting.

The certificate chains for each peer will need to be saved in a file in PEM format. This CA-bundle will not need to contain the leaf certificates; it only needs to contain the intermediate and root CA certificates.

Be sure to provide your peer with a CA-bundle containing your intermediate and root CAs. This will allow them to trust your certificate when you make a connection.

5. Create an SSL config for the connection.

In InterSystems's Health Connect, you will need to create client and server SSL configs for each system that your server will be connecting to. These SSL configs will point to the associated system's CA-bundle file and will also point to your server's key and certificate files.

Client SSL configs are used on operations to initiate the TLS handshake. Server SSL configs are used on services to respond to TLS handshakes. If a system has both inbound services and outbound operations, you will need to configure both a client and server SSL config for that system.

To create a client SSL config:

  1. Go to System Administration > Security > SSL/TLS Configurations.
  2. Click Create New Configuration.
  3. Give your SSL configuration a Configuration Name and Description.
  4. Make sure your SSL configuration is Enabled.
  5. Choose Client as the Type.
  6. Choose Require for the Server certificate verification field. This performs host verification on the connection.
  7. Point File containing trusted Certificate Authority certificate(s) to the CA-bundle file that contains the intermediate and root CAs (in PEM format) for the system to which you are connecting.
  8. Point File containing this client's certificate to the file that holds your server's X.509 certificate in PEM format.
  9. Point File containing associated private key to the file containing your certificate's private key.
  10. Private key type will most likely be RSA. This should match the type of your private key.
  11. If you private key is password protected (as it should be), fill in the password in both the Private key password and Private key password (confirm) fields.
  12. You likely can leave the other fields to their default values.

To create a server SSL config:

  1. Go to System Administration > Security > SSL/TLS Configurations.
  2. Click Create New Configuration.
  3. Give your SSL configuration a Configuration Name and Description.
  4. Make sure your SSL configuration is Enabled.
  5. Choose Server as the Type.
  6. Choose Require for the Client certificate verification field. This will make sure that mutual TLS is performed.
  7. Point File containing trusted Certificate Authority certificate(s) to the CA-bundle file that contains the intermediate and root CAs (in PEM format) for the system to which you are connecting.
  8. Point File containing this server's certificate to the file that holds your server's X.509 certificate in PEM format.
  9. Point File containing associated private key to the file containing your certificate's private key.
  10. Private key type will most likely be RSA. This should match the type of your private key.
  11. If you private key is password protected (as it should be), fill in the password in both the Private key password and Private key password (confirm) fields.
  12. You likely can leave the other fields to their default values.

Creating SSL Configs

6. Add the SSL config to the interface, bounce the interface, and verify message flow.

Once you've created the client and server SSL configs, you are ready to activate TLS on the interfaces. On each service or operation, select the associated SSL config on the Connection Settings > SSL Configuration dropdown found on the Settings tab of the interface.

After bouncing the interface, you should see the connection reestablish. When a new message is tranferred, a Completed status indicates that TLS is working. If TLS is not working, every time a message is attempted, the connection will drop.

To help debug issues with TLS, you may need to use tools such as tcpdump, Wireshark, or OpenSSL's s_client utility.

Summary

This has been a very long deep-dive into the topic of SSL/TLS. There is so much more information that was not included in this article. Hopefully, this has provided you with enough of an overview of how TLS works that you can research the details and learn more information as needed.

If you are looking for an in-depth resource on TLS, check out Ivan Ristić's website, fiestyduck.com and book, Bulletproof TLS and PKI. I have found this book to be a great resource for learning more about the details of TLS.

1
6 466
Question Scott Roth · Oct 24, 2025

According to the Documentation  EnsLib.Workflow.TaskRequest has the following fields...

  • %Action
  • %Command
  • %FormFields
  • %FormTemplate
  • %FormValues
  • %Message
  • %Priority
  • %Subjext
  • %TaskHandler
  • %Title
  • %UserName

I want to be able to capture the Source, Session ID, and any other Identifiers outside of the Error so it will show up on the Task List.

I am struggling how to build a csp template for me to be able to capture additional fields to send to the Workflow Operation.

0
0 30
InterSystems Official Dipak Bhujbal · Oct 24, 2025

Overview 

This release focuses on upgrade reliability, security expansion, and support experience improvements across multiple InterSystems Cloud Services. With this version, all major offerings—including FHIR Server, InterSystems Data Fabric Studio (IDS), IDS with Supply Chain, and IRIS Managed Services—now support Advanced Security, providing a unified and enhanced security posture. 

New Features and Enhancements 

0
0 60
InterSystems Official Daniel Palevski · Oct 22, 2025

The 2025.1.2 and 2024.1.5 maintenance releases of InterSystems IRIS® data platform, InterSystems IRIS® for HealthTM, and HealthShare® Health Connect are now Generally Available (GA). These releases include the fixes for a number of recently issued alerts and advisories, including the following: 

0
0 59
Article Sanjib Pandey · Oct 17, 2025 13m read

Overview

This web interface is designed to facilitate the management of Data Lookup Tables via a user-friendly web page. It is particularly useful when your lookup table values are large, dynamic, and frequently changing. By granting end-users controlled access to this web interface (read, write, and delete permissions limited to this page), they can efficiently manage lookup table data according to their needs.

The data managed through this interface can be seamlessly utilized in HealthConnect rules or data transformations, eliminating the need for constant manual monitoring and management of the lookup tables and thereby saving significant time.

Note:
If the standard Data Lookup Table does not meet your mapping requirements, you can create a custom table and adapt this web interface along with its supporting class with minimal modifications. Sample class code is available upon request.

0
1 59
Question Mark OReilly · Oct 8, 2025

Hi:

I see a lot of cool REST apps and i'm trying to host something in the TIE using REST/Axios with VITE. 

At the moment i will probably host the application in web applications in Intersytems. 

For authorisation and getting the logged in user and password to any app, is there a standard people are doing? 

I.e. for axios you might have this from the app

auth: {
        username: apiUser,
        password: apiPass
      }
8
0 111
Article Cecilia Yang · Oct 10, 2025 2m read

To manage the accumulation of production data, InterSystems IRIS enables users to manage the database size by periodically purging the data. This purge can apply to messages, logs, business processes, and managed alerts.

Please check the documentation for more details on the settings of the purge task:
https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=EGMG_purge#EGMG_purge_settings

0
0 44
Article Ariel Glikman · Sep 16, 2025 14m read

One of the recommendations when deploying InterSystems Technologies for production is to set up High Availability. The recommended API Manager for these InterSystems Technologies is the InterSystems API Manager (IAM). IAM (essentially Kong Gateway) has multiple deployment topologies.

If you are looking for high availability you could use:

a) Kong Traditional Mode: Multiple Node Clusters

b) Hybrid Mode

c) DB-less Mode

Before we break them down let's first understand the out of the box deployment that is provided by InterSystems: Installing IAM Version 3.10.

Kong Traditional Mode

2
3 112
Article Luis Angel Pérez Ramos · Sep 30, 2025 11m read

Welcome, dear members of the Community!

In this article, we will present an example of a project implementing a FHIR-based solution. This project will be based on the national project (Spanish national project), known as ÚNICAS.

What is ÚNICAS?

In his own words:

A project whose objective is to create an ecosystem of partnerships to improve healthcare for pediatric patients with complex rare diseases (RMDs). This project is being implemented through the network within the National Health System (NHS) to improve the diagnosis and care of patients with rare diseases.

2
0 72
Question Martin Staudigel · Sep 17, 2025

Hello community,

is anybody located in the DACH area healthcare sector working with Dedalus Orbis as patient master and uses a custom HL7 schema for parsing Orbis message structures into Health Connect?

We're facing a migration and I ask myself if I have to create a schema by myself, based on the pdf documentation given by the company. This is a tedious task,  so hopefully there is somebody out there willing to share his or her experience.

Kind regards,

Martin 

2
0 55
Article Sanjib Pandey · Sep 26, 2025 19m read

Introduction

HL7 messages often contain multiple repeating segments such as NTE, AL1, OBX, ZTX, DG1, and others. These segments sometimes require individual processing and routing to different downstream systems. This technical paper introduces a configurable template designed to automate the splitting of these repeating HL7 segments, improving message handling and integration efficiency.

3
0 76
Announcement Kristina Lauer · Sep 29, 2025

Hi, Community!

🔥Does your organization work with HL7® FHIR® resources and need training, now or in the future?

Learning Services is exploring whether to create a new instructor-led course on FHIR support in InterSystems IRIS® for Health and HealthShare® Health Connect.

Need FHIR Training? Take the survey.

If you’re involved in approving or recommending training for your team, we’d love your input! Please take a few minutes to complete this short survey.

Your feedback will help us understand both current and future demand so we can build training that supports your needs.

Thanks in advance for sharing your perspective!

👉Take the survey.

0
0 37
Article Jordan Simpson · Sep 26, 2025 2m read

Hi,

Just thought I'd share quite a handy hook that has helped me out when developing on Health Connect Cloud with VS Code and GitBash. When developing on Health Connect Cloud, if changes are made directly on the server such as routing rules or component deployments, they aren't automatically included in source control, therefore you must export from the server into your local files and push to your remote repo. I'm sure there are easier methods to deal with that which I'm in the process of testing, but as a quick solution I thought it would be handy have a pre-commit hook which triggers a reminder in GitBash - see below.

1
1 123
Article Padmaja Konduru · Jan 14, 2025 2m read

The utility returns the desired values from the text and display the multiple values if exists based on starting and ending string.

Class Test.Utility.FunctionSet Extends %RegisteredObject
{

/// W !,##class(Test.Utility.FunctionSet).ExtractValues("Some random text VALUE=12345; some other VALUE=2345; more text VALUE=345678;","VALUE=",";")
 

4
1 229
Article Eric Fortenberry · Dec 20, 2024 9m read

Your Mission

Let's pretend for a moment that you're an international action spy who's dedicated your life to keeping the people of the world safe from danger. You recieve the following mission:

Good day, Agent IRIS,

We're sorry for interrupting your vacation in the Bahamas, but we just received word from our London agent that a "time bomb" is set to detonate in a highly populated area in Los Angeles. Our sources say that the "time bomb" is set to trigger at 3:14 PM this afternoon.

Hurry, the people are counting on you!

The Problem

You rush to your feet and get ready to head to Los Angeles, but you quickly realize that you're missing a key piece of information; will the "time bomb" trigger at 3:14 PM Bahama-time or at 3:14 PM Los Angeles-time? ...or maybe even 3:14 PM London-time.

You quickly realize that the time you were provided (3:14 PM) does not give you enough information to determine when you need to be in Los Angeles.

The time you were provided (3:14 PM) was ambiguous. You need more information to determine an exact time.

Some Solutions

As you think over the problem, you realize there are methods of overcoming the ambiguity of time that you were provided:

  1. Your source could have provided the location to which the local time was 3:14 PM. For instance, Los Angeles, Bahamas, or London.

  2. Your source could have used a standard such as UTC (Coordinated Universal Time) to provide you an offset from an agreed-upon location (such as Greenwich, London).

The Happy Ending

You call your source and confirm that the time provided was indeed 3:14 PM Los Angeles-time. You are able to travel to Los Angeles, disarm the "time bomb" before 3:14 PM, and quickly return to the Bahamas to finish your vacation.

The Point

So, what is the point of this thought exercise? I doubt that any of us will encounter the problem presented above, but if you work with an application or code that moves data from one location to another (especially if the locations are in different time zones), you need to be aware of how to handle datetimes and time zones.

Time Zones are HARD!

Well, time zones aren't so bad. Daylight savings time and political boundaries make time zones difficult.

I thought I always understood the "general" idea of time zones: the planet is split into vertical slices by time zone, where each time zone is one hour behind the time zone to the East.

Simplification of time zones on a world map

While this simplification holds for many locations, unfortunately there are many exceptions to this rule.

Time zones of the world (Wikipedia) Reference: Time zones of the world (Wikipedia)

Standardizing with UTC (the "Origin")

To simplify the language of conveying specific times, the world has settled on using UTC (Coordinated Universal Time). This standard sets the "origin" to the 0° longitude that goes through Greenwich, London.

Defining "Offset"

Using UTC as the basis, all other time zones can be defined relative to UTC. This relationship is referred to as the UTC offset.

If you have a local time and an offset, you no longer have an ambiguous time (as seen in our spy example above); you have a definite and specific time with no ambiguity.

The typical format used to show the UTC offset is ±HHMM[SS[.ffffff]].

  • A minus - sign indicates an offset to the West of UTC.
  • A plus + sign indicates an offset to the East of UTC.
  • HH indicates hours (zero-padded)
  • MM indicates minutes (zero-padded)
  • SS indicates seconds (zero-padded)
  • .ffffff indicates fractional seconds

For example, in America, the Eastern Standard Zime Zone (EST) is defined as -0500 UTC. This means that all locations in EST are 5 hours behind UTC. If the time is 9:00 PM at UTC, then the local time in EST is 4:00 PM.

In the Australian Central Western Standard Time Zone (ACWST), the offset is defined as +0845 UTC. If the time is 1:00 AM at UTC, then the local time in ACWST is 9:45 AM.

Daylight Savings Time

So, back to the time zone maps above. From the image, you can see that many time zones follow the political boundaries of countries and regions. This complicates time zone calculations slightly, but it is easy enough to wrap your mind around.

Unfortunately, there is one more factor to consider when working with times and time zones.

Let's look at Los Angeles.

On the map, the UTC offset for Los Angeles is -8 in Standard Time. Standard Time is typically followed during the winter months, whereas Daylight Savings Time is typically followed during the summer months.

Daylight Savings Time (DST) advances the clocks in a give time zone forward (typically by one hour during the summer months). There are several reasons that political regions might choose to follow DST (such as energy savings, better use of daylight, etc.). The difficulty and complexity of Daylight Savings Time is that DST is not consistently followed around the world. Depending on your location, your region may or may not follow DST.

Time Zone Database

Since the combination of political boundaries and Daylight Savings Time greatly increases the complexity of determining a specific time, a time zone database is needed to correctly map local times to specific times relative to UTC. The Internet Assigned Numbers Authority (IANA) Time Zone Database is the common source of time zone information used by operating systems and programming languages.

The database includes the names and aliases of all time zones, information about the offset, information about the use of Daylight Savings Time, time zone abbreviations, and which date ranges the various rules apply.

Copies of and information about the time zone database can be found on IANA's website.

Most UNIX systems have a copy of the database that gets updated with the operating system's package manager (typically installed in /usr/share/zoneinfo). Some programming languages have the database built-in. Others make it available by a library or can read the system's copy of the database.

Time Zone Names/Identifiers

The time zone database contains many names and aliases for specific time zones. Many of the entries include a country (or continent) and major city in the name. For example:

  • America/New_York
  • America/Los_Angeles
  • Europe/Rome
  • Australia/Melbourne

Conversion and Formatting Using ObjectScript

So, now we know about:

  • Local times (ambiguous times without an offset or location)
  • UTC offsets (the relative offset a timestamp or location is from the UTC "origin" in Greenwich, London)
  • Daylight Savings Time (an attempt at helping civilization at the expense of time zone offsets)
  • Time zone database (which includes information about time zones and Daylight Savings observance in many locations and regions)

Knowing this, how do we work with datetimes/time zones in ObjectScript?

***Note: I believe all the following statements are true about ObjectScript, but please let me know if I misstate how ObjectScript works with time zones and offsets.

Built-in Variables and Functions

If you need to convert timestamps between various formats within the system time zone of the process running IRIS, the built-in features of ObjectScript should be sufficient. Here is a brief listing of various time-related variables/functions in ObjectScript:

  • $ZTIMESTAMP / $ZTS

    • IRIS Internal format as a UTC value (offset +0000).
    • Format: ddddd,sssss.fffffff
  • $NOW(tzmins)

    • Current system local time with the given tzmins offset from UTC.
    • Does not take Daylight Savings Time into account.
    • By default, tzmins is based off of the $ZTIMEZONE variable.
    • Format: ddddd,sssss.fffffff
  • $HOROLOG

    • Current system local time (based on $ZTIMEZONE), taking Daylight Savings Time into account.
    • Format: ddddd,sssss.fffffff
  • $ZTIMEZONE

    • Returns or sets the system's local UTC offset in minutes.
  • $ZDATETIME() / $ZDT()

    • Converts $HOROLOG format to a specific display format.
    • Can be used to convert from system local time to UTC (+0000).
  • $ZDATETIMEH() / $ZDTH()

    • Converts a datetime string to internal $HOROLOG format.
    • Can be used to convert from UTC (+0000) to system local time.

As best as I can tell, these functions are only able to manipulate datetimes using the time zone of the local system. There does not appear to be a way to work with arbitrary time zones in ObjectScript.

Enter the tz Library on Open Exchange

To accommodate conversion to and from arbitrary time zones, I worked to create the tz - ObjectScript Time Zone Conversion Library.

This library accesses the time zone database installed on your system to provide support for converting timestamps between time zones and formats.

For instance, if you have time local to Los Angeles (America/Los_Angeles), you can convert it to the time zone used in the Bahamas (America/New_York) or the time zone used in London (Europe/London):

USER>zw ##class(tz.Ens).TZ("2024-12-20 3:14 PM", "America/Los_Angeles", "America/New_York")
"2024-12-20 06:14 PM"

USER>zw ##class(tz.Ens).TZ("2024-12-20 3:14 PM", "America/Los_Angeles", "Europe/London")
"2024-12-20 11:14 PM"

If you are given a timestamp with an offset, you can convert it to the local time in Eucla, Australia (Australia/Eucla), even if you don't know the original time zone:

USER>zw ##class(tz.Ens).TZ("2024-12-20 08:00 PM -0500", "Australia/Eucla")
"2024-12-21 09:45 AM +0845"

If you work with HL7 messages, the tz library has several methods exposed to Interoperability Rules and DTLs to help you easily convert between time zones, local times, times with offsets, etc.:

// Convert local time from one time zone to another 	 
set datetime = "20240102033045"
set newDatetime = ##class(tz.Ens).TZ(datetime,"America/New_York","America/Chicago")

// Convert local time to offset 	 
set datetime = "20240102033045"
set newDatetime = ##class(tz.Ens).TZOffset(datetime,"America/Chicago","America/New_York")

// Convert offset to local time 	 
set datetime = "20240102033045-0500"
set newDatetime = ##class(tz.Ens).TZLocal(datetime,"America/Chicago")

// Convert to a non-HL7 format 	 
set datetime = "20240102033045-0500"
set newDatetime = ##class(tz.Ens).TZ(datetime,"America/Chicago",,"%m/%d/%Y %H:%M:%S %z")

Summary

I appreciate you following me on this "international journey" where we encountered time zones, Daylight Savings Time, world maps, and "time bombs". Hopefully, this was able to shed some light on (and simplify) many of the complexities of working with datetimes and time zones.

Check out tz - ObjectScript Time Zone Conversion Library and let me know if you have any questions (or corrections/clarifications to something I said).

Thanks!

References/Interesting Links

4
5 441
Announcement Kimi Niittyniemi · Sep 14, 2025

We are excited to announce the general availability of JediSoft IRISsync®, our new synchronization and comparison solution built on InterSystems IRIS technology.  IRISsync makes it easy to synchronize and compare IRIS instances.

IRISsync was voted runner-up in the "Most Likely to Use" category at InterSystems READY 2025 Demos and Drinks.

A huge thanks to everyone who supported us — we’re thrilled to see IRISsync resonating with the InterSystems user community!

0
0 74
Question Scott Roth · Sep 8, 2025

We currently have Business Operation that we built to use the EnsLib.SQL.OutboundAdapter so we can make Microsoft SQL Server Stored Procedure calls. The BO is attached to a Java Gateway Service.

Some of our MS SQL Databases have moved from being OnPrem to Azure Cloud. We have started seeing where we are receiving errors on the BO saying that we cannot connect to the Azure Database, but we never receive a Disconnect from the Azure Database.

2
0 37
Article Ashok Kumar T · Sep 8, 2025 19m read

FHIR Server

A FHIR Server is a software application that implements the FHIR (Fast Healthcare Interoperability Resources) standard, enabling healthcare systems to store, access, exchange, and manage healthcare data in a standardized manner.

Intersystems IRIS can store and retrieve the following FHIR resources:

  • Resource Repository – IRIS Native FHIR server can effortlessly store the FHIR bundles/resources directly in the FHIR repository.
  • FHIR Facade - the FHIR facade layer is a software architecture pattern used to expose a FHIR-compliant API on top of an existing one (often non-FHIR). It also streamlines the healthcare data system, including an electronic health record (EHR), legacy database, or HL7 v2 message store, without requiring the migration of all data into a FHIR-native system.

What is FHIR?

Fast Healthcare Interoperability Resources (FHIR) is a standardized framework created by HL7 International to facilitate the exchange of healthcare data in a flexible, developer-friendly, and modern way. It leverages contemporary web technologies to ensure seamless integration and communication across various healthcare systems.

0
3 224