Разница в днях между двумя датами в Java? - PullRequest
80 голосов
/ 21 июля 2010

Мне нужно найти количество дней между двумя датами : одно из отчета, а другое текущая дата. Мой фрагмент:

  int age=calculateDifference(agingDate, today);

Здесь calculateDifference - это закрытый метод, agingDate и today - это Date объекты, просто для вашего пояснения. Я следил за двумя статьями на форуме Java: Тема 1 / Тема 2 .

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

Почему это происходит и как я могу это исправить?

РЕДАКТИРОВАТЬ:

Я получаю большее количество дней по сравнению с фактическим количеством дней.

public static int calculateDifference(Date a, Date b)
{
    int tempDifference = 0;
    int difference = 0;
    Calendar earlier = Calendar.getInstance();
    Calendar later = Calendar.getInstance();

    if (a.compareTo(b) < 0)
    {
        earlier.setTime(a);
        later.setTime(b);
    }
    else
    {
        earlier.setTime(b);
        later.setTime(a);
    }

    while (earlier.get(Calendar.YEAR) != later.get(Calendar.YEAR))
    {
        tempDifference = 365 * (later.get(Calendar.YEAR) - earlier.get(Calendar.YEAR));
        difference += tempDifference;

        earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
    }

    if (earlier.get(Calendar.DAY_OF_YEAR) != later.get(Calendar.DAY_OF_YEAR))
    {
        tempDifference = later.get(Calendar.DAY_OF_YEAR) - earlier.get(Calendar.DAY_OF_YEAR);
        difference += tempDifference;

        earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
    }

    return difference;
}

Примечание:

К сожалению, ни один из ответов не помог мне решить проблему. Я выполнил эту проблему с помощью библиотеки Joda-time .

Ответы [ 20 ]

2 голосов
/ 18 августа 2011

Посмотрите на getFragmentInDays методов в этом классе apache commons-lang DateUtils.

1 голос
/ 14 июня 2016

ThreeTen-Extra

Ответ Виталия Федоренко правильный, описывающий, как выполнить этот расчет современным способом с java.time классами (Duration & ChronoUnit) встроен в Java 8 и более поздние версии (и перенесен на Java 6 & 7 и на Android ).

Days

Если вы регулярно используете количество дней в своем коде, вы можете заменить простые целые числа использованием класса. Класс Days можно найти в проекте ThreeTen-Extra , расширении java.time и полигоне для возможных будущих дополнений к java.time. Класс Days обеспечивает безопасный тип представления количества дней в вашем приложении. Класс включает в себя удобные константы для ZERO и ONE.

Учитывая старые устаревшие java.util.Date объекты в Вопросе, сначала преобразуйте их в современные java.time.Instant объекты. Старые классы даты и времени имеют недавно добавленные методы для облегчения преобразования в java.time, такие как java.util.Date::toInstant.

Instant start = utilDateStart.toInstant(); // Inclusive.
Instant stop = utilDateStop.toInstant();  // Exclusive.

Передайте оба объекта Instant заводскому методу для org.threeten.extra.Days.

В текущей реализации (2016-06) это оболочка, вызывающая java.time.temporal.ChronoUnit.DAYS.between, для подробностей прочтите документ ChronoUnit class. Для ясности: все заглавные буквы DAYS находятся в перечислении ChronoUnit, в то время как initial-cap Days является классом от ThreeTen-Extra.

Days days = Days.between( start , stop );

Вы можете передавать эти Days объекты вокруг вашего собственного кода. Вы можете сериализовать строку в стандартный формат ISO 8601 , вызвав toString. Этот формат PnD использует P для обозначения начала, а D означает «дни» с количеством дней между ними. Классы java.time и ThreeTen-Extra по умолчанию используют эти стандартные форматы при генерации и разборе строк, представляющих значения даты и времени.

String output = days.toString();

P3D

Days days = Days.parse( "P3D" );  
1 голос
/ 12 августа 2014

Сто строк кода для этой базовой функции ???

Просто простой метод:

protected static int calculateDayDifference(Date dateAfter, Date dateBefore){
    return (int)(dateAfter.getTime()-dateBefore.getTime())/(1000 * 60 * 60 * 24); 
    // MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
}
1 голос
/ 21 июля 2010

Вы говорите, что это "отлично работает в автономной программе", но вы получаете "необычные значения разности", когда вы "включаете это в мою логику для чтения из отчета". Это говорит о том, что в вашем отчете есть некоторые значения, для которых он работает некорректно, а в вашей отдельной программе эти значения отсутствуют. Вместо отдельной программы я предлагаю тестовый пример. Напишите тестовый пример так же, как автономную программу, подклассы класса JCnit TestCase. Теперь вы можете запустить очень конкретный пример, зная, какое значение вы ожидаете (и не указывайте его сегодня для значения теста, потому что сегодня меняется со временем). Если вы введете значения, которые вы использовали в автономной программе, ваши тесты, вероятно, пройдут. Это здорово - вы хотите, чтобы эти дела продолжали работать. Теперь добавьте значение из вашего отчета, которое не работает правильно. Ваш новый тест, вероятно, не удастся. Выясните, почему он не работает, исправьте его и доберитесь до зеленого (все тесты пройдены). Запустите ваш отчет. Посмотри, что еще сломано; написать тест; сделать это. Довольно скоро вы обнаружите, что ваш отчет работает.

