Working with JSON Dates in ServiceNow

Date Manipulation

Handling dates is always interesting, especially when those dates come in from a different system and are represented as a string.  Right now, I can hear all of the hard core, old line programmers harrumphing that I need to get over myself because dates are just numbers.  “You can add and subtract, can’t you?”, I hear them saying with that very specific Computer Nerd condescending tone. Well, Poindexter, let me tell you, out here in the real world with real users and messy data, dates are complicated.

Let’s look at an example I recently ran into reading a JSON response in ServiceNow.  The JSON response from a REST call, had dates will looked something like this: 2017-04-26T21:00:00.000-07:00. That’s a UTC date with time zone information.  Looking through the GlideDateTime docs I saw this:  setValueUTC(String dt, String format). So far, so good, I thought.  I can give that function a date string and tell it what format it’s in. I will need to strip off the time zone information and the milliseconds at the end of the string, but that’s no big deal. Just do something like this:

gr.u_mydate.setValue(new GlideDateTime().setValueUTC(incoming_date.slice(0,-10),” yyyy-MM-dd HH:mm:ss”);

Good to go, right?  Well, not so much.   The setValueUTC doesn’t like the “T” in the format string.  My first impulse is to just strip out the “T”:

gr.u_mydate.setValue(new GlideDateTime().setValueUTC(incoming_date.slice(0,-10).replace(/T/g," "),”yyyy-MM-dd HH:mm:ss”);

That worked, but I was thinking, “What if I ever get a response that has a date in a different format?”.  I know that probably won’t happen, but you never know.  And with some tweaking I can take this from the specific problem domain into a general purpose domain.

The first thing I went looking for was a way to format dates in JavaScript.  In native JavaScript there’s not much, but in Java there is this nifty class SimpleDateFormat.  In ServiceNow you can call some Java libraries and lo and behold the SimpleDateFormat is one of them.  So now I can specify the incoming date format and tell it what the outgoing format is:

function formatDate(/*String*/ incoming_date, /*String*/ formatIn, /*String*/ formatOut) {
var inDateTimeFormat = new Packages.java.text.SimpleDateFormat(formatIn);
var parsedDate = inDateTimeFormat.parse(incoming_date);
var outDatetimeFormat = new Packages.java.text.SimpleDateFormat(formatOut);
return outDatetimeFormat.format(parsedDate).toString();
}

Let’s walk through the new function.  The first step is to create a new SimpleDateFormat object with the incoming date format (in our case that format is yyyy-MM-dd’T’HH:mm:ss.SSSXXX). Next, we parse the incoming date using the inbound form to get a Date object.  Then we create another SimpleDateFormat object using the outbound date format (in our case yyyy-MM-dd HH:mm:ss), and finally take the parsed Date object and format it using the outbound SimpleDateFormat object.

Calling the new function looks like this:

formatDate("2017-04-26T21:00:00.000-07:00", "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", "yyyy-MM-dd HH:mm:ss")

This new function works for any date format, inbound or outbound, no replacement or truncating needed.

Date handling can still be a messy business, but I think this little function takes some of the messiness out of handing differently formatted dates.