26

In my web app, date & time of a user's certain activity is stored(in database) as a timestamp Long which on being displayed back to user needs to be converted into normal date/time format.

(Actually my database Cassandra stores the timestamp of when a column was written to it, as a long value( microseconds since 1970 ) which I will use to find out the time of that corresponding user activity)

I am using JSF 2.0(+ primefaces) which I believe has converters that may be helpful for this conversion? Or otherwise how How can I, at best, achieve these conversions?

Rajat Gupta
  • 25,853
  • 63
  • 179
  • 294
  • I know nothing about Cassandra, so here's just a shoot in the dark: I wonder if `PreparedStatement#setTimestamp()` and `ResultSet#getTimestamp()` doesn't work out for you? See also the answer on a similar question which I posted before today: http://stackoverflow.com/questions/6778558/how-can-i-set-the-global-default-date-format-in-java With a fullworthy `java.util.Date` object you can just use JSF standard date/time converters such as `` in the view side the usual way to convert between it and a human readable string representation. – BalusC Jul 21 '11 at 20:41
  • 1
    @BalusC: isn't Cassandra is one of those `BigTable` or `NoQuery` database that facebook or twitter use. I heard those are very different from regular DB. @Raj, since `PreparedStatement#setTimestamp() and ResultSet#getTimestamp()` might not work for you, I post higher layer solution for you. – Thang Pham Jul 21 '11 at 20:52

5 Answers5

76

Let me propose this solution for you. So in your managed bean, do this

public String convertTime(long time){
    Date date = new Date(time);
    Format format = new SimpleDateFormat("yyyy MM dd HH:mm:ss");
    return format.format(date);
}

so in your JSF page, you can do this (assuming foo is the object that contain your time)

<h:dataTable value="#{myBean.convertTime(myBean.foo.time)}" />

If you have multiple pages that want to utilize this method, you can put this in an abstract class and have your managed bean extend this abstract class.

EDIT: Return time with TimeZone

unfortunately, I think SimpleDateFormat will always format the time in local time, so we can't use SimpleDateFormat anymore. So to display time in different TimeZone, we can do this

public String convertTimeWithTimeZome(long time){
    Calendar cal = Calendar.getInstance();
    cal.setTimeZone(TimeZone.getTimeZone("UTC"));
    cal.setTimeInMillis(time);
    return (cal.get(Calendar.YEAR) + " " + (cal.get(Calendar.MONTH) + 1) + " " 
            + cal.get(Calendar.DAY_OF_MONTH) + " " + cal.get(Calendar.HOUR_OF_DAY) + ":"
            + cal.get(Calendar.MINUTE));

}

A better solution is to utilize JodaTime. In my opinion, this API is much better than Calendar (lighter weight, faster and provide more functionality). Plus Calendar.Month of January is 0, that force developer to add 1 to the result, and you have to format the time yourself. Using JodaTime, you can fix all of that. Correct me if I am wrong, but I think JodaTime is incorporated in JDK7

Gastón Saillén
  • 12,319
  • 5
  • 67
  • 77
Thang Pham
  • 38,125
  • 75
  • 201
  • 285
  • 1
    Thanks ! could you also let me know how can I convert(increment/decrement) it according to the user's local timezone. – Rajat Gupta Jul 22 '11 at 05:59
  • 2
    There's [JSR-310](http://sourceforge.net/apps/mediawiki/threeten/index.php?title=ThreeTen), a proposed standardised Joda-Time-alike library to appear in a future JDK, but it didn't make it into JDK 7. – Rup Apr 23 '12 at 16:01
  • @ThangPham JodaTime is not incorporated in JDK7. – falsarella May 23 '12 at 12:13
  • 1
    It is added to JAVA SE 8 – Sam Feb 10 '15 at 15:10
  • This doesn't provide leading 0 when second,minute or hour is single digit. I have modified it to make look like a digital clock. User formatting to achieve the same as below : String curTime = String.format("%02d:%02d:%02d", cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND)); or Check my answer in comments – Irfan Raza Jul 30 '16 at 20:02
3

java.time

    ZoneId usersTimeZone = ZoneId.of("Asia/Tashkent");
    Locale usersLocale = Locale.forLanguageTag("ga-IE");
    DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
            .withLocale(usersLocale);

    long microsSince1970 = 1_512_345_678_901_234L;
    long secondsSince1970 = TimeUnit.MICROSECONDS.toSeconds(microsSince1970);
    long remainingMicros = microsSince1970 - TimeUnit.SECONDS.toMicros(secondsSince1970);
    ZonedDateTime dateTime = Instant.ofEpochSecond(secondsSince1970, 
                    TimeUnit.MICROSECONDS.toNanos(remainingMicros))
            .atZone(usersTimeZone);
    String dateTimeInUsersFormat = dateTime.format(formatter);
    System.out.println(dateTimeInUsersFormat);

The above snippet prints:

4 Noll 2017 05:01:18

“Noll” is Gaelic for December, so this should make your user happy. Except there may be very few Gaelic speaking people living in Tashkent, so please specify the user’s correct time zone and locale yourself.

I am taking seriously that you got microseconds from your database. If second precision is fine, you can do without remainingMicros and just use the one-arg Instant.ofEpochSecond(), which will make the code a couple of lines shorter. Since Instant and ZonedDateTime do support nanosecond precision, I found it most correct to keep the full precision of your timestamp. If your timestamp was in milliseconds rather than microseconds (which they often are), you may just use Instant.ofEpochMilli().

The answers using Date, Calendar and/or SimpleDateFormat were fine when this question was asked 7 years ago. Today those classes are all long outdated, and we have so much better in java.time, the modern Java date and time API.

For most uses I recommend you use the built-in localized formats as I do in the code. You may experiment with passing SHORT, LONG or FULL for format style. Yo may even specify format style for the date and for the time of day separately using an overloaded ofLocalizedDateTime method. If a specific format is required (this was asked in a duplicate question), you can have that:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss, dd/MM/uuuu");

Using this formatter instead we get

05:01:18, 04/12/2017

Link: Oracle tutorial: Date Time explaining how to use java.time.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
1

Not sure if JSF provides a built-in functionality, but you could use java.sql.Date's constructor to convert to a date object: http://download.oracle.com/javase/1.5.0/docs/api/java/sql/Date.html#Date(long)

Then you should be able to use higher level features provided by Java SE, Java EE to display and format the extracted date. You could instantiate a java.util.Calendar and explicitly set the time: http://download.oracle.com/javase/1.5.0/docs/api/java/util/Calendar.html#setTime(java.util.Date)

EDIT: The JSF components should not take care of the conversion. Your data access layer (persistence layer) should take care of this. In other words, your JSF components should not handle the long typed attributes but only a Date or Calendar typed attributes.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
home
  • 12,468
  • 5
  • 46
  • 54
0

To show leading zeros infront of hours, minutes and seconds use below modified code. The trick here is we are converting (or more accurately formatting) integer into string so that it shows leading zero whenever applicable :

public String convertTimeWithTimeZome(long time) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeZone(TimeZone.getTimeZone("UTC"));
        cal.setTimeInMillis(time);
        String curTime = String.format("%02d:%02d:%02d", cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
        return curTime;
    }

Result would be like : 00:01:30

Irfan Raza
  • 2,859
  • 1
  • 22
  • 29
0

I tried this and worked for me.

Date = (long)(DateTime.Now.Subtract(new DateTime(1970, 1, 1, 0, 0, 0))).TotalSeconds
Mebin Joe
  • 2,172
  • 4
  • 16
  • 22
sachin
  • 202
  • 3
  • 2