Первый день следующего месяца с Java Joda-Time - PullRequest
40 голосов
/ 24 января 2011

Как бы вы переписали описанный ниже метод, который возвращает первый день следующего месяца, с пакетом org.joda.time в Joda-Time ?

public static Date firstDayOfNextMonth() {
    Calendar nowCal = Calendar.getInstance();
    int month = nowCal.get(Calendar.MONTH) + 1;
    int year = nowCal.get(Calendar.YEAR);

    Calendar cal = Calendar.getInstance();
    cal.clear();
    cal.set(Calendar.YEAR, year);
    cal.set(Calendar.MONTH, month);
    cal.set(Calendar.DAY_OF_MONTH, 1);
    Date dueDate = new Date(cal.getTimeInMillis());

    return dueDate;
}

Ответы [ 7 ]

45 голосов
/ 24 января 2011
   LocalDate today = new LocalDate();
   LocalDate d1 = today.plusMonths(1).withDayOfMonth(1);

Немного легче и чище, не так ли? : -)

Обновление: если вы хотите вернуть дату:

return new Date(d1.toDateTimeAtStartOfDay().getMillis());

но я настоятельно советую вам не смешивать чистые типы DATE (то есть день в календаре без информации о времени) с типами DATETIME, особенно с «физическим» типом даты и времени, таким как отвратительный java.util.Date. Это как преобразование целочисленных и плавающих типов в некоторые, вы должны быть осторожны.

21 голосов
/ 24 января 2011

Я предполагаю, что вы хотите вернуть объект Date, поэтому:

public static Date firstDayOfNextMonth() {
    MutableDateTime mdt = new MutableDateTime();
    mdt.addMonths(1);
    mdt.setDayOfMonth(1);
    mdt.setMillisOfDay(0); // if you want to make sure you're at midnight
    return mdt.toDate();
}
15 голосов
/ 21 января 2014

Joda-Time

Вот мой взгляд на эту проблему, используя Joda-Time 2.3.

Неизменный

Как правило, вы должны использовать неизменных версий классов Joda-Time.Почти все методы возвращают новый экземпляр DateTime, а не изменяют существующий экземпляр.Упрощает вещи и обеспечивает автоматическую безопасность потоков.

Начало дня

Используйте более новый метод withTimeAtStartOfDay() вместо установки времени дня на ноль.Из-за летнего времени (DST) и других аномалий в некоторые дни в некоторых часовых поясах нет полуночи или 00:00:00 часов дня.

Преобразование: juDate ↔ DateTime

Чтобы перевести экземпляр Joda-Time DateTime в экземпляр java.util.Date , просто вызовите метод toDate.Нет необходимости в конструкторе для Date.

Если вы используете java.util.Date и хотите использовать Joda-Time DateTime, просто передайте Date конструктору DateTime вместе с желаемым * 1033.*DateTimeZone объект.

Пример кода

DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
// Usually better to specify a time zone rather than rely on default.
DateTime now = new DateTime( timeZone ); // Or, for default time zone: new DateTime()
DateTime monthFromNow = now.plusMonths(1);
DateTime firstOfNextMonth = monthFromNow.dayOfMonth().withMinimumValue();
DateTime firstMomentOfFirstOfNextMonth = firstOfNextMonth.withTimeAtStartOfDay();

Или, если вы маньяк, объедините все это в одну строку кода.

DateTime allInOneLine = new DateTime( DateTimeZone.forID( "Europe/Paris" ) ).plusMonths( 1 ).dayOfMonth().withMinimumValue().withTimeAtStartOfDay();

Перевести на старый java.util.Date для взаимодействия с другими классами / библиотеками.

java.util.Date date = firstMomentOfFirstOfNextMonth.toDate();

Дамп в консоль ...

System.out.println( "now: " + now );
System.out.println( "monthFromNow: " + monthFromNow );
System.out.println( "firstOfNextMonth: " + firstOfNextMonth );
System.out.println( "firstMomentOfFirstOfNextMonth: " + firstMomentOfFirstOfNextMonth );
System.out.println( "allInOneLine: " + allInOneLine );
System.out.println( "date: " + date );

При запуске ...

now: 2014-01-21T02:46:16.834+01:00
monthFromNow: 2014-02-21T02:46:16.834+01:00
firstOfNextMonth: 2014-02-01T02:46:16.834+01:00
firstMomentOfFirstOfNextMonth: 2014-02-01T00:00:00.000+01:00
allInOneLine: 2014-02-01T00:00:00.000+01:00
date: Fri Jan 31 15:00:00 PST 2014

java.time

Платформа java.time , встроенная в Java 8 и более поздние версии, заменяет старые классы java.util.Date/.Calendar.Вдохновленный Joda-Time и призванный стать его преемником.

Эти новые классы включают интерфейс TemporalAdjuster ( Tutorial ) с кучей реализаций в TemporalAdjusters (обратите внимание на множественное число s).Получается только тот регулятор, который нам нужен: firstDayOfNextMonth.

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
LocalDate today = LocalDate.now ( zoneId );
LocalDate firstOfNextMonth = today.with ( TemporalAdjusters.firstDayOfNextMonth () );

Дамп на консоль.

System.out.println ( "today: " + today + "  |  firstOfNextMonth: " + firstOfNextMonth );

сегодня: 2015-12-22 |firstOfNextMonth: 2016-01-01

Если вы хотите использовать дату-время, а не только дату, настройте.

ZonedDateTime zdt = firstOfNextMonth.atStartOfDay( zoneId );

Если вам нужно использовать старый java.util.Дата для работы со старыми классами, которые еще не обновлены до java.time, конвертируйте из Instant, извлеченного из объекта ZonedDateTime.Мгновенное действие - это момент времени на UTC.

java.util.Date date = java.util.Date.from( zdt.toInstant() );

О java.time

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

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

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

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

Где получить классы java.time?

  • Java SE 8 , Java SE 9 , Java SE 10, а позже
    • Встроенный.
    • Часть стандартного Java API с встроенной реализацией.
    • 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 .

6 голосов
/ 07 января 2014

в Joda API есть метод для этого:

Date date = new LocalDate().plusMonths(1).dayOfMonth().withMinimumValue().toDate();

Надеюсь, это поможет!

2 голосов
/ 16 октября 2012

то же самое, что и раньше, но преобразовано также в java.util.Date

Дата firstDayOfNextMonth = (new LocalDate (). PlusMonths (1) .withDayOfMonth (1)). ToDate ();

1 голос
/ 24 января 2011

localDate = new LocalDate (). PlusMonths (1) .withDayOfMonth (1);

0 голосов
/ 18 декабря 2015

Я не уверен, что «я» правильно понял вопрос, но вот моя попытка: D .. вроде просто не добавлять +1 месяц ???

public static Date firstDayOfNextMonth() {
        LocalDateTime now = LocalDateTime.now();
        int year = now.getYear();
        int month = now.getMonthValue();
        int day = now.getDayOfMonth();  

        Calendar cal = Calendar.getInstance();
        cal.clear();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.DAY_OF_MONTH, 1);

        Date dueDate = new Date(cal.getTimeInMillis());

    return dueDate;
}
...