Найдите дату окончания следующего квартала по дате окончания предыдущего квартала, используя Java - PullRequest
6 голосов
/ 28 января 2020

У меня есть дата окончания квартала последнего квартала, пусть она будет 30-09-20, требуется найти дату окончания следующего квартала, т.е. 31-12-20. Я использую код ниже, чтобы сделать то же самое, но дает ли он неправильный вывод в некоторых сценариях ios. Это решение должно быть правильным для всех сторон.

String str = "30-09-20";
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yy");
Date date = format.parse(str);
Date newDate = DateUtils.addMonths(date, 3);
System.out.println(newDate);//Dec 30 - It should be 31 Dec

Ответы [ 5 ]

9 голосов
/ 28 января 2020

Чтобы ответить на ваш вопрос, я думаю, что вы ищете это:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yy");
LocalDate end = LocalDate.parse("30-09-20", formatter)
    .plusMonths(3)                             // add three months to your date
    .with(TemporalAdjusters.lastDayOfMonth()); // with the last day of the month

Примечание: не используйте устаревшую библиотеку Date, вы отметили свой вопрос Java -8, что означает, что вы можете использовать java -time API.


Получить последний день текущего квартала

@ deHaar есть причина, чтобы получить дату окончания текущего квартала я бы предложил использовать:

public LocalDate lastDayFromDateQuarter(String date) {
    final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yy");
    LocalDate ld = LocalDate.parse(date, formatter);
    int quarter = ld.get(IsoFields.QUARTER_OF_YEAR); // Get the Quarter, 1, 2, 3, 4
    // Then create a new date with new quarter * 3 and last day of month
    return ld.withMonth(quarter * 3).with(TemporalAdjusters.lastDayOfMonth());
}

Получить последний день следующего квартала

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

public static LocalDate lastDayFromDateQuarter(String date) {
    final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yy");
    LocalDate ld = LocalDate.parse(date, formatter);
    int quarter = ld.get(IsoFields.QUARTER_OF_YEAR);
    return ld.withMonth(quarter * 3)
            .plusMonths(3)
            .with(TemporalAdjusters.lastDayOfMonth());
}
4 голосов
/ 31 января 2020

tl; др

Использование YearQuarter класс от ThreeTen-Extra .

YearQuarter                                       // A class available in the ThreeTen-Extra library.
.from(                                            // Factory method rather than calling `new`. 
    LocalDate.of( 2020 , Month.SEPTEMBER , 30 )   // Returns a `LocalDate` object, represent a date-only value without a time-of-day and without a time zone.
)                                                 // Returns a `YearQuarter` object.
.plusQuarters( 1 )                                // Perform date-math, resulting in a new `YearQuarter` object (per immutable objects pattern). 
.atEndOfQuarter()                                 // Determine the date of last day of this year-quarter.
.toString()                                       // Generate text in standard ISO 8601 format.

2020-12-31

org.threeten.extra.YearQuarter

Библиотека ThreeTen-Extra предоставляет классы, расширяющие функциональные возможности java .time классы, встроенные в Java 8 и более поздние версии. Один из его классов YearQuarter представляет определенный c квартал в конкретный c год. Кварталы определяются календарным годом: январь-март, апрель-июнь, июль-сентябрь, октябрь-декабрь c.

LocalDate localDate = LocalDate.of( 2020 , Month.SEPTEMBER , 30 ) ;
YearQuarter yearQuarter = YearQuarter.from( localDate ) ;

Перейдите к следующему кварталу, добавив один квартал к нашему текущему кварталу.

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

YearQuarter followingYearQuarter = yearQuarter.plusQuarters( 1 ) ;

Определите последний день этого квартала.

LocalDate lastDateOfFollowingYearQuarter = followingYearQuarter.atEndOfQuarter() ;

О java .time

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

Чтобы узнать больше, см. Учебник Oracle . И поиск переполнения стека для многих примеров и объяснений. Спецификация: JSR 310 .

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

Вы можете обмениваться java .time объектами напрямую с вашей базой данных. Используйте драйвер JDB C , совместимый с JDB C 4.2 или более поздней версией. Нет необходимости в строках, нет необходимости в java.sql.* классах.

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

  • Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11 и более поздних версий - часть стандартного API Java со связанной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большинство функций java .time перенесено на Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии Android связывают реализации классов java .time .
    • Для более ранних Android (<26) <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP проект адаптируется ThreeTen-Backport (упомянуто выше). См. Как использовать ThreeTenABP… .

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

2 голосов
/ 30 января 2020

Вот моя версия (надеюсь, более читабельная) определения последнего дня следующего квартала для любой даты:

public LocalDate lastDayOfNextQuarter(LocalDate date) {
  Month firstMonthOfCurrentQuarter = date.getMonth().firstMonthOfQuarter();
  LocalDate lastMonthOfCurrentQuarter = date.with(firstMonthOfCurrentQuarter.plus(2));
  LocalDate lastMonthOfNextQuarter = lastMonthOfCurrentQuarter.plusMonths(3);
  return lastMonthOfNextQuarter.with(lastDayOfMonth());
}

И соответствующий метод тестирования:

@ParameterizedTest
@CsvSource({"2020-01-01,2020-06-30", "2020-02-01,2020-06-30", "2020-03-01,2020-06-30", "2020-04-10,2020-09-30",
  "2020-05-10,2020-09-30", "2020-06-10,2020-09-30", "2020-07-20,2020-12-31", "2020-08-20,2020-12-31",
  "2020-09-30,2020-12-31", "2020-10-30,2021-03-31", "2020-11-30,2021-03-31", "2020-12-31,2021-03-31"})
public void testLastDayOfNextQuarter(LocalDate input, LocalDate expected) {
  LocalDate result = timeUtils.lastDayOfNextQuarter(input);
  assertEquals(expected, result);
}
0 голосов
/ 28 января 2020

Вы можете легко управлять кварталом с помощью TemporalAdjusters. См. Ниже:

    LocalDate localDate = LocalDate.now();
    LocalDate firstDayOfQuarter = localDate.with(IsoFields.DAY_OF_QUARTER, 1);
    System.out.println(firstDayOfQuarter);

    LocalDate lastDayOfQuarter = firstDayOfQuarter.plusMonths(2).with(TemporalAdjusters.lastDayOfMonth());
    System.out.println(lastDayOfQuarter);

    LocalDate firstDateOfNextQuarter = lastDayOfQuarter.plusDays(1);

    LocalDate lastDayOfNextQuarter = firstDateOfNextQuarter.plusMonths(2).with(TemporalAdjusters.lastDayOfMonth());
    System.out.println(lastDayOfNextQuarter);

Вывод:

2020-01-01
2020-03-31
2020-06-30
0 голосов
/ 28 января 2020

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

String str = "30-12-20";
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yy");
Date date = format.parse(str);
Date newDate = DateUtils.addMonths(date, 3);

Calendar cal = new GregorianCalendar();
cal.setTime(newDate);

System.out.println(cal.getActualMaximum(Calendar.DAY_OF_MONTH));
...