0

I have some data coming as a timestamp so I need to format it before it goes to the end user. I didn't found any way to achieve this using a predefined formatter from jQgrid.

Having said that I am trying to use a mix of "native" Javascript and MomentJS to format the data before display it.

The first thing I did was load the library momentjs before load jqgrid:

<script src="js/jquery-3.2.1.min.js" type="text/javascript"></script>
<script src="js/jquery-migrate-3.0.1.min.js" type="text/javascript"></script>
<script src="js/moment.min.2.20.1.js" type="text/javascript"></script>
<script src="js/free-jqgrid/jquery.jqgrid.min.js" type="text/javascript"></script>

Next I have created a custom formatter to be used in that column:

$.extend($.fn.fmatter, {
    customTimestampToDate: function (cellvalue, options, rowdata) {
        var parsed_timestamp = parseInt(rowdata.timestamp),
            tmp = new Date(parsed_timestamp * 1000).toISOString();

        console.log(typeof cellvalue); // logs string
        console.log(typeof rowdata.timestamp); // logs string
        console.log(typeof parsed_timestamp); // logs "number"
        console.log(tmp); // logs 2018-01-15T14:19:28.000Z

        return moment(tmp);
    }
});

Last I have tried to use the custom formatter in the colModel:

colModel: [
    {name: "act", template: "actions", width: 115},
    {name: "username", search: true, stype: "text"},
    {name: "email", search: true, stype: "text"},
    {name: "first_name", search: true, stype: "text"},
    {name: "last_name", search: true, stype: "text"},
    {name: "company", search: true, stype: "text"},
    {name: "request_uri", search: true, stype: "text"},
    {name: "client_ip", search: true, stype: "text"},
    {
        name: "timestamp",
        search: true,
        stype: "text",
        formatter: "customTimestampToDate"
    }
],

For some reason I am getting the timestamp value instead of the formatted one and I am not sure why or how.

I have been playing with momentjs on this Fiddle and it works as expected. I have been playing also with momentjs inside jqgrid in this Fiddle and as I am showing here is not working.

The problem: the issue here is the value being displayed as a string|int at timestamp column after the grid render which means the value on the column is the timestamp. The expected value would be the formatted one by moment doesn't matter if it's properly formatted or not (that's another different issue).

My guess is that the library hasn't been loaded when the grid is constructed or something like that but I am not sure at all.

Any ideas?

Note: Maybe there is an easy way to achieve this using a predefined formatter but I couldn't find it, if you know it let me know

ReynierPM
  • 17,594
  • 53
  • 193
  • 363
  • What do you mean with _not working_? I think you have to use moment [`format()`](http://momentjs.com/docs/#/displaying/format/). – VincenzoC Jan 15 '18 at 15:44
  • @VincenzoC **not working ===** _I am getting the timestamp value instead of the formatted one_. That's not true I don't need to use `format()` since `momentjs` support timestamp directly [see here](https://momentjs.com/docs/#/parsing/unix-timestamp-milliseconds/). Also if you take a look at the Fiddle examples you'll see what's not working – ReynierPM Jan 15 '18 at 15:47
  • Sorry I missed that part of your question, what is your desired output? – VincenzoC Jan 15 '18 at 15:50

3 Answers3

1

To display timestamps in jqGrid you can use predefined formatter "date" instead of the custom formatter: "customTimestampToDate". You can replace

formatter: "customTimestampToDate"

to, for example,

formatter: "date", sorttype: "date",
formatoptions: {srcformat: "u", newformat: "n/j/Y g:i:s A"}

The srcformat could be "u" or "u1000" depend on which timestamp you have as input. The default value of newformat is "n/j/Y", but you can change it to another one. You should use PHP formatting syntax (see http://php.net/manual/en/function.date.php).

It's recommended to use custom formatters only if predefined formatters can't do what you need. You can use moment plugin for example for advanced formatting of dates. You should don't forget to define unformatter (unformat callback function) always if you define formatter. It's required for editing of the data for example.

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Since the recommendation is to avoid custom formatter unless strictly needed then I have switched to Oleg answer however both solution did work as wanted. – ReynierPM Jan 15 '18 at 18:11
  • 1
    @ReynierPM: Yes, it's what I'd recommend you. And I'd recommend to write `unformat` always if you do define your custom `formatter` even if you currently no need it. Later if one will really need it, one will forget to define `unformat`. By usage of `formatter: "date", sorttype: "date"` you will be sure that all will be displayed and formatted as date independent on the format of input data or independent on the format of displayed data. Maximum, which you would could need is defining of `customSortOperations` See [the old answer](https://stackoverflow.com/a/29676941/315935). – Oleg Jan 15 '18 at 18:27
0

As the docs says:

To print out the value of a Moment, use .format(), .toString() or .toISOString().

Your code could be like the following:

customTimestampToDate: function (cellvalue, options, rowdata) {
    var parsed_timestamp = parseInt(rowdata.timestamp),
        tmp = new Date(parsed_timestamp * 1000).toISOString();

    return moment(tmp).format();
}

You can pass a format token to format() or use toISOString() to the the output in ISO 8601 compliant string.

Note that moment accepts also Unix timestamps in seconds, so you can use moment.unix(Number), in your case: return moment.unix(rowdata.timestamp).format();

VincenzoC
  • 30,117
  • 12
  • 90
  • 112
  • You were right apparently that was the missing piece here. Thx – ReynierPM Jan 15 '18 at 15:54
  • Glad it helped! Do not confuse between parsing input ([`moment(Number)`](https://momentjs.com/docs/#/parsing/unix-timestamp-milliseconds/)) and showing the value of a moment object (`format()`). – VincenzoC Jan 15 '18 at 15:56
  • Yeah, there was my confusion I though it should return the formatted date but it's not, thx again – ReynierPM Jan 15 '18 at 15:57
0

You do not need to use moment. Just use srcformat u (which is Unix timestamp) and the grid will do the job

formatter : 'date', formatoptions : { 
    srcformat : 'u',
    newformat : 'Y-m-d H:i:s'
} 
Tony Tomov
  • 3,122
  • 1
  • 11
  • 18