44

How would you rewrite the method below, which returns the first day of next month, with the org.joda.time package in 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;
}
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
MatBanik
  • 26,356
  • 39
  • 116
  • 178

7 Answers7

49
   LocalDate today = new LocalDate();
   LocalDate d1 = today.plusMonths(1).withDayOfMonth(1);

A little easier and cleaner, isn't it? :-)

Update: If you want to return a date:

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

but I strongly advise you to avoid mixing pure DATE types (i.e. a day in the calendar, without time information) with DATETIME types, specially with a "physical" datetime type as is the hideous java.util.Date . It's somewhat like converting from-to integer and floating types, you must be careful.

leonbloy
  • 73,180
  • 20
  • 142
  • 190
  • Yeah, `LocalDate` objects are a slight bit harder to convert back to Java `Date` objects... and since LocalDate represents a whole day in Joda Time, I don't remember what the time component would be on conversion to a Date. – delfuego Jan 24 '11 at 19:46
  • 3
    For those going the `LocalDate` route, it looks like using LocalDate.toDateMidnight().toDate() is the easiest way to convert it to a Java `Date` object with the time set to midnight. – delfuego Jan 24 '11 at 19:53
  • 1
    `toDateMidnight()` is not recommended http://stackoverflow.com/questions/17665921/recommended-use-for-joda-times-datemidnight – leonbloy Oct 22 '14 at 14:25
  • 1
    All the "midnight" related classes and methods in Joda-Time are deprecated and should be avoided. Instead call the various "toDateTime" methods to produce a `DateTime` from a `LocalDate`. For example, [`toDateTimeAtStartOfDay`](http://www.joda.org/joda-time/apidocs/org/joda/time/LocalDate.html#toDateTimeAtStartOfDay-org.joda.time.DateTimeZone-) where you pass the desired time zone. Dates do not always start at the time `00:00:00.0`, so Joda-Time will determine the first moment of the day appropriate for the specified time zone. – Basil Bourque Dec 25 '15 at 04:52
21

I'm assuming you want to return a Date object, so:

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();
}
delfuego
  • 14,085
  • 4
  • 39
  • 39
  • 5
    This code is somewhat outmoded now (2014). (A) The designers of Joda-Time recommend against using the mutable classes. Instead, you can call many of the methods that return a new fresh immutable [`DateTime`](http://www.joda.org/joda-time/apidocs/org/joda/time/DateTime.html) instance. (B) The midnight-related methods are no longer recommended. Instead, call [`withTimeAtStartOfDay`](http://www.joda.org/joda-time/apidocs/org/joda/time/DateTime.html#withTimeAtStartOfDay()) to get first moment of new day. Don't set millis to zero for midnight, as DST may mean there is no such midnight time. – Basil Bourque Jan 21 '14 at 00:57
16

Joda-Time

Here's my take on this problem, using Joda-Time 2.3.

Immutable

Generally you should use the immutable versions of the Joda-Time classes. Nearly all the methods return a new instance of a DateTime rather than modify existing instance. Simplifies things, and makes for automatic thread-safety.

Start-Of-Day

Use the newer method withTimeAtStartOfDay() rather than setting time of day to zero. Because of Daylight Saving Time (DST) and other anomalies, on some days in some time zones, there is no midnight or 00:00:00 time of day.

Convert: j.u.Date ↔ DateTime

To translate a Joda-Time DateTime instance to a java.util.Date instance, simply call toDate method. No need for constructor on Date.

Going the other way, if you hava a java.util.Date and want a Joda-Time DateTime, simply pass the Date to the constructor of DateTime along with the desired DateTimeZone object.

Example Code

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();

Or, if you are a maniac, string that all together in a single line of code.

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

Translate to an old java.util.Date for interaction with other classes/libraries.

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

Dump to console…

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 );

When run…

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

The java.time framework built into Java 8 and later supplants the old java.util.Date/.Calendar classes. Inspired by Joda-Time, and intended to be its successor.

These new classes include the TemporalAdjuster interface (Tutorial) with a bunch of implementations in TemporalAdjusters (notice the plural s). Happens to have just the adjuster we need: firstDayOfNextMonth.

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

Dump to console.

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

today: 2015-12-22 | firstOfNextMonth: 2016-01-01

If you want a date-time rather than date-only, adjust.

ZonedDateTime zdt = firstOfNextMonth.atStartOfDay( zoneId );

If you need to use the old java.util.Date for operating with old classes not yet updated to java.time, convert from an Instant extracted from the ZonedDateTime object. An Instant is a moment on the timeline in UTC.

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

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
6

there is a method for that in Joda API:

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

Hope it helps!

avaz
  • 523
  • 2
  • 8
  • 20
2

the same as before but converted also to java.util.Date

Date firstDayOfNextMonth = (new LocalDate().plusMonths(1).withDayOfMonth(1)).toDate();

simonC
  • 4,101
  • 10
  • 50
  • 78
1

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

Tomasz Krzyżak
  • 1,087
  • 8
  • 10
0

i am not sure if 'I' get the question right, but here's my try :D.. like just don't add the +1 month???

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;
}
BaajiRao
  • 99
  • 1
  • 10