Преобразовать временную метку в обычный формат даты

В моем веб-приложении дата и время пользователя определенная активность хранится (в базе данных) как временная метка. Long которая при отображении обратно пользователю должна быть преобразована в обычный формат даты/времени.

(На самом деле моя база данных Cassandra хранит метку времени, когда столбец был написан для нее, как длинное значение (микросекунд с 1970 года), которое я буду использовать, чтобы узнать время соответствующей деятельности пользователя)

Я использую JSF 2.0 (+ primefaces), который, как я считаю, имеет конвертеры, которые могут быть полезны для этого преобразования? Или иначе как я могу в лучшем случае достичь этих преобразований?

Ответ 1

Позвольте мне предложить вам это решение. Итак, в вашем управляемом компоненте сделайте это

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

поэтому на вашей странице JSF вы можете сделать это (предполагая, что foo - это объект, который содержит ваше time)

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

Если у вас есть несколько страниц, которые хотят использовать этот метод, вы можете поместить это в abstract class и ваш управляемый компонент расширяет этот abstract class.

EDIT: время возврата с помощью TimeZone

к сожалению, я думаю, что SimpleDateFormat всегда будет форматировать время по местному времени, поэтому мы можем использовать SimpleDateFormat. Таким образом, чтобы отображать время в разных TimeZone, мы можем сделать это

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));

}

Лучшее решение - использовать JodaTime. На мой взгляд, этот API намного лучше, чем календарь (легче, быстрее и обеспечивает большую функциональность). Plus Calendar.Month of January - 0, которые заставляют разработчика добавлять 1 к результату, и вам нужно отформатировать время самостоятельно. Используя JodaTime, вы можете исправить все это. Исправьте меня, если я ошибаюсь, но я думаю, что JodaTime включен в JDK7

Ответ 2

Не уверен, что JSF предоставляет встроенную функциональность, но вы можете использовать конструктор java.sql.Date для преобразования в объект даты: http://download.oracle.com/javase/1.5.0/docs/api/java/SQL/Date.html # Дата (длинный)

Затем вы сможете использовать функции более высокого уровня, предоставляемые Java SE, Java EE для отображения и форматирования извлеченной даты. Вы можете создать java.util.Calendar и явно установить время: http://download.oracle.com/javase/1.5.0/docs/api/java/util/Calendar.html#setTime(java.util.Date )

EDIT: компоненты JSF не должны заботиться о преобразовании. Ваш уровень доступа к данным (уровень сохранения) должен позаботиться об этом. Другими словами, ваши компоненты JSF не должны обрабатывать long типизированные атрибуты, а только атрибуты Date или Calendar.

Ответ 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);

Вышеприведенный фрагмент печатает:

4 Noll 2017 05:01:18

"Noll" является гэльский на декабрь, так что это должно сделать вашего пользователя счастливым. Кроме того, в Ташкенте может быть очень мало гэльских говорящих людей, поэтому, пожалуйста, укажите правильные часовой пояс и локали пользователей.

Я серьезно отношусь к тому, что вы получили микросекунды из своей базы данных. Если вторая точность в порядке, вы можете обойтись без remainingMicros Instant.ofEpochSecond() и просто использовать one-arg Instant.ofEpochSecond(), что сделает код на пару строк короче. Поскольку Instant и ZonedDateTime поддерживают наносекундную точность, я счел наиболее правильным сохранить полную точность вашей метки времени. Если ваша метка времени была в миллисекундах, а не в микросекундах (что они часто бывают), вы можете просто использовать Instant.ofEpochMilli().

Ответы с использованием Date, Calendar и/или SimpleDateFormat были прекрасны, когда этот вопрос был задан 7 лет назад. Сегодня эти классы давно устарели, и у нас намного лучше в java.time, современном Java-API дат и времени.

Для большинства применений я рекомендую использовать встроенные локализованные форматы, как и в коде. Вы можете поэкспериментировать с передачей SHORT, LONG или FULL для стиля форматирования. Yo может даже указывать стиль форматирования даты и времени суток отдельно, используя перегруженный ofLocalizedDateTime. Если требуется конкретный формат (это задавалось по дублированному вопросу), вы можете иметь следующее:

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

Используя этот форматтер, мы получаем

05:01:18, 04/12/2017

Ссылка: Учебник Oracle: Дата Время, объясняющее, как использовать java.time.

Ответ 4

Чтобы показать ведущие нули infront часов, минут и секунд, используйте ниже измененного кода. Трюк здесь заключается в том, что мы преобразуем (или, точнее, форматируем) целое число в строку, чтобы оно показывало ведущий ноль, когда это применимо:

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;
    }

Результат будет выглядеть так: 00:01:30