Pergunta

I'm trying to calculate the difference between two days in amount of days. For some reason comparing 01-03-2013 and 01-04-2013 gives the result 30, as does comparing 01-03-2013 and 31-03-2013

Calendar cal = Calendar.getInstance();
cal.clear();

cal.set(2013, Calendar.MARCH, 1);
Date start = cal.getTime();

cal.set(2013, Calendar.APRIL, 1);
Date end = cal.getTime();

long days = TimeUnit.MILLISECONDS.toDays(end.getTime() - start.getTime());
System.out.println("!!! Amount of days : " + String.valueOf(days));

>> 30

cal.set(2013, Calendar.MARCH, 1);
start = cal.getTime();

cal.set(2013, Calendar.MARCH, 31);
end = cal.getTime();

days = TimeUnit.MILLISECONDS.toDays(end.getTime() - start.getTime());
System.out.println("!!! Amount of days : " + String.valueOf(days));

>> 30

Why is this?

Foi útil?

Solução

You will get those results if daylight savings started in your time zone on 31 March.

Between 1 March and 1 April, you have 30 24-hour days and one 23-hour day, because of the start of daylight savings. If you divide the total number of milliseconds by 24 x 60 x 60 x 1000, then you will get 30 plus 23/24. This gets rounded down to 30.

Outras dicas

Time Zone

The correct answer by David Wallace explains that Daylight Saving Time or other anomalies affects the results of your code. Relying on default time zones (or outright ignoring time zones) will get you into this kind of trouble.

Make Span Inclusive-Exclusive

Also, the proper way to define a span of time is to make the beginning inclusive and the ending exclusive. So if you want the month of March, you need to go from first moment of first day to first moment of first day after March (April 1).

For lengthy discussion of this idea, see my other answers such as this one and this one.

Here's a diagram of mine lifted from other answers:

Timeline showing (  loading== start of day 1 ) and ( < start of day 8 )">

Joda-Time

The java.util.Date/Calendar classes bundled with Java are notoriously troublesome. Avoid them. Use either Joda-Time, or in Java 8, the new java.time.* package (inspired by Joda-Time).

The Joda-Time 2.3 library provides classes dedicated to spans of time: Period, Duration, and Interval. That library also has some handy static utility methods, such as Days.daysBetween.

Joda-Time's DateTime objects do know their own time zone, unlike java.util.Date/Calendar which seem to have a time zone but do not.

// Specify a timezone rather than rely on default.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );

DateTime marchFirst = new DateTime( 2013, DateTimeConstants.MARCH, 1, 0, 0, 0, timeZone );
DateTime aprilFirst = new DateTime( 2013, DateTimeConstants.APRIL, 1, 0, 0, 0, timeZone );

int days = Days.daysBetween( marchFirst, aprilFirst).getDays();

Dump to console…

System.out.println( "marchFirst: " + marchFirst );
System.out.println( "aprilFirst: " + aprilFirst ); // Note the change in time zone offset in the output.
System.out.println( "days: " + days );

When run, notice:

  • The correct answer: 31
  • The difference in time zone offset because of Daylight Saving Time in France.
marchFirst: 2013-03-01T00:00:00.000+01:00
aprilFirst: 2013-04-01T00:00:00.000+02:00
days: 31

When I run this version of your code here in United States west coast time zone:

java.util.Calendar cal = java.util.Calendar.getInstance();
cal.clear();

cal.set( 2013, java.util.Calendar.MARCH, 1 );
java.util.Date start = cal.getTime();

cal.set( 2013, java.util.Calendar.APRIL, 1 );
java.util.Date end = cal.getTime();

long days = java.util.concurrent.TimeUnit.MILLISECONDS.toDays( end.getTime() - start.getTime() );
System.out.println( "!!! Amount of days : " + String.valueOf( days ) );

cal.set( 2013, java.util.Calendar.MARCH, 1 );
start = cal.getTime();

cal.set( 2013, java.util.Calendar.MARCH, 31 );
end = cal.getTime();

days = java.util.concurrent.TimeUnit.MILLISECONDS.toDays( end.getTime() - start.getTime() );
System.out.println( "!!! Amount of days : " + String.valueOf( days ) );

I get:

!!! Amount of days : 30
!!! Amount of days : 29

For explanation, see comment by David Wallace on this answer.

Daylight Saving Time (United States) 2013 began at 2:00 AM on Sunday, March 10.

I executed same code in my system it is giving me output as :

!!! Amount of days : 31

please check your code again.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top