В Joda-Time установите DateTime на начало месяца

Мой API позволяет клиенту библиотеки передавать дату:

method(java.util.Date date)

Работая с Joda-Time, с этой даты я хотел бы извлечь месяц и перебрать все дней в этом месяце содержится.

Теперь переданная дата обычно является новой датой(), что означает текущий момент. На самом деле моя проблема заключается в установке нового экземпляра DateMidnight(jdkDate) в начало месяца.

Может ли кто-нибудь продемонстрировать этот вариант использования с Joda-Time?


person Maxim Veksler    schedule 14.02.2010    source источник
comment
В заголовке вопроса должно быть упомянуто Joda Time.   -  person Lachlan Roche    schedule 14.02.2010
comment
Может кто-нибудь продемонстрировать этот вариант использования с joda-time. Я добавил еще одно примечание, чтобы было более понятно, что это вопрос времени Джоды.   -  person Maxim Veksler    schedule 14.02.2010
comment
@MaximVeksler Лахлан Роше сказал, что title должен упоминать Joda-Time. Я сделал правку.   -  person Basil Bourque    schedule 26.11.2013


Ответы (6)


Полночь в начале первого дня текущего месяца определяется как:

// first midnight in this month
DateMidnight first = new DateMidnight().withDayOfMonth(1);

// last midnight in this month
DateMidnight last = first.plusMonths(1).minusDays(1);

Если вы начинаете с java.util.Date, используется другой конструктор DateMidnight:

// first midnight in java.util.Date's month
DateMidnight first = new DateMidnight( date ).withDayOfMonth(1);

Java-документ Joda Time — https://www.joda.org/joda-time/apidocs/overview-summary.html

person Lachlan Roche    schedule 14.02.2010

Альтернативным способом (без учета DateMidnight) получения первого дня месяца было бы использование:

  DateTime firstDayOfMonth = new DateTime().dayOfMonth().withMinimumValue();
person ngeek    schedule 27.04.2011
comment
Хотя дата будет первой в месяце, время все равно будет в середине дня. Добавление .withTimeAtStartOfDay() в конец решит эту проблему. - person JustinKSU; 10.10.2014
comment
вы также можете добавить .dayOfMonth().withMaximumValue().hourOfDay().withMaximumValue() и можете добавить то же самое с минутами часов... чтобы быть более точным - person JPhi Denis; 18.10.2017

первый момент дня

ответ ngeek верен, но не может указать время в первый момент дня. Чтобы настроить время, добавьте вызов withTimeAtStartOfDay.

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.

org.joda.time.DateTime startOfThisMonth = new org.joda.time.DateTime().dayOfMonth().withMinimumValue().withTimeAtStartOfDay();
org.joda.time.DateTime startofNextMonth = startOfThisMonth.plusMonths( 1 ).dayOfMonth().withMinimumValue().withTimeAtStartOfDay();

System.out.println( "startOfThisMonth: " + startOfThisMonth );
System.out.println( "startofNextMonth: " + startofNextMonth );

Когда бежишь в Сиэтле, США…

startOfThisMonth: 2013-11-01T00:00:00.000-07:00
startofNextMonth: 2013-12-01T00:00:00.000-08:00

Обратите внимание на разницу в этих двух строках вывода консоли: -7 против -8 из-за летнего времени.


Как правило, всегда следует указывать часовой пояс, а не полагаться на значение по умолчанию. Здесь опущено для простоты. Нужно добавить строку, подобную этой, и передать объект часового пояса конструкторам, используемым в примере выше.

// Time Zone list: http://joda-time.sourceforge.net/timezones.html  (Possibly out-dated, read note on that page)
// UTC time zone (no offset) has a constant, so no need to construct: org.joda.time.DateTimeZone.UTC
org.joda.time.DateTimeZone kolkataTimeZone = org.joda.time.DateTimeZone.forID( "Asia/Kolkata" );

Java.время

Вышеупомянутое верно, но устарело. Библиотека Joda-Time теперь заменена фреймворком java.time, встроенным в Java 8 и более поздние версии.

LocalDate представляет значение только для даты без времени суток и без часового пояса. Часовой пояс имеет решающее значение для определения даты. В любой данный момент дата варьируется в зависимости от зоны по всему миру.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( zoneId );

Используйте один из TemporalAdjusters для получить первое число месяца.

LocalDate firstOfMonth = today.with( TemporalAdjusters.firstDayOfMonth() );

LocalDate может генерировать ZonedDateTime, представляющий первый момент дня.

ZonedDateTime firstMomentOfCurrentMonth = firstOfMonth.atStartOfDay( zoneId );
person Basil Bourque    schedule 25.11.2013

О, я не видел, чтобы речь шла о джодатиме. Так или иначе:

Calendar c = Calendar.getInstance();
c.setTime(date);
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);

int min = c.getActualMinimum(Calendar.DAY_OF_MONTH);
int max = c.getActualMaximum(Calendar.DAY_OF_MONTH);
for (int i = min; i <= max; i++) {
    c.set(Calendar.DAY_OF_MONTH, i);
    System.out.println(c.getTime());
}

Или используя commons-lang:

Date min = DateUtils.truncate(date, Calendar.MONTH);
Date max = DateUtils.addMonths(min, 1);
for (Date cur = min; cur.before(max); cur = DateUtils.addDays(cur, 1)) {
    System.out.println(cur);
}

person andi5    schedule 14.02.2010
comment
Спасибо за примечание к базовому API Java. Я тоже извлек из этого урок. - person Maxim Veksler; 14.02.2010

DateMidnight больше не рекомендуется. Вместо этого вы можете сделать:

LocalDate firstOfMonth = new LocalDate(date).withDayOfMonth(1);
LocalDate lastOfMonth = firstOfMonth.plusMonths(1).minusDays(1);

Если вы знаете часовой пояс, используйте new LocalDate(date, timeZone) для большей точности.

Вы также можете сделать .dayOfMonth().withMinimumValue() вместо .withDayOfMonth(1)

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

Это даст вам 12/1/YYYY 00:00 и 12/31/YYYY 00:00. Если вы предпочитаете, чтобы последний месяц был на самом деле первым в следующем месяце (потому что вы делаете предложение between), то удалите minusDays(1) из расчета lastOfMonth

person JustinKSU    schedule 09.10.2014
comment
@Xylian Думаю, это зависит от интерпретации вопроса. Для любого дня это даст вам полночь первого числа месяца и полночь последнего дня месяца. Если вам нужна полночь первого дня следующего месяца, просто удалите .minusDays(1) из второго. Если вы все еще считаете, что мой ответ неверен, пожалуйста, уточните, потому что мои модульные тесты говорят, что это работает. - person JustinKSU; 19.01.2015

Вы можете получить дату начала и дату окончания месяца, используя это:

DateTime monthStartDate = new DateTime().dayOfMonth().withMinimumValue();
DateTime monthEndDate = new DateTime().dayOfMonth().withMaximumValue();
                        
person Vikram Singh    schedule 20.08.2020