问题
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;
}
回答1:
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.
回答2:
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();
}
回答3:
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?
- Java SE 8, Java SE 9, Java SE 10, and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6 and Java SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.time classes.
- For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
回答4:
there is a method for that in Joda API:
Date date = new LocalDate().plusMonths(1).dayOfMonth().withMinimumValue().toDate();
Hope it helps!
回答5:
the same as before but converted also to java.util.Date
Date firstDayOfNextMonth = (new LocalDate().plusMonths(1).withDayOfMonth(1)).toDate();
回答6:
localDate = new LocalDate().plusMonths(1).withDayOfMonth(1);
回答7:
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;
}
来源:https://stackoverflow.com/questions/4786169/first-day-of-next-month-with-java-joda-time