ED Coder · Nov 24, 2020

Change date format in an easier way in objectscript

I am getting the date 20201121090000 in the HL7 message, How do I convert it to 2020-11-21 09:00:00 in a easy way?

I am currently doing it by extracting the first 7 values and splitting as date and time and then adding a hyphen using substring.

Is there an easier way by using $ZDATE? or something like that?

0 961
Discussion (20)1
Log in or sign up to continue

Use $tr() in backward mode

set date=" 20201121090000"
write $tr("abcd-ef-gh ij:kl:mn","abcdefghijklmn",date)  --> 2020-11-21 09:00:00

Amazing idea. Thank you Julius.

Wow, how have I not known this trick after all these years? :-) 

Wot, read documentation?? ;-)

I said nothing about a documentation. I don't do it even devil

By the way, what's the definition of an empty set?



don't know if this is faster but it may help Pass in your date ClassMethod testD(inDate As %String = "") As %String { s dd="" &SQL(SELECT TO_TIMESTAMP(:inDate,'YYYYMMDDHHMISS') INTO :dd) q dd }

set dd = $system.SQL.TOTIMESTAMP(20201121090000, "YYYYMMDDHHMISS")

Most of the SQL functions available with $SYSTEM.SQL

I think this can solve your problem

SET DATE="20201121090000"

WRITE $ZD($ZDH($E(DATE,1,8),8),3) // DAY
WRITE $E(DATE,9,10)_":"_$E(DATE,11,12)_":"_$E(DATE,13,14) // HOUR

Hey ED Coder.

There are built in classes to manage this in a nicer way.

##class(Ens.Util.Time).ConvertDateTime() is a good starting point. For example:

Here is the filled in classmethod call for easy copy/pasting:

Set NewDate = ##class(Ens.Util.Time).ConvertDateTime(HL7Date,"%Y%m%d%H%M%S","%Y-%m-%d %H:%M:%S")

The values for each section of the date are defined by the following:

After seeing several solutions I got the idea to make a comparison.
The bottom line is, it's advisable to check how an algorithm (or function or method etc.) performs over another.
So try the below program snippet... you will be surprised!

Test //
   s date="20201121090000"
   s new=""
   s t0=$zh

   f i=1:1:1E6 s new=$e(date,1,4)_"-"_$e(date,5,6)_"-"_$e(date,7,8)_" "_$e(date,9,10)_":"_$e(date,11,12)_":"_$e(date,13,14)
   s t1=$zh
   f i=1:1:1E6 s new=$tr("abcd-ef-gh ij:kl:mn","abcdefghijklmn",date)
   s t2=$zh
   f i=1:1:1E6 s new=$zd($zdh($e(date,1,8),8),3)_" "_$e(date,9,10)_":"_$e(date,11,12)_":"_$e(date,13,14)
   s t3=$zh
   f i=1:1:1E6 s new=$system.SQL.TOTIMESTAMP(date, "YYYYMMDDHHMISS") 
   s t4=$zh
   s t5=$zh

   w "$e() only",?12,t1-t0,!
   w "$tr()",?12,t2-t1,!
   w "$e()+$zd()",?12,t3-t2,!
   w "SQL/class",?12,t4-t3,!
   w "SQL/static",?12,t5-t4,!

Of course, the results will depend on hardware,  on Cache/IRIS version and on utilisation of your system

Very cool.  Certainly some cost as you work your way down the list, but for the balance of readability and performance, I prefer #2 - the $tr one.

Thank You Julius, very informative for me. Gives me an idea of the different ways I can implement the solution

Results running IRIS Container on Raspberry Pi 4 (4Gb RAM):

$e() only   1.279893

$tr()       1.281999

$e()+$zd()  1.470656

SQL/class   66.405927

I didn't include the SQL/static in my test on the RPi.

Comparison with IRIS on a Windows 10 i7 based Intel NUC machine:

$e() only   .14742
$tr()       .185998
$e()+$zd()  .182579
SQL/class   11.305143

Mind you, the NUC cost about 15 times that of the RPi :-)

Anyway, based on a combination of the performance and coolness of technique, the $tr() one gets my vote!

Notice, by the way, the hefty performance penalty incurred by the SQL/Class option compared with the low-level ObjectScript functions ($extract and $translate).  

Using $Extract will be 17 % faster (!)
Set date=20201121090000  
Set newDate=$E(date,1,4)_"-"_$E(date,5,6)_"-"_$E(date,7,8)_" "_$E(date,9,10)_":"_$E(date,11,12)_":"_$E(date,13,14)