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

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

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

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


person pr1001    schedule 12.10.2009    source источник
comment
Почему нет любви к joda time? Это лучший вариант, если вы собираетесь работать с датами в java.   -  person Doctor Jones    schedule 03.05.2012
comment
Пожалуйста, проверьте мое элегантное 2-лайнерное решение без использования Joda и предоставив результат в любом TimeUnit по адресу stackoverflow.com/a/10650881/82609   -  person Sebastien Lorber    schedule 12.03.2013
comment
Позор всем тем, кто рекомендует время Joda и не рекомендует истинный ответ Java ...   -  person Zizouz212    schedule 30.12.2015
comment
Для большинства решений, описанных здесь и в других местах, они неточны при учете перехода на летнее время (DST). Действительно, когда к субботе 2016-03-26T23: 30 CET добавляются 24 часа, в результате получается дата 2016-03-28T00: 30 CET, и двухдневные границы пересекаются. Действительно, летнее время вступает в силу в воскресенье 2016-03-27T02 : 00 Центральноевропейское время. Проблема с переходом на летнее время не относится к среднеевропейскому времени и возникает каждый раз, когда в рассматриваемый период вступает в силу переход на летнее время.   -  person Ceki    schedule 18.03.2016
comment
@ Zizouz212 Что касается рекомендации Joda-Time, старые классы времени и даты, связанные с Java, плохие, очень плохие, плохо спроектированные, запутанные и проблемные. Настолько плохо, что Joda-Time стал очень успешным в качестве их замены. Настолько плохо, что даже Sun / Oracle отказались от них и приняли пакет java.time как часть Java 8 и более поздних версий. Классы java.time вдохновлены Joda-Time. И Joda-Time, и java.time возглавляет один и тот же человек, Стивен Колборн. Я бы сказал: «Позор любому, кто рекомендует использовать Date, Calendar и SimpleDateFormat».   -  person Basil Bourque    schedule 26.10.2016
comment
@BasilBourque OP попросил более простой и приятный способ получить временную дельту; быстрый двухстрочный diff кажется проще / приятнее, чем требовать внешней зависимости.   -  person plátano plomo    schedule 12.11.2016
comment
Хотя Joda Time, вероятно, был хорошим ответом, когда был задан вопрос, сегодня лучший ответ для любого, кто может использовать Java 8, - использовать java.time.Period и / или Duration. См. ответ Базиля Бурка ниже.   -  person Ole V.V.    schedule 16.02.2017
comment
Вы также можете посмотреть Расчет дней между двумя датами в Java 8. И все же избегайте любой внешней зависимости.   -  person Ole V.V.    schedule 12.04.2017


Ответы (43)


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

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

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

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

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

person notnoop    schedule 12.10.2009
comment
кстати - вы имеете в виду Comparable.compareTo(), а не Comparable.compare(). - person Scott Morrison; 13.12.2010
comment
В Joda-Time есть три класса для отображения промежутка времени различными способами: интервал, продолжительность и период. В этом правильном ответе обсуждаются первые два. См. мой ответ для получения информации о Period. - person Basil Bourque; 25.06.2014
comment
Java 8 имеет новый api даты и времени, такой как joda. - person tbodt; 26.06.2014
comment
Новый пакет java.time на Java 8 вдохновлен Joda-Time, но не является заменой. У каждого есть свои плюсы и минусы. К счастью, вам не нужно выбирать между ними. Используйте каждую из них с учетом ее сильных сторон, если вы будете осторожны со своими import утверждениями. См. этот другой ответ для примера java.time. - person Basil Bourque; 26.06.2014
comment
К вашему сведению, проект Joda-Time теперь находится в режим обслуживания, при этом команда советует перейти на классы java.time. См. Руководство Oracle. - person Basil Bourque; 05.05.2017

Простой diff (без библиотеки)