1 голос
/ 24 декабря 2014
public static int getDifferenceIndays(long timestamp1, long timestamp2) {
    final int SECONDS = 60;
    final int MINUTES = 60;
    final int HOURS = 24;
    final int MILLIES = 1000;
    long temp;
    if (timestamp1 < timestamp2) {
        temp = timestamp1;
        timestamp1 = timestamp2;
        timestamp2 = temp;
    }
    Calendar startDate = Calendar.getInstance(TimeZone.getDefault());
    Calendar endDate = Calendar.getInstance(TimeZone.getDefault());
    endDate.setTimeInMillis(timestamp1);
    startDate.setTimeInMillis(timestamp2);
    if ((timestamp1 - timestamp2) < 1 * HOURS * MINUTES * SECONDS * MILLIES) {
        int day1 = endDate.get(Calendar.DAY_OF_MONTH);
        int day2 = startDate.get(Calendar.DAY_OF_MONTH);
        if (day1 == day2) {
            return 0;
        } else {
            return 1;
        }
    }
    int diffDays = 0;
    startDate.add(Calendar.DAY_OF_MONTH, diffDays);
    while (startDate.before(endDate)) {
        startDate.add(Calendar.DAY_OF_MONTH, 1);
        diffDays++;
    }
    return diffDays;
}
0 голосов
/ 14 июня 2016

Я уже писал об этом. Это репост из Расчет разницы между двумя экземплярами даты Java .

public int getDiffernceInDays(long timeAfter, long timeBefore) {
    Calendar calendarAfter = Calendar.getInstance();
    calendarAfter.setTime(new Date(timeAfter));

    Calendar calendarNewAfter = Calendar.getInstance();
    calendarNewAfter.set(calendarAfter.get(Calendar.YEAR), calendarAfter.get(Calendar.MONTH), calendarAfter.get(Calendar.DAY_OF_MONTH));

    Calendar calendarBefore = Calendar.getInstance();
    calendarBefore.setTime(new Date(timeBefore));

    Calendar calendarNewBefore = Calendar.getInstance();
    calendarNewBefore.set(calendarBefore.get(Calendar.YEAR), calendarBefore.get(Calendar.MONTH), calendarBefore.get(Calendar.DAY_OF_MONTH));

    return (int) ((calendarNewAfter.getTime().getTime() - calendarNewBefore.getTime().getTime()) / (24 * 60 * 60 * 1000));
}
0 голосов
/ 03 декабря 2014

Если вы ищете решение, которое возвращает правильное число или дни между, например, 11/30/2014 23:59 и 12/01/2014 00:01, вот решение с использованием Joda Time.

private int getDayDifference(long past, long current) {
    DateTime currentDate = new DateTime(current);
    DateTime pastDate = new DateTime(past);
    return currentDate.getDayOfYear() - pastDate.getDayOfYear();
} 

Эта реализация вернет 1 в виде разницы в днях.Большинство решений, опубликованных здесь, рассчитывают разницу в миллисекундах между двумя датами.Это означает, что 0 будет возвращено, потому что разница между этими двумя датами составляет всего 2 минуты.

0 голосов
/ 16 августа 2014

Этот код вычисляет дни между двумя строками даты:

    static final long MILLI_SECONDS_IN_A_DAY = 1000 * 60 * 60 * 24;
    static final String DATE_FORMAT = "dd-MM-yyyy";
    public long daysBetween(String fromDateStr, String toDateStr) throws ParseException {
    SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
    Date fromDate;
    Date toDate;
    fromDate = format.parse(fromDateStr);
    toDate = format.parse(toDateStr);
    return (toDate.getTime() - fromDate.getTime()) / MILLI_SECONDS_IN_A_DAY;
}
0 голосов
/ 13 июля 2016

Вы должны использовать библиотеку Joda Time, потому что Java Util Date иногда возвращает неправильные значения.

Joda vs Java Util Date

Например, дни между вчерашним днем ​​(дд-мм-гггг, 12-07-2016) и первым днем ​​года в 1957 году (дд-мм-гггг, 01-01-1957):

public class Main {

public static void main(String[] args) {
    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

    Date date = null;
    try {
        date = format.parse("12-07-2016");
    } catch (ParseException e) {
        e.printStackTrace();
    }

    //Try with Joda - prints 21742
    System.out.println("This is correct: " + getDaysBetweenDatesWithJodaFromYear1957(date));
    //Try with Java util - prints 21741
    System.out.println("This is not correct: " + getDaysBetweenDatesWithJavaUtilFromYear1957(date));    
}


private static int getDaysBetweenDatesWithJodaFromYear1957(Date date) {
    DateTime jodaDateTime = new DateTime(date);
    DateTimeFormatter formatter = DateTimeFormat.forPattern("dd-MM-yyyy");
    DateTime y1957 = formatter.parseDateTime("01-01-1957");

    return Days.daysBetween(y1957 , jodaDateTime).getDays();
}

private static long getDaysBetweenDatesWithJavaUtilFromYear1957(Date date) {
    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

    Date y1957 = null;
    try {
        y1957 = format.parse("01-01-1957");
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return TimeUnit.DAYS.convert(date.getTime() - y1957.getTime(), TimeUnit.MILLISECONDS);
}

Поэтому я действительно советую вам использовать библиотеку Joda Time.

0 голосов
/ 08 октября 2013

Я так и сделал.это просто :) 1001

Date d1 = jDateChooserFrom.getDate();
Date d2 = jDateChooserTo.getDate();

Calendar day1 = Calendar.getInstance();
day1.setTime(d1);

Calendar day2 = Calendar.getInstance();
day2.setTime(d2);

int from = day1.get(Calendar.DAY_OF_YEAR);
int to = day2.get(Calendar.DAY_OF_YEAR);

int difference = to-from;
...