2016-01-13 2 views
1

мне нужно, чтобы получить разницу в месяцах между двумя датами, я использую Joda время, проблема заключается в следующем:Joda Время - разница в месяцах между двумя датами

DateTime date1 = new DateTime().withDate(2015, 2, 1); 
DateTime date2 = new DateTime().withDate(2015, 1, 1); 
Months m = Months.monthsBetween(date1, date2); 
int monthDif = m.getMonths();//this return 0 

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

+1

Несмотря на то, что вышеупомянутый вопрос касается нескольких дней, он очень похож на ваш вопрос, и решение одно и то же, вызовите 'DateTime # toLocalDate()' для передачи 'LocalDate' в' Months # monthsBetween', вместо 'DateTime '. – Tom

+1

Почему вы используете 'новое Datetime(). WithDate()' в первую очередь? Он создает экземпляр DateTime текущего момента и затем меняет его (оставляя поля времени как есть). Если вы хотите создать только новую конкретную дату без времени, просто используйте [LocalDate] (http://www.joda.org/joda-time/apidocs/org/joda/time/LocalDate.html), а затем «Months.monthsBetween» (date1, date2) 'будет работать нормально. – djxak

ответ

5

изменяющемся первую дату в 2015-02-02, Joda правильно возвращает 1 месяц:

DateTime date1 = new DateTime().withDate(2015, 2, 2); 
DateTime date2 = new DateTime().withDate(2015, 1, 1); 

System.out.println(Months.monthsBetween(date2, date1).getMonths()); 
// Returns 1. 

Так что моя догадка, что, потому что вы не обеспечивают временная часть, Джода не может быть точным точно о , который указывает время 2015-01-01date2 относится к. Возможно, вы также упомянули 23:59:59, и в этом случае полный месяц еще не прошел бы, технически.

Если вы предоставите нулевой временную часть в явном виде, он работает, как вы первоначально ожидался:

DateTime date1 = new DateTime().withDate(2015, 2, 1).withTime(0, 0, 0, 0); 
DateTime date2 = new DateTime().withDate(2015, 1, 1).withTime(0, 0, 0, 0); 

System.out.println(Months.monthsBetween(date2, date1).getMonths()); 
// Returns 1. 

Поэтому я рекомендую указать 00:00:00 временную часть в каждой дате явно.

+1

только деталь, DateTime имеет методTimeAtStartOfDay() – TheJudge

-1

Способ, которым это рассчитывается, зависит от бизнес-логики, которая должна использоваться. Каждый месяц меняется по длине. Один из вариантов заключается в том, чтобы в функции monthsBetween() получить начало месяца как для date1, так и для date2 и сравнить это.

Что-то вроде:

DateTime firstOfMonthDate1 = new DateTime(date1.getYear(), date1.getMonthOfYear(), 1, 0, 0); 
DateTime firstOfMonthDate2 = new DateTime(date2.getYear(), date2.getMonthOfYear(), 1, 0, 0); 
Months m = Months.monthsBetween(firstOfMonthDate1, firstOfMonthDate2) 
5

В то время как другие ответы верны, они по-прежнему маскируют реальную проблему.

возвращает 0, потому что нет месяца в середине двух дат

Нет. Она возвращает 0, потому что время часть DateTime объекта. Вы создаете два значения DateTime, заполненных текущим моментом времени (с часами, минутами, секундами и миллисекундами), а затем изменяете только дату. Нет причин для этого, если вы хотите сравнить только две даты. вместо этого используйте LocalDate.

LocalDate date1 = new LocalDate(2015, 2, 1); 
LocalDate date2 = new LocalDate(2015, 1, 1); 
Months m = Months.monthsBetween(date1, date2); 
int monthDif = Math.abs(m.getMonths());//this return 1 

необходимо также обратить внимание на тот факт, что, несмотря на то, что Months документы не говоря уже об этом, Month может содержать отрицательное значение, если первая дата после второго дня. Поэтому нам нужно использовать Math.abs, чтобы действительно подсчитать количество месяцев между двумя датами.

docs говорит:

Создает Месяцы, представляющее число полных месяцев между двумя указанными частичным DateTimes.

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

+1

Да, моя вина. Он фактически возвращает '-1', потому что' date1' после 'date2'. Документы 'Months.monthsBetween' никогда не говорят, что * период в месяцах * может быть отрицательным. :) Но это также верно для вопроса и принятого ответа и ничего не меняет. Я редактирую свой ответ, чтобы использовать 'Math.abs'. – djxak

+0

Я думаю, было бы лучше объяснить OP (в ответе), почему он возвращает -1 с текущим кодом и вместо этого использует 'Months.monthsBetween (date2, date1);'. Это как вызов 'X.compareTo (Y)' vs 'Y.compareTo (X)', результат также будет инвертирован: D. – Tom

Смежные вопросы