2016-09-04 4 views
1

Я хочу посчитать месяцы между двумя датами и сравнить их с месяцами, игнорируя дни, поэтому 2012-01-31 и 2012-02-01 должны иметь 1 разницу между ними.Получите месяцы между двумя датами, игнорируя дни

Я делаю это с Joda времени:

import org.joda.time.*; 
PeriodType yearMonth = PeriodType.yearMonthDay().withDaysRemoved(); 
LocalDate dt1 = new LocalDate(2012, 1, 31); 
LocalDate dt2 = new LocalDate(2012, 2, 1); 
int months = new Period(dt1, dt2, yearMonth).getMonths(); 
System.out.println(months); 

Но я получил распечатки:

0 

Хотя я использовал .withDaysRemoved(), но это не работает. Я злоупотребляю им?

ответ

0

java.time

Проект Joda время находится в режиме технического обслуживания. Команда советует перейти на классы java.time.

LocalDate

Как и в Joda-время, LocalDate представляет собой дату только значение без времени-дня и без временной зоны.

LocalDate start = LocalDate.of (2012 , Month.JANUARY , 31); 
LocalDate stop = LocalDate.of (2012 , Month.MARCH , 1); 

Укажите место, чтобы наши результаты.

long countMonths = 0; 

YearMonth

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

YearMonth ymStart = YearMonth.from (start); 
YearMonth ymStop = YearMonth.from (stop); 

Этот YearMonth класс имеет методы для сравнения, такие как isAfter, isBefore и equals.

Класс ChronoUnit может рассчитать прошедшие месяцы между двумя объектами Temporal. Класс YearMonth, к счастью, реализует Temporal и работает с ChronoUnit.

if (ymStart.isAfter (ymStop)) { 
    // Handle error condition. Unexpected input values. 
} else if (ymStart.equals (ymStop)) { 
    countMonths = 0; 
} else { // Else different months. 
    countMonths = ChronoUnit.MONTHS.between (ymStart , ymStop); 
} 

Дамп для консоли.

System.out.println ("start: " + start + " | stop: " + stop + " | countMonths: " + countMonths); 

старт: 2012-01-31 | stop: 2012-03-01 | countMonths: 2

Half-Open

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

Так, например, период обеда начинается в первый момент дня полудня и доходит до первого момента 1 вечера, но не включает первый момент.

Другой пример: неделя начнется в понедельник и поднимется до следующего, но не включенного в понедельник. Или в этом случае - пару месяцев с января и до, , но не включая, март; они дают промежуток в 2 месяца.

Я считаю, что использование подхода Half-Open во всем вашем коде приводит к большей ясности и меньшему количеству ошибок. Но если вы или ваши пользователи потребуете иного, добавьте его к результатам выше.

О java.time

java.time каркас встроен в Java 8 и более поздних версий. Эти классы вытесняют неприятные старые классы времени, такие как java.util.Date, .Calendar, & java.text.SimpleDateFormat.

Проект Joda-Time, теперь в maintenance mode, советует перейти на java.time.

Чтобы узнать больше, см. Oracle Tutorial. И поиск Stack Overflow для многих примеров и объяснений.

Большая часть функциональности java.time будет обратно портирован на Java 6 & 7 в ThreeTen-Backport и дополнительно выполнен с возможностью Android в ThreeTenABP (см How to use…).

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

0

Арифметика месяца от LocalDate будет и должна всегда использовать день за месяц для своих расчетов. Тот факт, что вы указали тип периода, чтобы дни не использовались, означает только: Конечный результат не должен показывать никаких дней (но компонент дня LocalDate используется по-прежнему).

Однако, если вы используете другой тип, а именно YearMonth, то этот тип определяет другой месяц арифметику:

LocalDate dt1 = new LocalDate(2012, 1, 31); 
LocalDate dt2 = new LocalDate(2012, 2, 1); 

YearMonth ym1 = new YearMonth(dt1.getYear(), dt1.getMonthOfYear()); 
YearMonth ym2 = new YearMonth(dt2.getYear(), dt2.getMonthOfYear()); 

PeriodType yearMonth = PeriodType.yearMonthDay(); 
System.out.println(new Period(ym1, ym2, yearMonth).getMonths()); // 1 
System.out.println(new Period(ym1, ym2, yearMonth.withDaysRemoved()).getMonths()); // 1 

Здесь вы можете увидеть, что - в контексте YearMonth - подавляя дней PeriodType не Соответствующий.

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