Преобразовать временную метку в обычный формат даты
В моем веб-приложении дата и время пользователя определенная активность хранится (в базе данных) как временная метка. 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