/**
 * 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 - это java.util.concurrent.TimeUnit, стандартное перечисление Java, которое изменяется от нанометров до нескольких дней.


Удобочитаемый diff (без библиотеки)

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, вы можете получить разницу для двух мгновенных дат (с поддержкой 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()
person Sebastien Lorber    schedule 18.05.2012
comment
Ух ты, действительно можешь научить старую собаку новым трюкам! Никогда не слышал об этом раньше, очень полезно для перевода разницы дат в значимые строки. - person Jeremy Goodell; 03.03.2014
comment
@SebastienLorber Есть ли в TimeUnit способ рассчитать разницу таким образом? Будильник установлен на 3 дня, 4 часа и 12 минут с этого момента. - person likejudo; 15.04.2014
comment
блестящий материал действительно сэкономил мне много времени. Ценю вашу помощь. - person Lyju I Edwinson; 25.08.2014
comment
Я потратил 3 дня своей жизни на Java Dates, и я просто выбросил их и заменил этим. Спасибо. - person user1091524; 03.05.2015
comment
Это лучший ответ, который я видел с тех пор, как зашел в stackoverflow! : D: D: D - person Cold; 06.07.2015
comment
сообщение в блоге, на которое вы ссылаетесь, к сожалению, невозможно просмотреть? - person Stefan Hendriks; 05.04.2018

int diffInDays = (int)( (newerDate.getTime() - olderDate.getTime()) 
                 / (1000 * 60 * 60 * 24) )

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

person Michael Borgwardt    schedule 16.08.2010
comment
На самом деле это не работает правильно в Android. Существуют ошибки округления. Пример с 19 по 21 мая говорит 1 день, потому что он приводит к 1.99 к 1. Используйте round перед преобразованием в int. - person Pratik Mandrekar; 01.05.2013
comment
Это лучший и самый простой ответ. При вычислении разницы между двумя датами местные часовые пояса вычитают друг друга ... так что правильный ответ (как двойной) дается просто ((double) (newer.getTime () - old.getTime ()) / (86400.0 * 1000.0); ... как двойное число, у вас также есть дробный день, который можно легко преобразовать в ЧЧ: ММ: сс. - person scottb; 16.05.2013
comment
@scottb: проблема с местными датами заключается в том, что у вас может быть летнее время, что означает, что в некоторые дни есть 23 или 25 часов, что потенциально может испортить результат. - person Michael Borgwardt; 16.05.2013
comment
@Steve: мне 28, когда я определяю их как новую Date (115, 2, 26); (обратите внимание на документацию по API для параметров). Возможно ли, что вы разбираете их, используя формат даты в США и в мягком режиме, так что 26/03/2015 интерпретируется как 3-й день 26-го месяца 2015 года? - person Michael Borgwardt; 07.04.2015
comment
Извините, это было -21, а не 1: Date startDate = new Date(); Date endDate = new Date(); DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy"); int rosterDays = 0; try { startDate = formatter.parse("26/02/2015"); endDate = formatter.parse("26/03/2015"); rosterDays = (int)(endDate.getTime() - startDate.getTime()) / ((1000 * 60 * 60 * 24)); } catch (ParseException e) {} System.out.println("rosterDays = " + rosterDays); Извините за форматирование, я не вижу, как его лучше отформатировать! - person Steve; 09.04.2015
comment
@Steve: когда я запускаю этот точный код, на выходе получается 28. Он зависит от локали, но я не могу понять, как он вообще может вывести -21. Что вы получаете при запуске System.out.println (Locale.getDefault (Locale.Category.FORMAT)) ;? - person Michael Borgwardt; 09.04.2015
comment
Привет, Майкл, я получаю en_AU при выводе Locale. Вот полный код PasteBin: pastebin.com/QQjU2T4k - person Steve; 13.04.2015
comment
@ Стив: хм, не знаю, почему раньше у меня был другой результат, но теперь я могу воспроизвести вашу ошибку. Фигурные скобки в вашем коде отличаются от моего ответа, что приводит к преобразованию (endDate.getTime() - startDate.getTime()) в int вместо окончательного результата, и вы получаете целочисленное переполнение. - person Michael Borgwardt; 13.04.2015
comment
Мне просто нужно было посчитать секунды и миллисекунды для простой проверки времени производительности, я сделал double diffInSeconds = ((after.getTime() - b4.getTime()) / 1000d); - person Joey Baruch; 01.03.2017
comment
getTime() возвращает длинное число, поэтому, вероятно, лучше использовать в этих вычислениях длинное число. - person ThomasW; 28.04.2017

Использование созданной инфраструктуры 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.

person Vitalii Fedorenko    schedule 20.04.2014
comment
Это или используйте Period вместо Duration для дат. - person Aphex; 09.12.2016
comment
хорошо :) мне этот нравится больше - person Deunz; 08.01.2021

Вам нужно более четко определить вашу проблему. Вы можете просто взять количество миллисекунд между двумя Date объектами и разделить его на количество миллисекунд за 24 часа, например ... но:

  • При этом не будут учитываться часовые пояса - Date всегда в формате UTC.
  • При этом не учитывается переход на летнее время (например, могут быть дни длиной всего 23 часа).
  • Даже в рамках всемирного координированного времени, сколько дней осталось с 11 вечера 16 августа по 2 часа ночи 18 августа? Это всего лишь 27 часов, значит ли это, что один день? Или это должно быть три дня, потому что оно охватывает три даты?
person Jon Skeet    schedule 16.08.2010
comment
Я думал java.util. Дата была просто крошечной оболочкой вокруг представления в миллисекундах времени, интерпретируемого в локальном (по умолчанию) часовом поясе. Распечатка даты дает мне представление о местном часовом поясе. Я здесь запутался? - person Adriaan Koster; 16.08.2010

tl;dr

Преобразуйте устаревшие java.util.Date объекты на их замену, java.time.Instant. Затем рассчитайте прошедшее время как Duration.

Duration d = 
    Duration.between(                   // Calculate the span of time between two moments as a number of hours, minutes, and seconds.
        myJavaUtilDate.toInstant() ,    // Convert legacy class to modern class by calling new method added to the old class.
        Instant.now()                   // Capture the current moment in UTC. About two and a half hours later in this example.
    )
;

d.toString (): PT2H34M56S

d.toMinutes (): 154

d.toMinutesPart (): 34

Формат ISO 8601: PnYnMnDTnHnMnS

Разумный стандарт ISO 8601 определяет краткое текстовое представление промежутка времени в виде количества лет, месяцев, дней, часов и т. д. Стандарт называет такой промежуток продолжительностью. Формат - PnYnMnDTnHnMnS, где P означает «Период», T отделяет часть даты от части времени, а между ними находятся числа, за которыми следует буква.

Примеры:

  • P3Y6M4DT12H30M5S
    три года, шесть месяцев, четыре дня, двенадцать часов, тридцать минут и пять секунд
  • PT4H30M
    Четыре с половиной часа

java.time

Фреймворк java.time, встроенный в Java 8 и более поздние версии заменяют неудобные старые классы _11 _ / _ 12_. Новые классы вдохновлены очень успешной структурой Joda-Time, которая должна стать ее преемницей, аналогичной по концепции, но с новой архитектурой. Определено JSR 310. Расширен проектом ThreeTen-Extra. См. Руководство.

Момент

Класс Instant представляет момент на временной шкале. в UTC с разрешением наносекунды (до девяти (9) цифр десятичной дроби).

Instant instant = Instant.now() ;  // Capture current moment in UTC.

Лучше избегать устаревших классов, таких как _15 _ / _ 16_. Но если вам необходимо взаимодействовать со старым кодом, который еще не обновлен до java.time, конвертируйте туда и обратно. Вызов новых методов преобразования, добавленных к старым классам. Для перехода от java.util.Date к _ 18_, позвоните _ 19_.

Instant instant = myJavaUtilDate.toInstant() ;  // Convert from legacy `java.util.Date` class to modern `java.time.Instant` class.

Промежуток времени

Классы java.time разделили идею представления промежутка времени в виде числа лет, месяцев, дней, часов, минут, секунд на две половины:

  • Period для лет, месяцев, дней
  • Duration для дней, часов, минут, секунд.

Вот пример.

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
ZonedDateTime future = now.plusMinutes ( 63 );
Duration duration = Duration.between ( now , future );

Выгрузить в консоль.

И Period, и Duration используют стандарт ISO 8601 для создания строкового представления своего значения.

System.out.println ( "now: " + now + " to future: " + now + " = " + duration );

сейчас: 2015-11-26T00: 46: 48.016-05: 00 [Америка / Монреаль] в будущее: 2015-11-26T00: 46: 48.016-05: 00 [Америка / Монреаль] = PT1H3M

В Java 9 к Duration добавлены методы для получения части дней, часов, минут и секунд.

Вы можете получить общее количество дней, часов, минут, секунд, миллисекунд или наносекунд во всей продолжительности.

long totalHours = duration.toHours();

В Java 9 класс Duration получает новые методы для возврата различных частей дня, часы, минуты, секунды, миллисекунды / наносекунды. Вызовите to…Part методы: toDaysPart(), toHoursPart() и так далее.

ChronoUnit

Если вас интересует только более простая и крупная детализация времени, например «количество прошедших дней», используйте _ 34_ перечисление.

long daysElapsed = ChronoUnit.DAYS.between( earlier , later );

Другой пример.

Instant now = Instant.now();
Instant later = now.plus( Duration.ofHours( 2 ) );
…
long minutesElapsed = ChronoUnit.MINUTES.between( now , later );

120


О java.time

Создана структура java.time в Java 8 и новее. Эти классы заменяют неудобные старые устаревшие классы даты и времени, такие как _ 37_, _ 38_, & _ 39_.

Проект Joda-Time теперь в режим обслуживания, советует перейти на java.time.

Чтобы узнать больше, см. Учебник Oracle. И поищите в Stack Overflow множество примеров и объяснений. Спецификация - JSR 310.

Где взять классы java.time?

  • Java SE 8 and SE 9 and later
    • Built-in.
    • Часть стандартного Java API со встроенной реализацией.
    • В Java 9 добавлены некоторые незначительные функции и исправления.
  • Java SE 6 and SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является испытательной площадкой для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, например _40 _, YearWeek, _ 42_ и подробнее.


Джода-Тайм

ОБНОВЛЕНИЕ: проект Joda-Time теперь находится в режим обслуживания, при этом команда советует перейти на java.time. Я оставляю этот раздел нетронутым для истории.

Библиотека Joda-Time по умолчанию использует ISO 8601. Его класс Period анализирует и генерирует эти строки PnYnMnDTnHnMnS.

DateTime now = DateTime.now(); // Caveat: Ignoring the important issue of time zones.
Period period = new Period( now, now.plusHours( 4 ).plusMinutes( 30));
System.out.println( "period: " + period );

Оказывает:

period: PT4H30M
person Basil Bourque    schedule 23.03.2014
comment
Забавно, что вы начали стену текста, не имеющего отношения к вопросу, с помощью tl; доктор Вопрос не в том, как получить метку времени от X назад или в X единицах времени, а в том, как получить дельту между двумя датами. Вот и все. - person Buffalo; 19.03.2018
comment
@Buffalo Я не понимаю вашего комментария. Мой ответ включает Period, Duration и ChronoUnit, три класса, целью которых является определение разницы между точками времени. Укажите, пожалуйста, какие части моей «стены текста» неуместны. И вы ошибаетесь, говоря, что в вопросе запрашивалась «дельта между датами»: в вопросе запрашивалась дельта между Date объектами, которые являются моментами даты и времени, а не «датами», несмотря на неудачное название этого класса. - person Basil Bourque; 19.03.2018
comment
В вашем комментарии нет ничего, что могло бы обрабатывать два существующих объекта java.util.Date. Я пробовал использовать различные фрагменты в своем коде и не нашел ничего, что использует объект java.util.Date. - person Buffalo; 21.03.2018
comment
@Buffalo Достаточно честно, хорошая критика. Я добавил код в раздел tl; dr, конвертирующий из java.util.Date в Instant (просто позвоните .toInstant). И я добавил раздел Moment, чтобы объяснить. Вы упомянули пару Date объектов, но на самом деле Вопрос использует только один существующий объект Date, а затем фиксирует текущий момент, поэтому я сделал то же самое. Спасибо за ответ! Совет: откажитесь от использования Date - эти устаревшие классы действительно представляют собой ужасный беспорядок. - person Basil Bourque; 21.03.2018

Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();

https://www.joda.org/joda-time/faq.html#datediff

person Adriano Bacha    schedule 28.12.2010
comment
К вашему сведению, проект Joda-Time теперь находится в режим обслуживания, при этом команда советует перейти на классы java.time. - person Basil Bourque; 16.04.2017

Чуть более простая альтернатива:

System.currentTimeMillis() - oldDate.getTime()

Насчет «приятнее»: ну а что именно вам нужно? Проблема с представлением продолжительности времени в виде количества часов и дней и т. Д. Заключается в том, что это может привести к неточностям и неправильным ожиданиям из-за сложности дат (например, дни могут иметь 23 или 25 часов из-за перехода на летнее время).

person Michael Borgwardt    schedule 12.10.2009

Использование миллисекундного подхода может вызвать проблемы в некоторых регионах.

Например, разница между двумя датами 24.03.2007 и 25.03.2007 должна составлять 1 день;

Однако, используя миллисекундный маршрут, вы получите 0 дней, если запустите его в Великобритании!

/** Manual Method - YIELDS INCORRECT RESULTS - DO NOT USE**/  
/* This method is used to find the no of days between the given dates */  
public long calculateDays(Date dateEarly, Date dateLater) {  
   return (dateLater.getTime() - dateEarly.getTime()) / (24 * 60 * 60 * 1000);  
} 

