Java Date month difference

2019-01-04 14:20发布

I have start date and end date.

I need the number of months between this two dates in Java.

For example

  • From date: 2009-01-29
  • To date: 2009-02-02

It has one jan date and one Feb date.

It should return 2.

标签: java date
21条回答
来,给爷笑一个
2楼-- · 2019-01-04 14:28

tl;dr

ChronoUnit.MONTHS.between( 
    YearMonth.from( LocalDate.of( 2009 , 1 , 29 ) ) , 
    YearMonth.from( LocalDate.of( 2009 , 2 , 2 ) )
)

Time Zone

The Answer by Roland Tepp is close but ignores the crucial issue of time zone. Determining a month and date requires a time zone, as for any given moment the date varies around the globe by zone.

ZonedDateTime

So his example of converting java.util.Date objects to java.time.Instant objects implicitly uses UTC. Values in either of those classes is always in UTC by definition. So you need to adjust those objects into the desired/intended time zone to be able to extract a meaningful date.

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtStart = myJavaUtilDate1.toInstant().atZone( z );
ZonedDateTime zdtStop = myJavaUtilDate2.toInstant().atZone( z );

YearMonth

Since you want to know how many calendar months were touched by your date range rather than the number of 30-day chunks elapsed, convert to YearMonth objects.

YearMonth start = YearMonth.from( zdtStart );
YearMonth stop = YearMonth.from( zdtStop );

ChronoUnit

Calculate months between by calling on ChronoUnit enum.

long monthsBetween = ChronoUnit.MONTHS.between( start , stop );

1

Half-Open

You desired a result of 2 but we get 1 here. The reason is that in date-time work the best practice is to define spans of time by the Half-Open approach. In Half-Open, the beginning is inclusive while the ending is exclusive. I suggest you stick to this definition throughout your date-time work as doing so ultimately makes sense, eliminates confusing ambiguities, and makes your work easier to parse mentally and less error-prone. But if you insist on your definition, simply add 1 to the result assuming you have positive numbered results (meaning your spans of time go forward in time rather than backward).

LocalDate

The original Question is not clear but may require date-only values rather than date-time values. If so, use the LocalDate class. The LocalDate class represents a date-only value without time-of-day and without time zone.

LocalDate start = LocalDate.of( 2009 , 1 , 29 ) ; 
LocalDate stop = LocalDate.of( 2009 , 2 , 2 ) ;

long monthsBetween = ChronoUnit.MONTHS.between( start ,  stop );

1


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.

查看更多
女痞
3楼-- · 2019-01-04 14:29

it is not the best anwer but you can use unixtimestamp First you find the unixtime's of the dates then eject each other

Finally you should convert the unixtime(sum) to String

查看更多
萌系小妹纸
4楼-- · 2019-01-04 14:30

Joda Time is a pretty cool library for Java Date and Time and can help you achieve what you want using Periods.

查看更多
一纸荒年 Trace。
5楼-- · 2019-01-04 14:30

you can by 30 days or by months :

public static void main(String[] args) throws IOException {

        int n = getNumbertOfMonth(LocalDate.parse("2016-08-31"),LocalDate.parse("2016-11-30"));
        System.out.println("number of month = "+n);

         n = getNumbertOfDays(LocalDate.parse("2016-08-31"),LocalDate.parse("2016-11-30"));
        System.out.println("number of days = "+n);
        System.out.println("number of 30 days = "+n/30);
    }
        static int getNumbertOfMonth(LocalDate dateDebut, LocalDate dateFin) {

        LocalDate start = dateDebut;
        LocalDate end = dateFin;
        int count = 0 ;
        List<String> lTotalDates = new ArrayList<>();
        while (!start.isAfter(end)) {
            count++;
            start =  start.plusMonths(1);
        }
        return count;
    }

    static int getNumbertOfDays(LocalDate dateDebut, LocalDate dateFin) {

        LocalDate start = dateDebut;
        LocalDate end = dateFin;
        int count = 0 ;
        List<String> lTotalDates = new ArrayList<>();
        while (!start.isAfter(end)) {
            count++;
            start =  start.plusDays(1);
        }
        return count;
    }
查看更多
来,给爷笑一个
6楼-- · 2019-01-04 14:31

Now that JSR-310 has been included in the SDK of Java 8 and above, here's a more standard way of getting months difference of two date values:

public static final long getMonthsDifference(Date date1, Date date2) {
    YearMonth m1 = YearMonth.from(date1.toInstant());
    YearMonth m2 = YearMonth.from(date2.toInstant());

    return m1.until(m2, ChronoUnit.MONTHS) + 1;
}

This has a benefit of clearly spelling out the precision of the calculation and it is very easy to understand what is the intent of the calculation.

查看更多
forever°为你锁心
7楼-- · 2019-01-04 14:31

That's because the classes Java Date and Calendar use the Month indices from 0-11

January = 0
December = 1

Is recommended to use Joda Time!

查看更多
登录 后发表回答