Вопрос-ответ

Calculating the difference between two Java date instances

Вычисление разницы между двумя экземплярами даты Java

Я использую java.util.Date класс Java в Scala и хочу сравнить Date объект и текущее время. Я знаю, что могу вычислить дельту с помощью getTime ():

(new java.util.Date()).getTime() - oldDate.getTime()

Однако это просто оставляет меня с long, представляющим миллисекунды. Есть ли какой-либо более простой и приятный способ получить временную разницу?

Переведено автоматически
Ответ 1

Простая разница (без библиотеки lib)

/**
* Get a diff between two dates
* @param date1 the oldest date
* @param date2 the newest date
* @param timeUnit the unit in which you want the diff
* @return the diff value, in the provided unit
*/

public static long getDateDiff(Date date1, Date date2, TimeUnit timeUnit) {
long diffInMillies = date2.getTime() - date1.getTime();
return timeUnit.convert(diffInMillies,TimeUnit.MILLISECONDS);
}

А затем вы можете вызвать:

getDateDiff(date1,date2,TimeUnit.MINUTES);

чтобы получить разницу между двумя датами в единицах измерения минут.

TimeUnit is java.util.concurrent.TimeUnit, стандартное перечисление Java, переходящее от nanos к days.


Разница, читаемая человеком (без библиотеки lib)

public static Map<TimeUnit,Long> computeDiff(Date date1, Date date2) {

long diffInMillies = date2.getTime() - date1.getTime();

//create the list
List<TimeUnit> units = new ArrayList<TimeUnit>(EnumSet.allOf(TimeUnit.class));
Collections.reverse(units);

//create the result map of TimeUnit and difference
Map<TimeUnit,Long> result = new LinkedHashMap<TimeUnit,Long>();
long milliesRest = diffInMillies;

for ( TimeUnit unit : units ) {

//calculate difference in millisecond
long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS);
long diffInMilliesForUnit = unit.toMillis(diff);
milliesRest = milliesRest - diffInMilliesForUnit;

//put the result in the map
result.put(unit,diff);
}

return result;
}

http://ideone.com/5dXeu6

Результат выглядит примерно так Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}, с упорядоченными единицами измерения.

Вам просто нужно преобразовать эту карту в удобную для пользователя строку.


Предупреждение

Приведенные выше фрагменты кода вычисляют простую разницу между двумя моментами времени. Это может вызвать проблемы при переходе на летнее время, как описано в этом посте. Это означает, что если вы вычисляете разницу между датами без указания времени, у вас может отсутствовать день / час.

На мой взгляд, разница в дате отчасти субъективна, особенно по дням. Вы можете:


  • подсчитайте количество прошедших 24 часа времени: день + 1 - день = 1 день = 24 часа



  • подсчитайте количество прошедшего времени с учетом перехода на летнее время: день + 1 - день = 1 = 24 часа (но при использовании полуночного времени и перехода на летнее время это может быть 0 дней и 23 часа)



  • подсчитайте количество day switches, что означает день + 1 13:00 - 11:00 = 1 день, даже если прошедшее время составляет всего 2 часа (или 1 час, если установлен переход на летнее время : p)



Мой ответ верен, если ваше определение разницы дат в днях соответствует 1-му случаю

С помощью JodaTime

Если вы используете JodaTime, вы можете получить разницу для 2 мгновенных (с поддержкой миллионов ReadableInstant) дат с помощью:

Interval interval = new Interval(oldInstant, new Instant());

Но вы также можете получить разницу для локальных дат / времени:

// returns 4 because of the leap year of 366 days
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5), PeriodType.years()).getYears()

// this time it returns 5
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5+1), PeriodType.years()).getYears()

// And you can also use these static methods
Years.yearsBetween(LocalDate.now(), LocalDate.now().plusDays(365*5)).getYears()
Ответ 2

К сожалению, JDK Date API ужасно сломан. Я рекомендую использовать библиотеку времени Joda.

В Joda Time есть понятие временного интервала:

Interval interval = new Interval(oldTime, new Instant());

РЕДАКТИРОВАТЬ: Кстати, у Joda есть две концепции: Interval для представления интервала времени между двумя моментами времени (представляют время между 8 утра и 10 утра), и Duration который представляет отрезок времени без фактических временных границ (например, представляют два часа!)

Если вас интересует только сравнение времени, в большинстве Date реализаций (включая JDK) реализован Comparable интерфейс, который позволяет вам использовать Comparable.compareTo()

Ответ 3
int diffInDays = (int)( (newerDate.getTime() - olderDate.getTime()) 
/ (1000 * 60 * 60 * 24) )

Обратите внимание, что это работает с датами UTC, поэтому разница может составлять выходной день, если вы смотрите на местные даты. И чтобы это правильно работало с местными датами, требуется совершенно другой подход из-за перехода на летнее время.

Ответ 4

Использование фреймворка java.time, встроенного в Java 8+:

ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime oldDate = now.minusDays(1).minusMinutes(10);
Duration duration = Duration.between(oldDate, now);
System.out.println("ISO-8601: " + duration);
System.out.println("Minutes: " + duration.toMinutes());

Вывод:


ISO-8601: PT24H10M


Минут: 1450


Для получения дополнительной информации см. Руководство по Oracle и стандарт ISO 8601.

java date