Лучший способ реализовать это - использовать java.util.Calendar

/** Using Calendar - THE CORRECT WAY**/  
public static long daysBetween(Calendar startDate, Calendar endDate) {  
  Calendar date = (Calendar) startDate.clone();  
  long daysBetween = 0;  
  while (date.before(endDate)) {  
    date.add(Calendar.DAY_OF_MONTH, 1);  
    daysBetween++;  
  }  
  return daysBetween;  
}  
person zasadnyy    schedule 21.11.2011
comment
Не могли бы вы указать на первоначального автора этого кода и третьего предложения, чья запись в блоге датирована 2007 годом < / а>? - person wchargin; 15.01.2012
comment
Разве это не немного неэффективно? - person Gangnus; 11.01.2013
comment
@marcolopes - Вы ошибаетесь - потому что календарные месяцы отсчитываются от нуля. Я уверен, что вы имеете в виду март / апрель, но вы тестируете апрель / июнь, то есть 31. На всякий случай напишите это как ›новый GregorianCalendar (2014, Calendar.MARCH, 1) .... - person Uncle Iroh; 25.06.2014
comment
@UncleIroh, ты прав! Я упустил этот важный факт (календарные месяцы отсчитываются от нуля). Я должен еще раз повторить этот вопрос. - person marcolopes; 26.06.2014
comment
Предупреждение: этот метод может вернуть неверный результат, если поля времени не равны нулю и пересечена граница перехода на летнее время. - person Jool; 29.08.2016

Есть много способов найти разницу между датой и временем. Один из самых простых известных мне способов:

      Calendar calendar1 = Calendar.getInstance();
      Calendar calendar2 = Calendar.getInstance();
      calendar1.set(2012, 04, 02);
      calendar2.set(2012, 04, 04);
      long milsecs1= calendar1.getTimeInMillis();
      long milsecs2 = calendar2.getTimeInMillis();
      long diff = milsecs2 - milsecs1;
      long dsecs = diff / 1000;
      long dminutes = diff / (60 * 1000);
      long dhours = diff / (60 * 60 * 1000);
      long ddays = diff / (24 * 60 * 60 * 1000);

      System.out.println("Your Day Difference="+ddays);

Оператор печати - это просто пример - вы можете отформатировать его по своему усмотрению.

person JDGuide    schedule 03.04.2012
comment
@ манодж кумар бардхан: добро пожаловать в переполнение стека: как вы видите, этому вопросу и ответам уже много лет. Ваш ответ должен добавить больше к вопросу / ответу, чем существующие. - person Jayan; 03.04.2012
comment
А как насчет дней, в которых 23 или 25 часов связано с переходом на летнее время? - person Joni; 15.06.2012

Поскольку все ответы здесь верны, но используются устаревшие java или сторонние библиотеки, такие как joda или аналогичные, я просто выберу другой способ, используя новый java.time классы в Java 8 и новее. См. Учебник Oracle.

Используйте LocalDate и _ 2_:

LocalDate d1 = LocalDate.of(2017, 5, 1);
LocalDate d2 = LocalDate.of(2017, 5, 18);

long days = ChronoUnit.DAYS.between(d1, d2);
System.out.println( days );
person ΦXocę 웃 Пepeúpa ツ    schedule 18.05.2017
comment
приятно :) этот нис тот, который мне нравится больше всего !!! - person Deunz; 08.01.2021

Если вы не хотите использовать JodaTime или аналогичный, вероятно, лучшим решением будет следующее:

final static long MILLIS_PER_DAY = 24 * 3600 * 1000;
long msDiff= date1.getTime() - date2.getTime();
long daysDiff = Math.round(msDiff / ((double)MILLIS_PER_DAY));

