In Joda-Time, set DateTime to start of month
Solution 1
Midnight at the start of the first day of the current month is given by:
// first midnight in this month
DateMidnight first = new DateMidnight().withDayOfMonth(1);
// last midnight in this month
DateMidnight last = first.plusMonths(1).minusDays(1);
If starting from a java.util.Date, a different DateMidnight constructor is used:
// first midnight in java.util.Date's month
DateMidnight first = new DateMidnight( date ).withDayOfMonth(1);
Joda Time java doc - https://www.joda.org/joda-time/apidocs/overview-summary.html
Solution 2
An alternative way (without taking DateMidnight into account) to get the first day of the month would be to use:
DateTime firstDayOfMonth = new DateTime().dayOfMonth().withMinimumValue();
Solution 3
First Moment Of The Day
The answer by ngeek is correct, but fails to put the time to the first moment of the day. To adjust the time, append a call to 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 );
When run in Seattle US…
startOfThisMonth: 2013-11-01T00:00:00.000-07:00
startofNextMonth: 2013-12-01T00:00:00.000-08:00
Note the difference in those two lines of console output: -7 vs -8 because of Daylight Saving Time.
Generally one should always specify the time zone rather than rely on default. Omitted here for simplicity. One should add a line like this, and pass the time zone object to the constructors used in example above.
// 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.time
The above is correct but outdated. The Joda-Time library is now supplanted by the java.time framework built into Java 8 and later.
The LocalDate
represents a date-only value without time-of-day and without time zone. A time zone is crucial in determine a date. For any given moment the date varies by zone around the globe.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( zoneId );
Use one of the TemporalAdjusters
to get first of month.
LocalDate firstOfMonth = today.with( TemporalAdjusters.firstDayOfMonth() );
The LocalDate
can generate a ZonedDateTime
that represents the first moment of the day.
ZonedDateTime firstMomentOfCurrentMonth = firstOfMonth.atStartOfDay( zoneId );
Solution 4
Oh, I did not see that this was about jodatime. Anyway:
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());
}
Or using 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);
}
Solution 5
DateMidnight
is now deprecated. Instead you can do:
LocalDate firstOfMonth = new LocalDate(date).withDayOfMonth(1);
LocalDate lastOfMonth = firstOfMonth.plusMonths(1).minusDays(1);
If you know the time zone use new LocalDate(date, timeZone)
instead for greater accuracy.
You can also do .dayOfMonth().withMinimumValue()
instead of .withDayOfMonth(1)
EDIT:
This will give you 12/1/YYYY 00:00
and 12/31/YYYY 00:00
. If you rather the last of the month be actually the first of the next month (because you are doing a between clause), then remove the minusDays(1)
from the lastOfMonth calculation
Comments
-
Maxim Veksler almost 4 years
My API allows library client to pass Date:
method(java.util.Date date)
Working with Joda-Time, from this date I would like to extract the month and iterate over all days this month contains.
Now, the passed date is usually new Date() - meaning current instant. My problem actually is setting the new DateMidnight(jdkDate) instance to be at the start of the month.
Could someone please demonstrates this use case with Joda-Time?
-
Maxim Veksler over 14 yearsThanks for the java basic api note. I've learned from this as well.
-
Maxim Veksler over 14 yearsbtw, on that "last" why not: DateMidnight last = first.plusMonths(1).minusDays(1); Same thing,just cleaner.
-
Basil Bourque over 10 yearsThis answer was correct, but is now outmoded. Not every day in every time zone has a midnight. Joda-Time 2 added a method
withTimeAtStartOfDay
to be used in place of the "midnight" features. -
JustinKSU over 9 yearsAlthough the date would be the first of the month, the time would still be in the middle of the day. Adding .withTimeAtStartOfDay() to the end would resolve this.
-
JustinKSU over 9 yearsDateMidnight is now deprecated. From JavaDoc: "The time of midnight does not exist in some time zones where the daylight saving time forward shift skips the midnight hour. Use LocalDate to represent a date without a time zone. Or use DateTime to represent a full date and time, perhaps using DateTime.withTimeAtStartOfDay() to get an instant at the start of a day."
-
JustinKSU over 9 years@Xylian I guess it depends on the interpretation of the question. For the any day, it will give you midnight on the first of the month and midnight of the last day of the month. If you want midnight of the first day of the next month, just remove the ".minusDays(1) from the second. If you still think my answer is incorrect, please elaborate, because my unit tests say it works.
-
JPhi Denis over 6 yearsyou can also add .dayOfMonth().withMaximumValue().hourOfDay().withMaximumValue() and can add the same with minutes of Hours... to be more precise
-
yash over 5 years
DateMidnight
is deprecated.