Я хочу взять два раза (в секундах с эпохи) и показать разницу между ними в таких форматах, как:
- 2 минуты
- 1 час, 15 минут
- 3 часа, 9 минут
- 1 минуту назад
- 1 час, 2 минуты назад
Как я могу этого добиться?
Я хочу взять два раза (в секундах с эпохи) и показать разницу между ними в таких форматах, как:
Как я могу этого добиться?
Поскольку все кричат «YOODAA !!!» но никто не публикует конкретный пример, вот мой вклад.
Вы также можете сделать это с помощью Joda-Time. Используйте Period
для обозначения точки. Чтобы отформатировать период в желаемом человеческом представлении, используйте PeriodFormatter
, который можно создать с помощью PeriodFormatterBuilder
.
Вот начальный пример:
DateTime myBirthDate = new DateTime(1978, 3, 26, 12, 35, 0, 0);
DateTime now = new DateTime();
Period period = new Period(myBirthDate, now);
PeriodFormatter formatter = new PeriodFormatterBuilder()
.appendYears().appendSuffix(" year, ", " years, ")
.appendMonths().appendSuffix(" month, ", " months, ")
.appendWeeks().appendSuffix(" week, ", " weeks, ")
.appendDays().appendSuffix(" day, ", " days, ")
.appendHours().appendSuffix(" hour, ", " hours, ")
.appendMinutes().appendSuffix(" minute, ", " minutes, ")
.appendSeconds().appendSuffix(" second", " seconds")
.printZeroNever()
.toFormatter();
String elapsed = formatter.print(period);
System.out.println(elapsed + " ago");
Гораздо яснее и лаконичнее, не правда ли?
Это отпечатано к настоящему времени
32 years, 1 month, 1 week, 5 days, 6 hours, 56 minutes, 24 seconds ago
(Кашель, старый, кашель)
Period
и Duration
. Проект ThreeTen-Extra предлагает Interval
.
- person Basil Bourque; 02.01.2018
Да разбудил мёртвых, которые у меня есть, но вот моя улучшенная реализация, основанная на опубликованном коде @mtim, так как эта ветка идет почти поверх результатов поиска, поэтому я возился с сонной лощиной,
public static String getFriendlyTime(Date dateTime) {
StringBuffer sb = new StringBuffer();
Date current = Calendar.getInstance().getTime();
long diffInSeconds = (current.getTime() - dateTime.getTime()) / 1000;
/*long diff[] = new long[]{0, 0, 0, 0};
/* sec * diff[3] = (diffInSeconds >= 60 ? diffInSeconds % 60 : diffInSeconds);
/* min * diff[2] = (diffInSeconds = (diffInSeconds / 60)) >= 60 ? diffInSeconds % 60 : diffInSeconds;
/* hours * diff[1] = (diffInSeconds = (diffInSeconds / 60)) >= 24 ? diffInSeconds % 24 : diffInSeconds;
/* days * diff[0] = (diffInSeconds = (diffInSeconds / 24));
*/
long sec = (diffInSeconds >= 60 ? diffInSeconds % 60 : diffInSeconds);
long min = (diffInSeconds = (diffInSeconds / 60)) >= 60 ? diffInSeconds % 60 : diffInSeconds;
long hrs = (diffInSeconds = (diffInSeconds / 60)) >= 24 ? diffInSeconds % 24 : diffInSeconds;
long days = (diffInSeconds = (diffInSeconds / 24)) >= 30 ? diffInSeconds % 30 : diffInSeconds;
long months = (diffInSeconds = (diffInSeconds / 30)) >= 12 ? diffInSeconds % 12 : diffInSeconds;
long years = (diffInSeconds = (diffInSeconds / 12));
if (years > 0) {
if (years == 1) {
sb.append("a year");
} else {
sb.append(years + " years");
}
if (years <= 6 && months > 0) {
if (months == 1) {
sb.append(" and a month");
} else {
sb.append(" and " + months + " months");
}
}
} else if (months > 0) {
if (months == 1) {
sb.append("a month");
} else {
sb.append(months + " months");
}
if (months <= 6 && days > 0) {
if (days == 1) {
sb.append(" and a day");
} else {
sb.append(" and " + days + " days");
}
}
} else if (days > 0) {
if (days == 1) {
sb.append("a day");
} else {
sb.append(days + " days");
}
if (days <= 3 && hrs > 0) {
if (hrs == 1) {
sb.append(" and an hour");
} else {
sb.append(" and " + hrs + " hours");
}
}
} else if (hrs > 0) {
if (hrs == 1) {
sb.append("an hour");
} else {
sb.append(hrs + " hours");
}
if (min > 1) {
sb.append(" and " + min + " minutes");
}
} else if (min > 0) {
if (min == 1) {
sb.append("a minute");
} else {
sb.append(min + " minutes");
}
if (sec > 1) {
sb.append(" and " + sec + " seconds");
}
} else {
if (sec <= 1) {
sb.append("about a second");
} else {
sb.append("about " + sec + " seconds");
}
}
sb.append(" ago");
/*String result = new String(String.format(
"%d day%s, %d hour%s, %d minute%s, %d second%s ago",
diff[0],
diff[0] > 1 ? "s" : "",
diff[1],
diff[1] > 1 ? "s" : "",
diff[2],
diff[2] > 1 ? "s" : "",
diff[3],
diff[3] > 1 ? "s" : ""));*/
return sb.toString();
}
Очевидно, это можно улучшить. в основном он пытается сделать временной интервал более удобным, хотя есть несколько ограничений, то есть он будет вести себя странно, если время (параметр) будет в будущем, и оно ограничено только днями, часами и секундами (месяцы и годы не обработали, так что может кто-то другой ;-).
Примеры выходных данных:
, ура: D
РЕДАКТИРОВАТЬ: теперь поддерживает месяцы и годы: P
Я бы порекомендовал вам взглянуть на HumanTime
Остальные ответы могут быть правильными, но устарели. Проблемные старые классы даты и времени в Java теперь унаследованы, их вытеснили классы java.time.
Аналогичным образом, проект Joda-Time теперь в режим обслуживания, советует перейти на java.time классы.
Instant
два раза (в секундах с эпохи)
В java.time мы представляем моменты на шкале времени в формате UTC как Instant
. Я предполагаю, что ваша эпоха такая же, как и для java.time, первый момент 1970 года в формате UTC (1970-01-01T00:00:00Z
). Обратите внимание, что Instant
имеет разрешение наносекунды. Метод удобной фабрики создает Instant
из целых секунд, как указано в Вопросе.
Instant start = Instant.ofEpochSecond( … );
Instant stop = Instant.ofEpochSecond( … );
Здесь мы используем текущий момент и несколько минут спустя.
Instant start = Instant.now() ;
Instant stop = start.plusSeconds( TimeUnit.MINUTES.toSeconds( 7L ) ) ; // Seven minutes as a number of seconds.
Duration
В java.time промежуток времени, не привязанный к временной шкале, представлен двумя способами. Для лет-месяцев-дней у нас есть Period
. Для часов-минут-секунд у нас есть Duration
.
Duration duration = Duration.between( start , stop );
Прошедшее время рассчитывается с использованием метода Half-Open. В этом подходе начало включающее, а окончание исключающее. Этот подход обычно используется в работе с датой и временем. Я считаю, что последовательное использование этого подхода во всей базе кода поможет устранить ошибки и недоразумения из-за двусмысленности и снизит когнитивную нагрузку на программирование.
Стандарт ISO 8601 определяет множество практических форматов для представления значений даты и времени в виде текста. Эти форматы разработаны таким образом, чтобы избежать двусмысленности, их легко анализировать на машине, и они интуитивно понятны для людей в разных культурах.
Классы java.time по умолчанию используют эти форматы при синтаксическом анализе и генерации строк.
Для промежутка времени, не привязанного к временной шкале, стандарт определяет формат PnYnMnDTnHnMnS
, где P
отмечает начало, а T
отделяет любые годы-месяцы-дни от любых часов-минут-секунд. Итак, полтора часа - это 15_15.
В нашем примере кода используется семь минут:
String outputStandard = duration.toString();
PT7M
См. Приведенный выше пример кода, работающего в реальном времени на IdeOne.com.
Я предлагаю по возможности придерживаться этих форматов, особенно при обмене или сериализации данных даты и времени, но также подумайте об их использовании в пользовательском интерфейсе, где это необходимо, и ваши пользователи могут быть обучены их использованию.
Я рекомендую никогда не использовать формат часового времени (например, 01:30 для полутора часов), поскольку этот формат совершенно неоднозначен с временем суток.
Если вы должны указать промежуток времени, как показано в Вопросе, вам нужно будет составить текст самостоятельно.
Period
вызовите _ 18_, getMonths
и getDays
для получения каждой части .Duration
такие геттеры отсутствовали в Java 8, но они были получены в Java 9 и более поздних версий: _ 22_, toHoursPart
, toMinutesPart
, toSecondsPart
и toNanosPart
.Некоторый пример кода, простой и базовый, чтобы вы начали.
int days = duration.toDaysPart() ;
int hours = duration.toHoursPart() ;
int minutes = duration.toMinutesPart() ;
int seconds = duration.toSecondsPart() ;
int nanos = duration.toNanosPart() ;
StringBuilder sb = new StringBuilder( 100 );
if( days != 0 ) {
sb.append( days + " days" ) ;
};
if( hours != 0 ) {
sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ; // Append comma if any existing text.
sb.append( hours + " hours" ) ;
};
if( minutes != 0 ) {
sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ; // Append comma if any existing text.
sb.append( minutes + " minutes" ) ;
};
if( seconds != 0 ) {
sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ; // Append comma if any existing text.
sb.append( seconds + " seconds" ) ;
};
if( nanos != 0 ) {
sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ; // Append comma if any existing text.
sb.append( nanos + " nanos" ) ;
};
String output = sb.toString();
Или, возможно, вы могли бы написать приятный код, используя _28 _ способом, показанным с помощью Joda-Time в ответе Балуса C.
Создана структура java.time в Java 8 и новее. Эти классы заменяют неудобные старые устаревшие классы даты и времени, такие как _ 29_, _ 30_, & _ 31_.
Проект Joda-Time теперь в режим обслуживания, советует перейти на java.time классы.
Чтобы узнать больше, см. Учебник Oracle. И поищите в Stack Overflow множество примеров и объяснений. Спецификация - JSR 310.
Где взять классы java.time?
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является испытательной площадкой для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, например _32 _, YearWeek
, _ 34_, andfz подробнее.
Я не эксперт в Java, но вы можете сделать t1-t2 = t3 (в секундах), затем разделить это на 60, даст вам минуты, еще на 60 даст вам секунды. Тогда остается только выяснить, сколько подразделений вам нужно.
Надеюсь, поможет.
Если ваши временные интервалы пересекают границы перехода на летнее время, вы хотите сообщить количество дней?
Например, с 23:00 до 23:00 следующего дня всегда будет день, но это может быть 23, 24 или 25 часов в зависимости от того, переходите ли вы на летнее время.
Если вам это небезразлично, убедитесь, что вы учли это при своем выборе.
какой-то код, который играет с форматированием даты ... и время назад.
SimpleDateFormat curFormater = new SimpleDateFormat("EEE, dd MMM yyyy kk:mm:ss");
try {
Date dateObj = curFormater.parse(pubDate);
SimpleDateFormat postFormater = new SimpleDateFormat("MMMM dd, yyyy ss:mm:hh");
String newDateStr = postFormater.format(dateObj);
Log.v("THE NEW DATE IS",newDateStr);
long pubdateinmilis = dateObj.getTime();
pubDate = (String) DateUtils.getRelativeTimeSpanString(pubdateinmilis, System.currentTimeMillis(),DateUtils.HOUR_IN_MILLIS,DateUtils.FORMAT_ABBREV_RELATIVE);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Вы можете использовать java.time.Duration
, смоделированный на стандарты ISO-8601 и был представлен вместе с Java-8 как часть реализации JSR-310. В Java-9 были представлены несколько более удобных методов.
Демо:
import java.time.Duration;
import java.time.Instant;
class Main {
public static void main(String[] args) {
// Test
System.out.println(getFormattedDuration(1619575035, 1619810961));
}
public static String getFormattedDuration(long start, long end) {
Instant startInstant = Instant.ofEpochSecond(start);
Instant endInstant = Instant.ofEpochSecond(end);
Duration duration = Duration.between(startInstant, endInstant);
// Custom format
// ####################################Java-8####################################
return String.format("%d days, %d hours, %d minutes, %d seconds", duration.toDays(), duration.toHours() % 24,
duration.toMinutes() % 60, duration.toSeconds() % 60);
// ##############################################################################
// ####################################Java-9####################################
// return String.format("%d days, %d hours, %d minutes, %d seconds",
// duration.toDaysPart(), duration.toHoursPart(),
// duration.toMinutesPart(), duration.toSecondsPart());
// ##############################################################################
}
}
Вывод:
2 days, 17 hours, 32 minutes, 6 seconds
Я всегда начинаю с Joda Time. Работать с датой и временем на Java всегда «весело», но Joda Time снимает напряжение.
У них есть классы Interval и Duration, которые делают половину того, что вы ищете. Не уверен, что у них есть функция вывода в читаемом формате. Я буду искать.
HTH
Класс Calendar может обрабатывать большинство связанных с датами математика. Вам нужно будет получить результат compareTo и вывести формат самостоятельно. Не существует стандартной библиотеки, которая бы делала именно то, что вы ищете, хотя может существовать сторонняя библиотека, которая это делает.
Хорошо, после краткого ознакомления с API кажется, что вы можете сделать следующее: -
HTH
Решение «Abduliam Rehmanius» кажется довольно приятным, или вы можете использовать какую-либо указанную выше библиотеку, или вы можете создавать новые простые вещи, обратитесь к решению JS здесь: http://www.datejs.com/. Перевести на язык Java несложно :-)
Надеюсь, моя ссылка будет для вас полезной!
Временные интервалы форматирования в java у меня часто возникают в ETL или DB. Следующий фрагмент кода показывает, как я получаю импульс операции.
SimpleDateFormat ymdhms=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
DecimalFormat formatter = new DecimalFormat("#,###"); /* ("#,###.00"); gives you the decimal fractions */
int counter=0;
Date beginTime0=new Date();
while (<some end condition>) {
<some time consuming operation>
/*// uncomment this section durring initial exploration of the time consumer
if(counter>100000){
System.out.println("debug exiting due to counter="+counter);
System.exit(0);
}
*/
if(0==counter%1000){
Date now = new Date();
long diffInSeconds = (now.getTime() - beginTime0.getTime()) / 1000;
long diff[] = new long[] { 0, 0, 0, 0 };
diff[3] = (diffInSeconds >= 60 ? diffInSeconds % 60 : diffInSeconds); /* sec */
diff[2] = (diffInSeconds = (diffInSeconds / 60)) >= 60 ? diffInSeconds % 60 : diffInSeconds; /* min */
diff[1] = (diffInSeconds = (diffInSeconds / 60)) >= 24 ? diffInSeconds % 24 : diffInSeconds; /* hours */
diff[0] = (diffInSeconds = (diffInSeconds / 24)); /* days */
String delta = String.format(
"%s%s%s%s"
,(diff[0]>0?String.format("%d day%s " ,diff[0],(diff[0]!=1?"s":"")):"")
,(diff[1]>0?String.format("%2d hour%s " ,diff[1],(diff[1]!=1?"s":" ")):"")
,(diff[2]>0?String.format("%2d minute%s ",diff[2],(diff[2]!=1?"s":" ")):"")
, String.format("%2d second%s ",diff[3],(diff[3]!=1?"s":" "))
);
System.out.println(String.format(
"%12s %s delta= %s"
,formatter.format(counter)
,ymdhms.format(new Date())
,delta
)
);
}
counter++;
}
Я думаю, вы ищете что-то вроде PrettyTime
PrettyTime - это библиотека форматирования времени с открытым исходным кодом. Полностью настраиваемый, он создает удобочитаемые, относительные отметки времени, подобные тем, которые можно увидеть на Digg, Twitter и Facebook. Он доступен более чем на 30 языках!
ссылка: https://github.com/ocpsoft/prettytime
Может использоваться и в Android
Например
System.out.println(p.format(new Date(System.currentTimeMillis() + 1000*60*10)));
//prints: "10 minutes from now"
Недавно у меня появилось такое же требование, когда мне нужен базовый метод для печати продолжительности. У меня не было возможности использовать стороннюю библиотеку. Поэтому я просто доработал идею @mtim.
public static void main(String[] args) throws IOException, ParseException {
String since = "2017-02-24T04:44:05.601Z";
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
TimeZone utc = TimeZone.getTimeZone("UTC");
dateFormat.setTimeZone(utc);
Date sinceDate = dateFormat.parse(since);
Date now = new Date();
long durationInSeconds = TimeUnit.MILLISECONDS.toSeconds(now.getTime() - sinceDate.getTime());
long SECONDS_IN_A_MINUTE = 60;
long MINUTES_IN_AN_HOUR = 60;
long HOURS_IN_A_DAY = 24;
long DAYS_IN_A_MONTH = 30;
long MONTHS_IN_A_YEAR = 12;
long sec = (durationInSeconds >= SECONDS_IN_A_MINUTE) ? durationInSeconds % SECONDS_IN_A_MINUTE : durationInSeconds;
long min = (durationInSeconds /= SECONDS_IN_A_MINUTE) >= MINUTES_IN_AN_HOUR ? durationInSeconds%MINUTES_IN_AN_HOUR : durationInSeconds;
long hrs = (durationInSeconds /= MINUTES_IN_AN_HOUR) >= HOURS_IN_A_DAY ? durationInSeconds % HOURS_IN_A_DAY : durationInSeconds;
long days = (durationInSeconds /= HOURS_IN_A_DAY) >= DAYS_IN_A_MONTH ? durationInSeconds % DAYS_IN_A_MONTH : durationInSeconds;
long months = (durationInSeconds /=DAYS_IN_A_MONTH) >= MONTHS_IN_A_YEAR ? durationInSeconds % MONTHS_IN_A_YEAR : durationInSeconds;
long years = (durationInSeconds /= MONTHS_IN_A_YEAR);
String duration = getDuration(sec,min,hrs,days,months,years);
System.out.println(duration);
}
private static String getDuration(long secs, long mins, long hrs, long days, long months, long years) {
StringBuffer sb = new StringBuffer();
String EMPTY_STRING = "";
sb.append(years > 0 ? years + (years > 1 ? " years " : " year "): EMPTY_STRING);
sb.append(months > 0 ? months + (months > 1 ? " months " : " month "): EMPTY_STRING);
sb.append(days > 0 ? days + (days > 1 ? " days " : " day "): EMPTY_STRING);
sb.append(hrs > 0 ? hrs + (hrs > 1 ? " hours " : " hour "): EMPTY_STRING);
sb.append(mins > 0 ? mins + (mins > 1 ? " mins " : " min "): EMPTY_STRING);
sb.append(secs > 0 ? secs + (secs > 1 ? " secs " : " secs "): EMPTY_STRING);
sb.append("ago");
return sb.toString();
}
Результатом будет временной интервал (продолжительность), напечатанный словами, например. 1 day 2 hours 51 mins 41 secs ago
Это старый вопрос, на него уже есть ответ, но у меня есть решение получше. Используйте relativeSpan from date utils
dateHere.setText(DateUtils.getRelativeTimeSpanString(timeInMillis,
System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS));
он принимает аргументы: длинное / целое время, текущее время и то, как вы этого хотите, _месяц, минута, секунда и т. д.
long time1, time2;
time1 = System.currentMillis();
.. drink coffee
time2 = System.currentMillis();
long difference = time2 - time1 // millies between time1 and time2
java.util.Date differneceDate = new Date(difference);
Чтобы создать строку типа «2 минуты», вы должны использовать DateFormatter / DateFormat. Вы можете найти более подробную информацию об этом в спецификации Java API (java.sun.com).
java.util.Date
,java.util.Calendar
иjava.text.SimpleTextFormat
теперь являются устаревшими, замененными java.time классы. Аналогичным образом, Joda-Time теперь находится в режим обслуживания и советует перейти на java.time. - person Basil Bourque   schedule 26.02.2017