0

Good day

I need to display the delta time as the difference between two java.date.Util instances in the format 'HH:mm:ss'

The Omnifaces library seems very handy in calculating the amount of seconds difference between these two java.date.Util instances that will always be on the same day.

The one value is set using a Primefaces calendar component at the top of the .xhtml file like this:

<p:outputLabel for="datetime" value="Marathon Race Start: "/>
<p:calendar id="datetime" value="#{resultsView.marathonStart}" pattern="yyyy/MM/dd HH:mm:ss">
        <p:ajax event="change" immediate="true" update="marathon_results_form:results_all_datatable"/>
</p:calendar>

And then the results are displayed in a Primefaces dataTable like below (only the time column shown as all other columns works correct):

<p:column headerText="Time - Completed" style="text-align: center; align-content: left">
    <c:set var="raceTime" value="#{of:secondsBetween(resultsView.marathonStart,allResults.dateTimeStamp)}"/>
    #{of:formatDate(raceTime, 'HH:mm:ss')}
</p:column>

The above snippet throws a runtime error stating:

cannot convert of type class java.lang.Long to class java.util.Date

If I remove the Omnifaces:

#{of:formatDate(raceTime, 'HH:mm:ss')}

And replace with only:

#{raceTime}

Converting the whole column then to:

<p:column headerText="Time - Completed" style="text-align: center; align-content: left">
    <c:set var="raceTime" value="#{of:secondsBetween(resultsView.marathonStart,allResults.dateTimeStamp)}"/>
    #{raceTime}
</p:column>

It indeed works correctly by showing the amount of seconds as a long in the table column; and as soon as the start time is updated via the Primefaces calendar, the amount of seconds as a long updates in real time in the table; exactly as it should.

So then, how can I in the EL (using JSF 2.3.5.SP1 on WildFly 15) convert those longs to the 'HH:mm:ss' format?

EDIT:

I know this can be easily done by passing the long raceTime to a managed bean's method and get a string back from the bean; however, if this can be done more concisely via EL or Omnifaces I would rather follow that approach.

Letholdrus
  • 1,261
  • 3
  • 20
  • 36
  • Does it work using a plain jsf datatable? If so, it is not PrimeFaces related or even a plain simple 'h:outputText' without any datatable, most likely not when I look at the error. You seem to expect a Long can be converted to a date while according to the error it can't. The function is called formatDate and not `convertLongInSecondsToHoursAndMinutes`. – Kukeltje Mar 12 '19 at 09:00
  • Off-topic:if it would work at all, you can do this in one EL without a `c:set` like `#{of:formatDate(of:secondsBetween(resultsView.marathonStart,allResults.dateTimeStamp), 'HH:mm:ss')}`? – Kukeltje Mar 12 '19 at 09:01
  • @Kukeltje Thanks for taking the time to reply. I cannot use a JSF datatable because the requirement include functionality provided by Primefaces dataTable out-of-the-box. Without using c:set the form fails to render at run time (possibly due to the Omnifaces tags not liking being nested in EL (the example from the Omnifaces site uses c:set as well) - meaning your second reply to do all in one fails at run time. The formatDate and or formatDateTime EL functions expects a date (something with year, month and day) to convert. It cannot convert a delta long (4792L) amount of seconds to HH:mm:ss – Letholdrus Mar 12 '19 at 09:28
  • TRY, TRY, TRY, narrow the problem down, I nowhere stated you should use an h:datatable in production... Sigh... – Kukeltje Mar 12 '19 at 09:30
  • @Kukeltje, I looked at the links below, and personally feel that managing the conversion of for instance 4777L to HH:mm:ss in a managed bean in this case is the best. All other 'formatDate' (from standard JSF or Omnifaces) need a proper date which is a very long amount of seconds since epoch. Not having to deal with time zones etcetera, converting the 4777L in a bean method returning a String seems the more robust method as no time zones or epochs are involved. Was hoping that JSF EL could do it with only long; hence the reason for the question ;) – Letholdrus Mar 12 '19 at 09:36
  • _"conversion of for instance 4777L to HH:mm:ss in a managed bean in this case is the best."_ Correct... Or write your own function... Not to difficult (e.g. see the omnifaces source) You could even file it as a patch in a pullrequest for an enhancement to Omnifaces. – Kukeltje Mar 12 '19 at 09:39
  • @Kukeltje Thanks Kulkeltje, I will endeavor to do so.. – Letholdrus Mar 12 '19 at 09:41
  • I slightly improved the answer. Please check it – Kukeltje Mar 12 '19 at 09:42

1 Answers1

1

According to the of:formatDate it expects a java.util.Date and not a java.lang.Long, so the classcast is to be expected since the return value of of:secondsBetween is not a java.util.Date.

So what you experience is totally as expected. See the 'See also' for a possible fix, but doing it in a backing bean is not wrong either (not not less consice imo). In addition you can also write your own EL function, not too difficul

See also

Kukeltje
  • 12,223
  • 4
  • 24
  • 47