Количество мс в день не всегда одинаково (из-за перехода на летнее время и дополнительных секунд), но оно очень близко, и, по крайней мере, отклонения из-за перехода на летнее время отменяются в течение более длительных периодов. Поэтому деление, а затем округление дадут правильный результат (по крайней мере, если используемый локальный календарь не содержит странных скачков времени, кроме летнего времени и дополнительных секунд).

Обратите внимание, что это по-прежнему предполагает, что date1 и date2 установлены на одно и то же время дня. Для разного времени суток вам сначала нужно определить, что означает «разница дат», как указал Джон Скит.

person sleske    schedule 30.08.2010
comment
Проблема в date1.getTime() против date2.getTime(). Таким образом, при сравнении с 2016-03-03 по 2016-03-31 будет вычислено 27 дней, в то время как вам нужно 28 дней. - person malat; 29.03.2018
comment
@malat: Извините, я не могу следить. Я просто попробовал - сравнение с 2016-03-03 по 2016-03-31 с моим кодом вычисляет 28 дней. Если он вычисляет что-то еще в вашем примере, подумайте о том, чтобы задать это как отдельный вопрос. - person sleske; 29.03.2018
comment
Кроме того, вы прочитали мою оговорку? это по-прежнему предполагает, что date1 и date2 установлены на одно и то же время дня. Возможно, вы использовали разное время дня в тесте? - person sleske; 29.03.2018
comment
Ах да! Я пропустил трюк с Math.round(), который кажется безопасным для календарей «реального мира». Простите за шум. - person malat; 29.03.2018

Вычитание дат в миллисекундах работает (как описано в другом сообщении), но вы должны использовать HOUR_OF_DAY, а не HOUR при очистке временных частей ваших дат:

public static final long MSPERDAY = 60 * 60 * 24 * 1000;
...
final Calendar dateStartCal = Calendar.getInstance();
dateStartCal.setTime(dateStart);
dateStartCal.set(Calendar.HOUR_OF_DAY, 0); // Crucial.
dateStartCal.set(Calendar.MINUTE, 0);
dateStartCal.set(Calendar.SECOND, 0);
dateStartCal.set(Calendar.MILLISECOND, 0);
final Calendar dateEndCal = Calendar.getInstance();
dateEndCal.setTime(dateEnd);
dateEndCal.set(Calendar.HOUR_OF_DAY, 0); // Crucial.
dateEndCal.set(Calendar.MINUTE, 0);
dateEndCal.set(Calendar.SECOND, 0);
dateEndCal.set(Calendar.MILLISECOND, 0);
final long dateDifferenceInDays = ( dateStartCal.getTimeInMillis()
                                  - dateEndCal.getTimeInMillis()
                                  ) / MSPERDAY;
if (dateDifferenceInDays > 15) {
    // Do something if difference > 15 days
}
person Malcolm Boekhoff    schedule 12.08.2013
comment
Это лучший способ определить разницу между двумя календарными датами, не выходя за рамки стандартных библиотек. В большинстве других ответов день рассматривается как произвольный 24-часовой период. Если високосные секунды когда-либо должны быть вычтены, а не добавлены, окончательный расчет может отличаться на единицу из-за усечения, поскольку абсолютная разница может быть немного меньше целого числа, кратного MSPERDAY. - person JulianSymes; 30.01.2014

Взгляните на Joda Time, который представляет собой улучшенный API даты / времени для Java и должен отлично работают со Scala.

person Rob H    schedule 12.10.2009
comment
заменен на java.time (JSR-310) в Java 8 - person malat; 29.03.2018

Позвольте мне показать разницу между Joda Interval и Days:

DateTime start = new DateTime(2012, 2, 6, 10, 44, 51, 0);
DateTime end = new DateTime(2012, 2, 6, 11, 39, 47, 1);
Interval interval = new Interval(start, end);
Period period = interval.toPeriod();
System.out.println(period.getYears() + " years, " + period.getMonths() + " months, " + period.getWeeks() + " weeks, " + period.getDays() + " days");
System.out.println(period.getHours() + " hours, " + period.getMinutes() + " minutes, " + period.getSeconds() + " seconds ");
//Result is:
//0 years, 0 months, *1 weeks, 1 days*
//0 hours, 54 minutes, 56 seconds 

//Period can set PeriodType,such as PeriodType.yearMonthDay(),PeriodType.yearDayTime()...
Period p = new Period(start, end, PeriodType.yearMonthDayTime());
System.out.println(p.getYears() + " years, " + p.getMonths() + " months, " + p.getWeeks() + " weeks, " + p.getDays() + "days");
System.out.println(p.getHours() + " hours, " + p.getMinutes() + " minutes, " + p.getSeconds() + " seconds ");
//Result is:
//0 years, 0 months, *0 weeks, 8 days*
//0 hours, 54 minutes, 56 seconds 
person user674158    schedule 06.02.2012

Если вам нужна отформатированная строка возврата, например «2 дня 03ч 42м 07с», попробуйте следующее:

public String fill2(int value)
{
    String ret = String.valueOf(value);

    if (ret.length() < 2)
        ret = "0" + ret;            
    return ret;
}

public String get_duration(Date date1, Date date2)
{                   
    TimeUnit timeUnit = TimeUnit.SECONDS;

    long diffInMilli = date2.getTime() - date1.getTime();
    long s = timeUnit.convert(diffInMilli, TimeUnit.MILLISECONDS);

    long days = s / (24 * 60 * 60);
    long rest = s - (days * 24 * 60 * 60);
    long hrs = rest / (60 * 60);
    long rest1 = rest - (hrs * 60 * 60);
    long min = rest1 / 60;      
    long sec = s % 60;

    String dates = "";
    if (days > 0) dates = days + " Days ";

    dates += fill2((int) hrs) + "h ";
    dates += fill2((int) min) + "m ";
    dates += fill2((int) sec) + "s ";

    return dates;
}
person Ingo    schedule 04.10.2013
comment
Зачем катить свои собственные, когда Joda-Time предоставляет Period класс уже написан и отлажен? - person Basil Bourque; 23.03.2014
comment
Зачем мне загружать библиотеку с размером сжатого файла 4,1 МБ и добавлять ее в свой проект, если мне нужно всего 32 строки кода ??? - person Ingo; 30.03.2014
comment
Потому что Joda-Time похож на картофельные чипсы: вы не можете съесть только один. Вы будете использовать Joda-Time повсюду. И потому, что Joda-Time - это хорошо протестированный и хорошо зашитый код. И поскольку Joda-Time анализирует и генерирует стандартные строки ISO 8601 Duration, которые могут быть полезны для сериализация или сообщение этих значений. И потому, что Joda-Time включает средства форматирования для печати локализованных представлений этих значений. - person Basil Bourque; 19.12.2014
comment
Не весь ваш код протестирован. std выше не определено. - person Basil Bourque; 21.12.2014
comment
@Basil Bourque: Спасибо за подсказку. Я исправил источник. Эта ошибка возникла из-за перевода на английский. - person Ingo; 21.12.2014
comment
Я только что провел небольшое тестирование вашего кода (после изменения std на hrs) по сравнению с Joda-Time. Все прошло хорошо, ваш код согласован с Joda-Time в каждом из моих тестовых случаев. Но я по-прежнему рекомендую не использовать вашу собственную библиотеку даты и времени (поскольку это слишком рискованно, неэффективно, много желательных функций в Joda-Time, таких как простое управление часовыми поясами). - person Basil Bourque; 21.12.2014
comment
@Basil Bourque; Спасибо за тестирование. Я использую свою функцию get_duration во многих случаях без каких-либо проблем также на других языках, таких как c ++, c #, delphi и т. Д. Но если вам нравится Joda Time, используйте его :-) - person Ingo; 21.12.2014

