user3015561
user3015561

Reputation: 71

Calendar in Java... I get the same result for two different values

    Calendar cal = Calendar.getInstance();
    long now = cal.getTimeInMillis();
    int year = 2014;
    int month = 3;
    int date = 8;
    cal.set(year, month - 1, date);
    long dday = cal.getTimeInMillis();
    long count = (dday - now) / (1000 * 24 * 60 * 60);
    System.out.println((dday - now));
    System.out.println(count);

This code figures out how many days between now and a date. However, I get the same result for Mar. 8 and Mar. 9. Please help! Thank you in advance.


More detailed source code example, by Basil Bourque.

Calendar cal = Calendar.getInstance();
long nowInMillis = cal.getTimeInMillis();

cal.set( 2014, Calendar.MARCH, 8 );  // March 8, 2014   // year, month, day
long march_8_2014_inMillis = cal.getTimeInMillis();

cal.set( 2014,  Calendar.MARCH, 9 );  // March 9, 2014   // year, month, day
long march_9_2014_inMillis = cal.getTimeInMillis();

long daysTil8th = ( march_8_2014_inMillis - nowInMillis ) / ( 1000 * 24 * 60 * 60 );
long daysTil9th = ( march_9_2014_inMillis - nowInMillis ) / ( 1000 * 24 * 60 * 60 );

System.out.println( "( march_8_2014_inMillis - nowInMillis ) in artificial days: " + daysTil8th + ", in milliseconds: " + ( march_8_2014_inMillis - nowInMillis ) );
System.out.println( "( march_9_2014_inMillis - nowInMillis ) in artificial days: " + daysTil9th + ", in milliseconds: " + ( march_9_2014_inMillis - nowInMillis ) );

System.out.println( "( march_9_2014_inMillis - nowInMillis ) - ( march_8_2014_inMillis - nowInMillis ): " + ( ( march_9_2014_inMillis - nowInMillis ) - ( march_8_2014_inMillis - nowInMillis ) ) ) ;
System.out.println( "( march_9_2014_inMillis - nowInMillis ) - ( march_8_2014_inMillis - nowInMillis ) / ( 1000 * 60 * 60 ): " + ( ( march_9_2014_inMillis - nowInMillis ) - ( march_8_2014_inMillis - nowInMillis ) ) / ( 1000 * 60 * 60 ) ) ;

When run in Seattle, Java 7, Mac OS X 10.8.5 at 2013-11-20T17:35:01.119-08:00 (Pacific Standard Time)…

( march_8_2014_inMillis - nowInMillis ) in artificial days: 108, in milliseconds: 9331200000
( march_9_2014_inMillis - nowInMillis ) in artificial days: 108, in milliseconds: 9414000000
( march_9_2014_inMillis - nowInMillis ) - ( march_8_2014_inMillis - nowInMillis ): 82800000
( march_9_2014_inMillis - nowInMillis ) - ( march_8_2014_inMillis - nowInMillis ) / ( 1000 * 60 * 60 ): 23

NOTE: For my time zone, DST begins 2:00 AM on Sunday, March 9, 2014.

QUESTION: Why 108 in both lines of output above? The answer is DST, but how exactly?

Upvotes: 1

Views: 266

Answers (2)

Basil Bourque
Basil Bourque

Reputation: 338730

As Jim Garrison said in his correct answer, your integer-based math (1000 * 24 * 60 * 60) assumes 24-hours in a day. Not true for those of us in a time zone with the irrational practice of Daylight Saving Time (DST). Between the 8th and 9th in United States’ time zones is 23 hours, not 24.

Lessons learned:

  • Never do your own Date and Time math.
  • Never use java.util.Date & .Calendar bundled in Java.
  • Always use a decent library such as Joda-Time or the new JSR 310 in Java 8.

Here's the same problem solved in Java 7 with Joda-Time 2.3, and correct output.

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.

// Using US west coast time zone because March 9, 2014 at 02:00 is the start of DST Daylight Saving Time.
org.joda.time.DateTimeZone californiaTimeZone = org.joda.time.DateTimeZone.forID("America/Los_Angeles");

org.joda.time.DateTime now = new org.joda.time.DateTime(californiaTimeZone);

// Note the arbitrary choice of times (14 & 21 hours) assigned to new DateTimes.
org.joda.time.DateTime march_8_2014 = new org.joda.time.DateTime( 2014, 3, 8, 14, 0);
org.joda.time.DateTime march_9_2014 = new org.joda.time.DateTime( 2014, 3, 9, 21, 0);

int daysUntil8th = org.joda.time.Days.daysBetween( now , march_8_2014 ).getDays();
int daysUntil9th = org.joda.time.Days.daysBetween( now , march_9_2014 ).getDays();

// If you want whole days, call 'withTimeAtStartOfDate()' method.
// Don't get clever with trying to set a midnight time. Not every day in every time zone has a midnight.
int daysUntil8thStarts = org.joda.time.Days.daysBetween( now , march_8_2014.withTimeAtStartOfDay() ).getDays();
int daysUntil9thStarts = org.joda.time.Days.daysBetween( now , march_9_2014.withTimeAtStartOfDay() ).getDays();

System.out.println("Now in 'America/Los_Angeles' (Pacific Standard Time): " + now );

System.out.println("Days until " +  march_8_2014 + ": " + daysUntil8th );
System.out.println("Days until " + march_9_2014 + ": " + daysUntil9th );

System.out.println("Days until March 8, 2014 starts: " + daysUntil8thStarts );
System.out.println("Days until March 9, 2014 starts: " + daysUntil9thStarts );

When run…

Now in 'America/Los_Angeles' (Pacific Standard Time): 2013-11-20T18:25:06.424-08:00
Days until 2014-03-08T14:00:00.000-08:00: 107
Days until 2014-03-09T21:00:00.000-07:00: 109
Days until March 8, 2014 starts: 107
Days until March 9, 2014 starts: 108

NOTE: Time of day affects the count of days. Notice 107 & 109 versus 107 & 108, a two day difference versus one day difference.

Upvotes: 0

Jim Garrison
Jim Garrison

Reputation: 86774

March 9th is the day on which DST will switch in 2014. So, the calculation is right, the difference for March 9th is 108 days 23 hours, which rounds to 108 days.

Upvotes: 3

Related Questions