Written by

Question Nicky Zhu · Jan 10, 2023

How to use Regular expression to replace all ODBC datetime occurences in a String to UTC datetime format?

Hi guys,

Suppose I have a JSON string as below:

{"MessageID":"11111","save_date1":"2022-02-02 01:01:34","Sender_ID1":"esb","sent_date2":"1985-12-11 11:42:00"}

The two date variables are all formatted as ODBC date time, when I tried to import it to a %JSON.Adapter object, the date format was rejected as below

Error #9406:Unexpected format for value of field, save_date1, using class base mapping

Thus I'm trying to format all possible ODBC date time in the incoming JSON with Regular expression:

ClassMethod DateTimeFormatter(input As %String) As %String
{
    Set strTgt = input
    set r = "(([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2}))"
    set m=##class(%Regex.Matcher).%New(r, strTgt)
    while m.Locate(){
        set strTgt = m.ReplaceFirst("$2T$3Z")
        set m=##class(%Regex.Matcher).%New(r, strTgt)
    }
    Quit strTgt
}

As can be seen, so far I initialized %Regex.Matcher many times to format each of the occurences of  the ODBC dates. I wonder how may I write the regular expression or alter the loop thus I can initiate %Regex.Matcher once and format all the occurences?

Thanks.

Product version: IRIS 2022.1

Comments

Eduard Lebedyuk · Jan 10, 2023

I would not recommend regexp for that. If you have one place with such a date, you can use transient/calculated property pair:

Class User.JSON Extends (%RegisteredObject, %JSON.Adaptor)
{

Property tsjson As%String(%JSONFIELDNAME = "ts") [ Transient ];Property ts As%TimeStamp(%JSONINCLUDE = "none") [ SqlComputeCode = {set {*}=$replace({tsjson}," ", "T")_"Z"}, SqlComputed ];/// d ##class(User.JSON).Test()ClassMethod Test()
{
	set json = {"ts":"2022-02-02 01:01:34"}
	set obj = ..%New()
	zw obj.%JSONImport(json)
	w"ts:" _ obj.ts
}

}

If you have a lot of json properties,  use a custom datatype to do automatic conversion:

Class User.JSONTS Extends%Library.TimeStamp
{

ClassMethod IsValidDT(%valAs%RawString) As%Status
{
    /// replace it with a real checkq$$$OK
}

/// Converts the Objectscript value to the JSON number value.ClassMethod JSONToLogical(%valAs%Decimal) As%String [ CodeMode = generator, ServerOnly = 1 ]
{
    /// $replace({tsjson}," ", "T")_"Z"If1,($$$getClassType(%class)=$$$cCLASSCLASSTYPEDATATYPE) || $$$comMemberKeyGet(%class,$$$cCLASSparameter,"%JSONENABLED",$$$cPARAMdefault) {
        Set%codemode=$$$cMETHCODEMODEEXPRESSIONSet%code="$replace(%val,"" "", ""T"")_""Z"""
    } Else {
        Set%code=0 
    }
    Quit$$$OK
}

}

And use it instead of the standard timestamp:

Class User.JSON Extends (%RegisteredObject, %JSON.Adaptor)
{

Property ts As User.JSONTS;/// d ##class(User.JSON).Test()ClassMethod Test()
{
	set json = {"ts":"2022-02-02 01:01:34"}
	set obj = ..%New()
	zw obj.%JSONImport(json)
	w"ts:" _ obj.ts
}

}
0
Nicky Zhu  Jan 11, 2023 to Eduard Lebedyuk

Yep, that will help them. Thanks Eduard.yes

0