Примечание: startDate и endDates -> java.util.Date

import org.joda.time.Duration;
import org.joda.time.Interval;
// Use .getTime() unless it is a joda DateTime object
Interval interval = new Interval(startDate.getTime(), endDate.getTime());
Duration period = interval.toDuration();
//gives the number of days elapsed between start 
period.getStandardDays();

и дата окончания

Как и в днях, вы также можете получить часы, минуты и секунды.

period.getStandardHours();
period.getStandardMinutes();
period.getStandardSeconds();
person Shravan Ramamurthy    schedule 06.01.2015

Посмотрите пример здесь http://www.roseindia.net/java/beginners/DateDifferent.shtml Этот пример показывает разницу в днях, часах, минутах, секундах и миллисекундах :).

import java.util.Calendar;
import java.util.Date;

public class DateDifferent {
    public static void main(String[] args) {
        Date date1 = new Date(2009, 01, 10);
        Date date2 = new Date(2009, 07, 01);
        Calendar calendar1 = Calendar.getInstance();
        Calendar calendar2 = Calendar.getInstance();
        calendar1.setTime(date1);
        calendar2.setTime(date2);
        long milliseconds1 = calendar1.getTimeInMillis();
        long milliseconds2 = calendar2.getTimeInMillis();
        long diff = milliseconds2 - milliseconds1;
        long diffSeconds = diff / 1000;
        long diffMinutes = diff / (60 * 1000);
        long diffHours = diff / (60 * 60 * 1000);
        long diffDays = diff / (24 * 60 * 60 * 1000);
        System.out.println("\nThe Date Different Example");
        System.out.println("Time in milliseconds: " + diff + " milliseconds.");
        System.out.println("Time in seconds: " + diffSeconds + " seconds.");
        System.out.println("Time in minutes: " + diffMinutes + " minutes.");
        System.out.println("Time in hours: " + diffHours + " hours.");
        System.out.println("Time in days: " + diffDays + " days.");
    }
}
person YoK    schedule 16.08.2010
comment
-1 Это неверно, если экземпляры Date не были получены из времени UTC. См. Ответ Джона Скита. - person sleske; 30.08.2010

