Fun with Date Formatting

As an IBM i developer using Valence you will often find opportunities to create apps containing grids with date columns.  In the RPG world, dates are typically stored in physical files using date-type fields with data in *ISO format.   So when it comes time to display those dates in your grid, it’s tempting and easy to leave them in that default format.  But not all users are as comfortable working with YYYY-MM-DD dates as we developers are, so transforming the dates into a format they’re more accustomed to may well be worth your time. It’s certainly possible to make your RPG program handle the date formatting in your app, sending the data to the browser as strings in the desired format.  But for Valence apps we generally recommend you leave the dates in *ISO format, which is the format an unmodified VVOUT uses, then let the front end handle the date formatting for the interface.  The key is making sure your front-end code is aware of the *ISO-formatted dates it will be receiving from your RPG program.

Dates are interesting animals in the JavaScript world, in that each date represents a precise moment in time measured down to the millisecond — more akin to what we think of as timestamp fields on IBM i.  A Date object in JavaScript actually consists of a large integer value that represents the number of milliseconds elapsed since midnight on January 1, 1970.   The valid range is -100,000,000 to +100,000,000 days from that date, a span of about 274,000 years, which should be just about sufficient to cover the needs of most apps (up until our sun goes supernova). Date() can be used as a constructor to create Date objects in JavaScript.  Some examples of creating a Date object variable for particular date values are: var d1 = new Date(); // sets current date/time var d2 = new Date(‘2014-03-01’); var d3 = new Date(‘March 1, 2014 13:20:00’); The date interpreter is fairly flexible.  You could abbreviate the month, truncate the year, and a number of other permutations and still get a valid Date object value (see examples here). 

There is one very important thing to keep in mind with the date assignment, though: if you do not specify a time when constructing a date, then it is assumed you mean midnight GMT.  So unless you happen to be located in the UK, this may give you unexpected results for a date, in many cases subtracting a day from the expected date.  For example, here in Chicago, which is 6 time zones west of GMT 0000, if one were to use the “d2” example above the results might be a little unexpected. Let’s try it in the browser console and see: > var d2 = new Date(‘2014-03-01’); undefined > d2 Fri Feb 28 2014 18:00:00 GMT-0600 (CST) See what happened there?  Remember, JavaScript Dates include not just a date but also a time, and since no time was included on the date assignment for d2 it assumed we meant midnight GMT.  Thus d2’s calendar date, viewed in the Central time zone of the US, is actually a day prior to what we assigned (6 hours before midnight GMT). So to work around this characteristic of JavaScript date assignment, we need to be sure we set the appropriate time-of-day in conjunction with our date. 

As with many things in JavaScript, there are all sorts of approaches to this, but our favorite is to use the Ext.Date.parse method.  This will take a date and properly parse it into a Date object using a specified date format and the local time zone (unless a specific time zone is passed, which we won’t be doing).  So back to our browser console we go to see this function in action with our *ISO date: > dt = Ext.Date.parse(‘2013-03-01’,’Y-m-d’); Fri Mar 01 2013 00:00:00 GMT-0600 (CST) Ah, that’s more like it!  Now that we have a Date object containing a date based on midnight local time, we can use a utility function to express it in any date format we like and get the results we expect. So the process of using an IBM i *ISO-formatted date variable in JavaScript entails parsing the IBM i date into a Date object variable based on the local time zone, and converting that Date object into a string in the desired format. 

Inside an Ext JS grid, you could place this logic inside a renderer in the grid view for each date column.  The code would look something like this: renderer: function(value) { var dt = Ext.Date.parse(value,’Y-m-d’);  // convert IBM i ISO date to JavaScript Date return Ext.Date.format(dt, ‘m/d/Y’);  // convert JavaScript Date to MM/DD/YYYY } Here we have the Ext.Date.parse method taking the YYYY-MM-DD value and converting it into the “dt” Date object, then we’re using Ext.Date.format to convert “dt” into a string in MM/DD/YYYY format. You could also use a similar approach to convert IBM i timestamp fields to dates.  For example, to convert a timestamp like “2014-03-01-13.45.12.025000” into a date: renderer: function(value) { var dt = Ext.Date.parse(value,’Y-m-d-H.i.s.u’); return Ext.Date.format(dt, ‘m/d/Y’); } Ext.Date.format can be used to show in a myriad of different formats using special substitution characters that represent portions of the date and time.  For example, our 2014-03-01 date could be rendered as follows: ‘m/d/Y’ = 03/01/2014 ‘d-m-Y’ = 01/03/2014 ‘j.m.y’ = 1.03.14 ‘F j, Y’ = March 1, 2014 ‘M j, Y H:i’ = Mar 1, 2014 13:45 And the formatting possibilities go far beyond these examples. 

See the Ext.Date reference for the full list of available substitution characters. Happy formatting!