Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference Between two dates in minutes - different months - Java

I want to find the difference in minutes between 2 dates. My code works well if the 2 dates are in the same month(and year) but it seems like the difference considers every month to be 31 days long so for the dates:

 2016-02-29 12:21
 2016-03-1 12:21

I get 4320 minutes or 72 hours

for:

 2016-04-30 12:21
 2016-05-01 12:21

I get 2880 minutes or 48 hours

my code where d1 and d2 are Date objects:

long getDateDiff(Date d1, Date d2, TimeUnit timeUnit) {
    long diff = d2.getTime() - d1.getTime(); //in millisec
    long diffMinutes = TimeUnit.MILLISECONDS.toMinutes(diff);
    return diffMinutes;
}
like image 595
toiavalle Avatar asked Feb 06 '23 02:02

toiavalle


1 Answers

tl;dr

Parse your input strings.

LocalDateTime startLdt = LocalDateTime.parse( "2016-04-30T12:21" ) ;
LocalDateTime stopLdt = LocalDateTime.parse( "2016-05-01T12:21") ;

Assign the time zone or offset-from-UTC intended but omitted from the inputs. I assume you intended UTC itself (an offset of zero).

OffsetDateTime start = startLdt.atOffset( ZoneOffset.UTC );
OffsetDateTime stop = stopLdt.atOffset( ZoneOffset.UTC ) ;

Calculate elapsed time on the scale of days (24-hour chunks of time), hours, minutes, seconds, and nanoseconds.

Duration d = Duration.between( start , stop ) ;

d.toString(): PT24H

Your first example results in 24 hours, as seen when code runs live at IdeOne.com.

Your second example also results in 24 hours, as seen in IdeOne.com.

Details

The Question and other Answers all use the troublesome old date-time classes or the Joda-Time library. Both are supplanted by the java.time classes.

Using java.time

Convert your Date objects to Instant objects, the equivalent in java.time. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Instant start = d1.toInstant();
Instant stop = d2.toInstant();

Use Duration (or Period) for the span of time in between.

Duration d = Duration.between( start , stop );

Extract the total number of minutes across the entire span-of-time.

long minutes = d.toMinutes() ;

Time zone

You do not mention the time zone intended for example date-time values. Is their context UTC? Or did you intend some particular time zone. In various time zones, anomalies such as Daylight Saving Time (DST) means days are not always 24 hours long. So time zone is crucial.

Let's look at UTC.

// of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond, ZoneOffset offset)
OffsetDateTime odtStart1 = OffsetDateTime.of ( 2016 , 2 , 29 , 12 , 21 , 0 , 0 , ZoneOffset.UTC );
OffsetDateTime odtStop1 = OffsetDateTime.of ( 2016 , 3 , 1 , 12 , 21 , 0 , 0 , ZoneOffset.UTC );
Duration d1 = Duration.between ( odtStart1 , odtStop1 );

OffsetDateTime odtStart2 = OffsetDateTime.of ( 2016 , 4 , 30 , 12 , 21 , 0 , 0 , ZoneOffset.UTC );
OffsetDateTime odtStop2 = OffsetDateTime.of ( 2016 , 5 , 1 , 12 , 21 , 0 , 0 , ZoneOffset.UTC );
Duration d2 = Duration.between ( odtStart2 , odtStop2 );

System.out.println ( odtStart1 + "/" + odtStop1 + " = " + d1 );
System.out.println ( odtStart2 + "/" + odtStop2 + " = " + d2 );

2016-02-29T12:21Z/2016-03-01T12:21Z = PT24H

2016-04-30T12:21Z/2016-05-01T12:21Z = PT24H

The string generated by toString is in standard ISO 8601 format for durations. The P marks the beginning, the T separates any years-months-days portion from any hours-minutes-seconds portion.

In both cases the result is twenty-four hours. This is correct because in each case you chose to go from the last day of one month to the first day of the following month. UTC has no anomalies, so we expect exactly 24 hours elapsed.

You can compare the Duration objects by calling compareTo. And you can do math to get the difference between them. In this case we expect a different of zero.

Duration difference = d1.minus( d2 );

difference.toString(): PT0S

See this code run live at IdeOne.com.


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, Java SE 11, and later - 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.

like image 50
Basil Bourque Avatar answered Feb 07 '23 19:02

Basil Bourque