Используйте часовой пояс GMT, чтобы получить экземпляр Calendar, установите время, используя метод set класса Calendar. Часовой пояс GMT имеет смещение 0 (не очень важно), а флаг перехода на летнее время установлен в значение false.

    final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));

    cal.set(Calendar.YEAR, 2011);
    cal.set(Calendar.MONTH, 9);
    cal.set(Calendar.DAY_OF_MONTH, 29);
    cal.set(Calendar.HOUR, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    final Date startDate = cal.getTime();

    cal.set(Calendar.YEAR, 2011);
    cal.set(Calendar.MONTH, 12);
    cal.set(Calendar.DAY_OF_MONTH, 21);
    cal.set(Calendar.HOUR, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    final Date endDate = cal.getTime();

    System.out.println((endDate.getTime() - startDate.getTime()) % (1000l * 60l * 60l * 24l));
person Michal    schedule 27.12.2011
comment
Не забудьте обнулить миллисекунду, иначе это хороший ответ в контексте старых классов java.util.Date и т. Д. Использование хака для установки часового пояса на GMT делает код нечувствительным к эффектам перехода на летнее время. - person Meno Hochschild; 09.12.2016

Следующий код может дать вам желаемый результат:

String startDate = "Jan 01 2015";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd yyyy");
LocalDate date = LocalDate.parse(startDate, formatter);

String currentDate = "Feb 11 2015";
LocalDate date1 = LocalDate.parse(currentDate, formatter);

System.out.println(date1.toEpochDay() - date.toEpochDay());
person Vishal Ganjare    schedule 19.02.2015
comment
Можете ли вы объяснить, что именно делает ваш код? Кажется, вопрос задается о разнице во времени, и на первый взгляд может показаться, что ваш код возвращает дневную дельту? - person GHC; 19.02.2015

Лучшее, что можно сделать, это

(Date1-Date2)/86 400 000 

Это число - количество миллисекунд в день.

Одна дата-другая дата дает вам разницу в миллисекундах.

Соберите ответ в переменной double.

person Revanth Kumar    schedule 27.10.2014
comment
Да, почему бы и нет? Я в некотором роде не понимаю сути вопроса: OP имеет разницу в мс ... и есть определенное количество мс в день (нормально с некоторыми астрономическими корректировками один раз в синюю луну, но OP не Я не говорю, что он должен быть настолько точным, насколько это нужно астрономам ...) - person mike rodent; 25.02.2017

Вот правильное решение Java 7 в O (1) без каких-либо зависимостей.

public static int countDaysBetween(Date date1, Date date2) {

    Calendar c1 = removeTime(from(date1));
    Calendar c2 = removeTime(from(date2));

    if (c1.get(YEAR) == c2.get(YEAR)) {

        return Math.abs(c1.get(DAY_OF_YEAR) - c2.get(DAY_OF_YEAR)) + 1;
    }
    // ensure c1 <= c2
    if (c1.get(YEAR) > c2.get(YEAR)) {
        Calendar c = c1;
        c1 = c2;
        c2 = c;
    }
    int y1 = c1.get(YEAR);
    int y2 = c2.get(YEAR);
    int d1 = c1.get(DAY_OF_YEAR);
    int d2 = c2.get(DAY_OF_YEAR);

    return d2 + ((y2 - y1) * 365) - d1 + countLeapYearsBetween(y1, y2) + 1;
}

private static int countLeapYearsBetween(int y1, int y2) {

    if (y1 < 1 || y2 < 1) {
        throw new IllegalArgumentException("Year must be > 0.");
    }
    // ensure y1 <= y2
    if (y1 > y2) {
        int i = y1;
        y1 = y2;
        y2 = i;
    }

    int diff = 0;

    int firstDivisibleBy4 = y1;
    if (firstDivisibleBy4 % 4 != 0) {
        firstDivisibleBy4 += 4 - (y1 % 4);
    }
    diff = y2 - firstDivisibleBy4 - 1;
    int divisibleBy4 = diff < 0 ? 0 : diff / 4 + 1;

    int firstDivisibleBy100 = y1;
    if (firstDivisibleBy100 % 100 != 0) {
        firstDivisibleBy100 += 100 - (firstDivisibleBy100 % 100);
    }
    diff = y2 - firstDivisibleBy100 - 1;
    int divisibleBy100 = diff < 0 ? 0 : diff / 100 + 1;

    int firstDivisibleBy400 = y1;
    if (firstDivisibleBy400 % 400 != 0) {
        firstDivisibleBy400 += 400 - (y1 % 400);
    }
    diff = y2 - firstDivisibleBy400 - 1;
    int divisibleBy400 = diff < 0 ? 0 : diff / 400 + 1;

    return divisibleBy4 - divisibleBy100 + divisibleBy400;
}


public static Calendar from(Date date) {

    Calendar c = Calendar.getInstance();
    c.setTime(date);

    return c;
}


public static Calendar removeTime(Calendar c) {

    c.set(HOUR_OF_DAY, 0);
    c.set(MINUTE, 0);
    c.set(SECOND, 0);
    c.set(MILLISECOND, 0);

    return c;
}
person suxumuxu    schedule 28.04.2017

Пройдя через все остальные ответы, чтобы сохранить тип даты Java 7, но быть более точным / стандартным с подходом Java 8 diff,

public static long daysBetweenDates(Date d1, Date d2) {
    Instant instant1 = d1.toInstant();
    Instant instant2 = d2.toInstant();
    long diff = ChronoUnit.DAYS.between(instant1, instant2);
    return diff;
}
person gene b.    schedule 05.11.2018

Это, вероятно, самый простой способ сделать это - возможно, это потому, что я уже некоторое время кодирую на Java (с ее, по общему признанию, неуклюжими библиотеками даты и времени), но этот код мне кажется «простым и приятным»!

Довольны ли вы результатом, возвращаемым в миллисекундах, или, в рамках вашего вопроса, вы бы предпочли, чтобы он возвращался в каком-либо альтернативном формате?

person Andrzej Doyle    schedule 12.10.2009

Без использования стандартного API, нет. Вы можете сделать что-то вроде этого:

class Duration {
    private final TimeUnit unit;
    private final long length;
    // ...
}

Или вы можете использовать Joda:

DateTime a = ..., b = ...;
Duration d = new Duration(a, b);
person gustafc    schedule 12.10.2009

Просто чтобы ответить на первоначальный вопрос:

Поместите следующий код в функцию типа Long getAge () {}

Date dahora = new Date();
long MillisToYearsByDiv = 1000l *60l * 60l * 24l * 365l;
long javaOffsetInMillis = 1990l * MillisToYearsByDiv;
long realNowInMillis = dahora.getTime() + javaOffsetInMillis;
long realBirthDayInMillis = this.getFechaNac().getTime() + javaOffsetInMillis;
long ageInMillis = realNowInMillis - realBirthDayInMillis;

return ageInMillis / MillisToYearsByDiv;

Здесь самое главное - работать с длинными числами при умножении и делении. И, конечно же, смещение, которое Java применяет в своем исчислении дат.

:)

person MugiWara No Carlos    schedule 21.08.2015

Поскольку вопрос помечен тегом Scala,

import scala.concurrent.duration._
val diff = (System.currentTimeMillis() - oldDate.getTime).milliseconds
val diffSeconds = diff.toSeconds
val diffMinutes = diff.toMinutes
val diffHours = diff.toHours
val diffDays = diff.toDays
person VasiliNovikov    schedule 24.11.2015

попробуй это:

int epoch = (int) (new java.text.SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse("01/01/1970  00:00:00").getTime() / 1000);

вы можете редактировать строку в параметре методов parse ().

person sabbibJAVA    schedule 11.03.2013

Поскольку вы используете Scala, существует очень хорошая библиотека Scala Lamma. С Lamma вы можете вычесть дату напрямую с помощью оператора -

scala> Date(2015, 5, 5) - 2     // minus days by int
res1: io.lamma.Date = Date(2015,5,3)

scala> Date(2015, 5, 15) - Date(2015, 5, 8)   // minus two days => difference between two days
res2: Int = 7
person Max    schedule 10.06.2014

Просто используйте метод ниже с двумя объектами Date. Если вы хотите передать текущую дату, просто передайте new Date() в качестве второго параметра, так как он инициализируется текущим временем.

public String getDateDiffString(Date dateOne, Date dateTwo)
{
    long timeOne = dateOne.getTime();
    long timeTwo = dateTwo.getTime();
    long oneDay = 1000 * 60 * 60 * 24;
    long delta = (timeTwo - timeOne) / oneDay;

    if (delta > 0) {
        return "dateTwo is " + delta + " days after dateOne";
    }
    else {
        delta *= -1;
        return "dateTwo is " + delta + " days before dateOne";
     }
}

Кроме того, помимо количества дней, если вам нужна разница в других параметрах, используйте фрагмент ниже,

int year = delta / 365;
int rest = delta % 365;
int month = rest / 30;
rest = rest % 30;
int weeks = rest / 7;
int days = rest % 7;

P.S Код полностью взят из SO-ответа.

person Shubham A.    schedule 05.10.2015
comment
Рад видеть вас в StackOverflow. Пожалуйста, добавьте обсуждение вместе с опубликованным примером кода. Объясните, как работает ваш код, чем ваш ответ отличается от других, укажите на сложные концепции, дайте ссылку на документ и т. Д. StackOverflow - это нечто большее, чем библиотека фрагментов кода. - person Basil Bourque; 05.10.2015

Прочитав множество ответов и комментариев на этот вопрос, у меня сложилось впечатление, что нужно либо использовать время Джода, либо принимать во внимание некоторые особенности с переходом на летнее время и т. Д. Поскольку я не хотел делать ни одно из В итоге я написал несколько строк кода для вычисления разницы между двумя датами без использования каких-либо классов Java, связанных с датой или временем.

В приведенном ниже коде числа года, месяца и дня такие же, как в реальной жизни. Например, 24 декабря 2015 года год = 2015, месяц = ​​12 и день = 24.

Я хочу поделиться этим кодом на случай, если кто-то еще захочет его использовать. Существует 3 метода: 1) метод определения того, является ли данный год високосным; 2) метод вычисления количества данного дня по отношению к 1 января данного года; 3) метод расчета количества дней между любыми двумя датами с использованием метода 2 (число конечной даты минус число начальной даты).

Вот методы:

1)

public static boolean isLeapYear (int year) {
    //Every 4. year is a leap year, except if the year is divisible by 100 and not by 400
    //For example 1900 is not a leap year but 2000 is

    boolean result = false;

    if (year % 4 == 0) {
        result = true;
    }
    if (year % 100 == 0) {
        result = false;
    }
    if (year % 400 == 0) {
        result = true;
    }

    return result;

}

2)

