Я хочу взять два раза (в секундах с эпохи) и показать разницу между ними в таких форматах, как:
- 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
(Кашель, старый, кашель)
Date start = new Date(1167627600000L); // JANUARY_1_2007
Date end = new Date(1175400000000L); // APRIL_1_2007
long diffInSeconds = (end.getTime() - start.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));
System.out.println(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" : ""));
Yup пробудил мертвых, которые у меня есть, но здесь моя улучшенная реализация основана на @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
EDIT: теперь поддерживает месяцы и годы: 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
отделяет любые годы-месяцы-дни от любых часов-минут-секунд. Таким образом, полтора часа - PT1H30M
.
В нашем примере код используется семь минут:
String outputStandard = duration.toString();
PT7M
См. Приведенный выше пример кода, который работает в режиме реального времени на IdeOne.com.
Я предлагаю придерживаться этих форматов, когда это возможно, конечно, при обмене или сериализации данных даты и времени, но также подумайте над использованием в пользовательском интерфейсе, где это необходимо, и ваших пользователей можно обучить их использованию.
Я рекомендую никогда не использовать формат часового часа (например: 01:30 для полутора часов), поскольку этот формат полностью неоднозначен с временем суток.
Если вы должны указать промежуток времени, как показано в Вопросе, вам нужно будет создать текст самостоятельно.
Period
вызовите getYears
, getMonths
и getDays
для извлечения каждой части.Duration
не было таких геттеров в Java 8, но они получили их в Java 9 и более поздних toDaysPart
: toDaysPart
, 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();
Или, может быть, вы можете написать код с помощью DateTimeFormatterBuilder
способом, показанным с помощью Joda-Time в ответе от Balus C.
Рамка java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют неприятные старые устаревшие классы времени, такие как java.util.Date
, Calendar
и SimpleDateFormat
.
Проект Joda-Time, теперь в режиме обслуживания, советует перейти на классы java.time.
Чтобы узнать больше, ознакомьтесь с учебным пособием Oracle. И поиск Qaru для многих примеров и объяснений. Спецификация - JSR 310.
Где можно получить классы java.time?
Проект ThreeTen-Extra расширяет java.time с дополнительными классами. Этот проект является доказательством возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь, такие как Interval
, YearWeek
, YearQuarter
, 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();
}
Я всегда начинаю с Joda Time. Работа с датами и временем в Java всегда "веселая", но время Joda Time снимает напряжение.
У них есть классы Interval и Duration, которые выполняют половину того, что вы ищете. Не уверен, что у них есть функция для вывода в читаемом формате. Я буду продолжать искать.
НТН
Calendar класс может обрабатывать большинство связанных с датой математики. Вам нужно будет получить результат compareTo и вывести формат самостоятельно. Существует не стандартная библиотека, которая делает именно то, что вы ищете, хотя может быть и сторонняя библиотека, которая делает.
ОК, после краткого ознакомления с API кажется, что вы можете сделать следующее: -
НТН
Решение "Abduliam Rehmanius" кажется довольно приятным, или вы можете использовать некоторую библиотеку выше или вы можете создавать новые простые вещи, обратитесь к решению JS здесь: http://www.datejs.com/. Не сложно преобразовать в Java lang: -)
Надеюсь, что моя ссылка полезна для вас!
Время форматирования в java часто появляется для меня в ETL или DB pulls. Следующий фрагмент кода - это то, как я получаю импульс операции.
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 - это библиотека форматирования времени OpenSource. Полностью настраиваемый, он создает читаемые человеком относительные временные метки, подобные тем, которые видны на 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 из даты utils
dateHere.setText(DateUtils.getRelativeTimeSpanString(timeInMillis,
System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS));
он принимает аргументы: long/int time, текущее время и то, как вы хотите, _month, minute, second etc
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).