public static int daysGoneSince (int yearZero, int year, int month, int day) {
    //Calculates the day number of the given date; day 1 = January 1st in the yearZero

    //Validate the input
    if (year < yearZero || month < 1 || month > 12 || day < 1 || day > 31) {
        //Throw an exception
        throw new IllegalArgumentException("Too many or too few days in month or months in year or the year is smaller than year zero");
    }
    else if (month == 4 || month == 6 || month == 9 || month == 11) {//Months with 30 days
        if (day == 31) {
            //Throw an exception
            throw new IllegalArgumentException("Too many days in month");
        }
    }
    else if (month == 2) {//February 28 or 29
        if (isLeapYear(year)) {
            if (day > 29) {
                //Throw an exception
                throw new IllegalArgumentException("Too many days in month");
            }
        }
        else if (day > 28) {
            //Throw an exception
            throw new IllegalArgumentException("Too many days in month");
        }
    }

    //Start counting days
    int days = 0;

    //Days in the target month until the target day
    days = days + day;

    //Days in the earlier months in the target year
    for (int i = 1; i < month; i++) {
        switch (i) {
            case 1: case 3: case 5:
            case 7: case 8: case 10:
            case 12:
                days = days + 31;
                break;
            case 2:
                days = days + 28;
                if (isLeapYear(year)) {
                    days = days + 1;
                }
                break;
            case 4: case 6: case 9: case 11:
                days = days + 30;
                break;
        }
    }

    //Days in the earlier years
    for (int i = yearZero; i < year; i++) {
        days = days + 365;
        if (isLeapYear(i)) {
            days = days + 1;
        }
    }

    return days;

}

3)

public static int dateDiff (int startYear, int startMonth, int startDay, int endYear, int endMonth, int endDay) {

    int yearZero;

    //daysGoneSince presupposes that the first argument be smaller or equal to the second argument
    if (10000 * startYear + 100 * startMonth + startDay > 10000 * endYear + 100 * endMonth + endDay) {//If the end date is earlier than the start date
        yearZero = endYear;
    }
    else {
        yearZero = startYear;
    }

    return daysGoneSince(yearZero, endYear, endMonth, endDay) - daysGoneSince(yearZero, startYear, startMonth, startDay);

}
person William Greendale    schedule 31.10.2015

Вы можете попробовать более ранние версии Java.

 public static String daysBetween(Date createdDate, Date expiryDate) {

        Calendar createdDateCal = Calendar.getInstance();
        createdDateCal.clear();
        createdDateCal.setTime(createdDate);

        Calendar expiryDateCal = Calendar.getInstance();
        expiryDateCal.clear();
        expiryDateCal.setTime(expiryDate);


        long daysBetween = 0;
        while (createdDateCal.before(expiryDateCal)) {
            createdDateCal.add(Calendar.DAY_OF_MONTH, 1);
            daysBetween++;
        }
        return daysBetween+"";
    }
person Kumar Abhishek    schedule 26.10.2016

Если вы хотите исправить проблему для диапазонов дат, которые пересекают границу летнего времени (например, одна дата в летнее время, а другая - в зимнее время), вы можете использовать это чтобы получить разницу в днях:

public static long calculateDifferenceInDays(Date start, Date end, Locale locale) {
    Calendar cal = Calendar.getInstance(locale);

    cal.setTime(start);
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    long startTime = cal.getTimeInMillis();

    cal.setTime(end);
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    long endTime = cal.getTimeInMillis();

    // calculate the offset if one of the dates is in summer time and the other one in winter time
    TimeZone timezone = cal.getTimeZone();
    int offsetStart = timezone.getOffset(startTime);
    int offsetEnd = timezone.getOffset(endTime);
    int offset = offsetEnd - offsetStart;

    return TimeUnit.MILLISECONDS.toDays(endTime - startTime + offset);
}
person Fabi    schedule 14.02.2019

Просто вызовите getTime для каждого, возьмите разницу и разделите на количество миллисекунд в день.

person PaulJWilliams    schedule 16.08.2010
comment
-1 Это неверно, если экземпляры Date не были получены из времени UTC. См. Ответ Джона Скита. - person sleske; 30.08.2010

Ниже приводится одно из решений, поскольку есть множество способов добиться этого:

  import java.util.*; 
   int syear = 2000;
   int eyear = 2000;
   int smonth = 2;//Feb
   int emonth = 3;//Mar
   int sday = 27;
   int eday = 1;
   Date startDate = new Date(syear-1900,smonth-1,sday);
   Date endDate = new Date(eyear-1900,emonth-1,eday);
   int difInDays = (int) ((endDate.getTime() - startDate.getTime())/(1000*60*60*24));
person kundan bora    schedule 19.03.2012

Ответ @Michael Borgwardt на самом деле не работает правильно в Android. Существуют ошибки округления. Пример с 19 по 21 мая говорит 1 день, потому что он приводит к 1.99 к 1. Используйте round перед преобразованием в int.

Исправить

int diffInDays = (int)Math.round(( (newerDate.getTime() - olderDate.getTime()) 
                 / (1000 * 60 * 60 * 24) ))

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

person Pratik Mandrekar    schedule 01.05.2013
comment
Пока обе отметки времени находятся в одном часовом поясе, тогда разница между датами будет одинаковой, независимо от того, скорректирована ли она для местного часового пояса от UTC или нет (корректировки вычитаются). Существует возможность корректировки результата на летнее время, но если вы начнете с предположения, что день составляет 86400 секунд, это действительно не имеет значения. - person scottb; 16.05.2013
comment
Не в этом суть ответа. Ответ Майкла Брогвардта приведет к неправильному результату, если вы не округлите его и не приведете к int в Android Java SDK. - person Pratik Mandrekar; 16.05.2013

public static void main(String[] args) {

    String dateStart = "01/14/2012 09:29:58";
    String dateStop = "01/14/2012 10:31:48";

    SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");

    Date d1 = null;
    Date d2 = null;

    try {
        d1 = format.parse(dateStart);
        d2 = format.parse(dateStop);

        DateTime date11 = new DateTime(d1);
        DateTime date22 = new DateTime(d2);
        int days = Days.daysBetween(date11.withTimeAtStartOfDay(), date22.withTimeAtStartOfDay()).getDays();
        int hours = Hours.hoursBetween(date11, date22).getHours() % 24;
        int minutes = Minutes.minutesBetween(date11, date22).getMinutes() % 60;
        int seconds = Seconds.secondsBetween(date11, date22).getSeconds() % 60;
        if (hours > 0 || minutes > 0 || seconds > 0) {
            days = days + 1;
        }

        System.out.println(days);

    } catch (Exception e) {
        e.printStackTrace();
    }

}

Это также даст разницу дат для того же дня

person spysr    schedule 22.11.2014
comment
Не могли бы вы пояснить дополнительную ценность вашего ответа? Кажется избыточным с этим ответом и этот ответ. И другие ответы кажутся лучше, например использование TimeUnit Служебный класс Enum. - person Basil Bourque; 23.11.2014
comment
На самом деле проблема в каждой из этих реализаций заключается в том, что она подсчитывает 0 для того же дня datetime ... но с этим вы можете получить разницу в тот же день, что и 1, кроме того, это зависит от @BasilBourque - person spysr; 10.12.2014

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

вот метод подсчета, не такой эффективный, как некоторые другие, но, похоже, он работает для меня и также учитывает DST.

public static String getOffsetAsString( Calendar cNow, Calendar cThen) {
    Calendar cBefore;
    Calendar cAfter;
    if ( cNow.getTimeInMillis() < cThen.getTimeInMillis()) {
        cBefore = ( Calendar) cNow.clone();
        cAfter = cThen;
    } else {
        cBefore = ( Calendar) cThen.clone();
        cAfter = cNow;
    }
    // compute diff
    Map<Integer, Long> diffMap = new HashMap<Integer, Long>();
    int[] calFields = { Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND};
    for ( int i = 0; i < calFields.length; i++) {
        int field = calFields[ i];
        long    d = computeDist( cAfter, cBefore, field);
        diffMap.put( field, d);
    }
    final String result = String.format( "%dY %02dM %dT %02d:%02d:%02d.%03d",
            diffMap.get( Calendar.YEAR), diffMap.get( Calendar.MONTH), diffMap.get( Calendar.DAY_OF_MONTH), diffMap.get( Calendar.HOUR_OF_DAY), diffMap.get( Calendar.MINUTE), diffMap.get( Calendar.SECOND), diffMap.get( Calendar.MILLISECOND));
    return result;
}

private static int computeDist( Calendar cAfter, Calendar cBefore, int field) {
    cBefore.setLenient( true);
    System.out.print( "D " + new Date( cBefore.getTimeInMillis()) + " --- " + new Date( cAfter.getTimeInMillis()) + ": ");
    int count = 0;
    if ( cAfter.getTimeInMillis() > cBefore.getTimeInMillis()) {
        int fVal = cBefore.get( field);
        while ( cAfter.getTimeInMillis() >= cBefore.getTimeInMillis()) {
            count++;
            fVal = cBefore.get( field);
            cBefore.set( field, fVal + 1);
            System.out.print( count + "/"  + ( fVal + 1) + ": " + new Date( cBefore.getTimeInMillis()) + " ] ");
        }
        int result = count - 1;
        cBefore.set( field, fVal);
        System.out.println( "" + result + " at: " + field + " cb = " + new Date( cBefore.getTimeInMillis()));
        return result;
    }
    return 0;
}
person Ralf H    schedule 19.12.2014

Это еще один образец. Что в основном работает для пользовательского шаблона.

   public static LinkedHashMap<String, Object> checkDateDiff(DateTimeFormatter dtfObj, String startDate, String endDate)
   {
          Map<String, Object> dateDiffMap = new HashMap<String, Object>();
          DateTime start = DateTime.parse(startDate,dtfObj);
          DateTime end = DateTime.parse(endDate,dtfObj);
          Interval interval = new Interval(start, end);
          Period period = interval.toPeriod();

          dateDiffMap.put("ISO-8601_PERIOD_FORMAT", period);
          dateDiffMap.put("YEAR", period.getYears());
          dateDiffMap.put("MONTH", period.getMonths());
          dateDiffMap.put("WEEK", period.getWeeks());
          dateDiffMap.put("DAY", period.getWeeks());             
          dateDiffMap.put("HOUR", period.getHours());
          dateDiffMap.put("MINUTE", period.getMinutes());
          dateDiffMap.put("SECOND", period.getSeconds());

          return dateDiffMap;        
   }
person The N..    schedule 29.01.2015
comment
Спасибо за попытку внести свой вклад в StackOverflow. Предлагаю вам добавить обсуждение или пояснение. StackOverflow предназначен не только для библиотеки сниппетов. Итак, вы должны объяснить (а) как работает ваш код и (б) как он увеличивает ценность по сравнению со многими другими ответами, уже опубликованными на этот вопрос. Кроме того, этот код не является полным, с такими переменными, как dtfObj, которые не имеют объявления или назначения. Наконец, в качестве отступления, я предлагаю этот совет: вы можете использовать более общий Map интерфейс слева от вашей первой строки, а не LinkedHashMap. Это одно из преимуществ полиморфизма. - person Basil Bourque; 29.01.2015
comment
@BasilBourque: Привет, я внес ожидаемые изменения и обязательно попытаюсь добавить больше для объяснения. - person The N..; 12.02.2015

В java есть простой способ сделать это

// создаем служебный метод

public long getDaysBetweenDates(Date d1, Date d2){
return TimeUnit.MILLISECONDS.toDays(d1.getTime() - d2.getTime());
}

Этот метод вернет количество дней между двумя датами. Либо вы можете использовать формат даты java по умолчанию, либо можете легко преобразовать дату из любого формата.

person Vishal Kumar    schedule 27.10.2015
comment
Это предполагает постоянное количество миллисекунд в день. Это не всегда правда. - person pr1001; 29.10.2015

Еще одна чистая вариация Java:

public boolean isWithin30Days(Calendar queryCalendar) {

    // 1. Take the date you are checking, and roll it back N days
    Calendar queryCalMinus30Days = Calendar.getInstance();
    queryCalMinus30Days.setTime(queryCalendar.getTime());
    queryCalMinus30Days.add(Calendar.DATE, -30); // subtract 30 days from the calendar

    // 2. Get respective milliseconds for the two Calendars: now & queryCal minus N days 
    long nowL = Calendar.getInstance().getTimeInMillis();
    long queryCalMinus30DaysL = queryCalMinus30Days.getTimeInMillis();

    // 3. if nowL is still less than the queryCalMinus30DaysL, it means queryCalendar is more than 30 days into future
    boolean isWithin30Days = nowL >= queryCalMinus30DaysL;

    return isWithin30Days;
}

спасибо стартовому коду здесь: https://stackoverflow.com/a/30207726/2162226

person Gene Bo    schedule 05.01.2017

Если у вас есть даты d1 и d2, лучшим решением, вероятно, будет следующее:

int days1 = d1.getTime()/(60*60*24*1000);//find the number of days since the epoch.
int days2 = d2.getTime()/(60*60*24*1000);

тогда просто скажи

days2-days1

или что-то еще

person codersarepeople    schedule 16.08.2010
comment
-1 Это неверно, если экземпляры Date не были получены из времени UTC. См. Ответ Джона Скита. - person sleske; 30.08.2010
comment
Это неверно. Внутри экземпляры Date представляют собой тонкую оболочку вокруг long, представляющего POSIX Epoch Time. Это определено только для UTC. Следовательно, значение, возвращаемое dateObject.getTime (), всегда находится в формате UTC. - person scottb; 16.05.2013

person    schedule
comment
-1 Это неверно, если экземпляры Date не были получены из времени UTC. См. Ответ Джона Скита. - person sleske; 30.08.2010
comment
@sleske ты не прав. Он уже потерял информацию о часовом поясе, используя Date, поэтому это сравнение - лучшее, что может быть достигнуто с учетом обстоятельств. - person Bozho; 30.08.2010
comment
Ладно, думаю, мы оба правы. Верно, что это зависит от того, откуда берется экземпляр Date. Тем не менее, это настолько распространенная ошибка, что о ней стоит упомянуть. - person sleske; 30.08.2010
comment
Когда я использую ваше решение, оно говорит: Несоответствие типов: невозможно преобразовать long в int. Думаю, тебе тоже стоит добавить кастинг, или мне что-то не хватает? - person Ad Infinitum; 04.10.2017