Amira Elsayed Ismail
Amira Elsayed Ismail

Reputation: 9394

How to calculate the difference between two times

I want to calculate the sleeping time of user, he should enter when he slept and when he woke up and I should calculate how many hours he slept

For example if the user enter

His sleeping time : 11:00 pm

His waking up time : 7:30 am

The number of sleeping hours should be : 8:30 hrs

Is there any way to make this calculation easily

This is the code

cal.set(Calendar.HOUR_OF_DAY, 11);
        cal.set(Calendar.MINUTE, 0);
        sleepTimeOnOffDays = cal.getTime();

    private long subtractTwoDates(Date date1, Date date2) {

            Calendar calendar1 = Calendar.getInstance();
            Calendar calendar2 = Calendar.getInstance();
            calendar1.setTime(date1);
            calendar2.setTime(date2);
            long milsecs1 = calendar1.getTimeInMillis();
            long milsecs2 = calendar2.getTimeInMillis();
            long diff = milsecs2 - milsecs1;
            long dhours = diff / (60 * 60 * 1000);

            return Math.abs(dhours);
        }

Upvotes: 2

Views: 1185

Answers (4)

Basil Bourque
Basil Bourque

Reputation: 338306

tl;dr

11:00 PM to 7:30 AM = 7.5 or 8.0 or 8.5 or 9.5 or some other number of hours depending on the particular dates and time zone.

Duration.between(
    ZonedDateTime.of( 2019 , 1 , 23 , 23 , 0 , 0 , 0 , ZoneId.of( "Africa/Cairo" ) ) ,
    ZonedDateTime.of( 2019 , 1 , 24 , 7 , 30 , 0 , 0 , ZoneId.of( "Africa/Cairo" ) )
)
.toString()

See this code run live at IdeOne.com.

PT8H30M

Calculating elapsed time requires date, time-of-day, and time zone

The Answer by Markus Hänsel is headed the right way, but fails to account for anomalies such as Daylight Saving Time (DST).

Your Question is not quite clear. Do you mean to track the general idea of time-of-day using generic 24-hour days? Or do you mean to track actual moments, such as the time slept two days ago, the time slept yesterday, and so on?

If the latter, then you cannot use LocalDateDate as that class cannot, by definition, track moments. The LocalDateTime class lacks any concept of time zone or offset-from-UTC. As such, a LocalDateTime represents potential moments along a range of about 26-27 hours (the range of time zones around the globe).

Given your example of 11:00 pm to 7:30 am, that would mean 8.5 hours in a certain time zone with no anomalies on that date. But on a day of DST cut-over that might mean 7.5 hours (“Spring ahead”), or 9.5 hours (“Fall back”). Or maybe 8.0 hours on day such as last year when North Korea adjusted their clock by a half-hour. Or when in 2007 Venezuela turned back time a half-hour… and then a decade later flipped back again. These changes happen more often than you may realize. Politicians around the globe have shown a penchant for redefining the offset of their time zone(s).

➥ The upshot is that you cannot reliably calculate elapsed time with only the time-of-day. You must use a date and a time zone.

ZoneId

Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;

ZonedDateTime

To track moments, use the ZonedDateTime class. This class combines a date, a time-of-day, and a time zone.

LocalDate ldStart = LocalDate.of( 2019 , 1 , 23 ) ;
LocalTime ldStart = LocalTime.of( 23 , 0 ) ;
ZonedDateTime zdtStart = ZonedDateTime.of( ldStart , ltStart , z ) ;

And the stop time.

LocalDate ldStop = LocalDate.of( 2019 , 1 , 24 ) ;  // Next day.
LocalTime ldStop = LocalTime.of( 7 , 30 ) ;
ZonedDateTime zdtStop = ZonedDateTime.of( ldStop , ltStop , z ) ;

Calculate elapsed time using Duration class.

Duration d = Duration.between( zdtStart , zdtStop ) ;

ISO 8601

I recommend you not report elapsed time using time-of-day format, HH:MM:SS. Instead use the standard format defined for this purpose, in the ISO 8601 standard.

So, 8.5 hours would be PT8H30M.

The java.time classes use ISO 8601 formats by default when parsing/generating strings.

String output = d.toString() ;  // Generate `PT8H30M`.

And parsing.

Duration d = Duration.parse( "PT8H30M" ) ;

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?

Table of which java.time library to use with which version of Java or Android

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.

Upvotes: 3

Markus Hänsel
Markus Hänsel

Reputation: 31

From Java SE 8 onwards i would like to suggest using the java.time API. For Android users, java.time is added in API 26+.

Java 8 introduced new APIs for Date and Time to address the shortcomings of the older java.util.Date and java.util.Calendar.

Using the java.time API calculating the duration between 2 date times is very easy.

LocalDateTime localDateTime1 = LocalDateTime.now();
localDateTime1 = localDateTime1.withHour(23).withMinute(0).withSecond(0).withNano(0);

LocalDateTime localDateTime2 = LocalDateTime.now();
localDateTime2 = localDateTime2.plusDays(1).withHour(7).withMinute(30).withSecond(0).withNano(0);

Duration diff = Duration.between(localDateTime1, localDateTime2);

String hms = String.format("%d:%02d:%02d", 
                 diff.toHoursPart(),
                 diff.toMinutesPart(), 
                 diff.toSecondsPart());
System.out.println(hms);

-----------------------

Console output:
8:30:00

If the java.time API is not available for your project, because for example your project is not yet on API level 26, then i would recommend using the ThreeTen Android Backport API as suggested by @Ole V.V in the comments below.

The Syntax is pretty much the same as the java.time API. The code snippet above works for the ThreeTen Android Backport API as well (like @Basil Bourque already mentioned) with one exception. The Duration class of the ThreeTen Android Backport API unfortunately does not provide helper methods for extracting the hours part, minutes part etc. from the duration object. Instead when you use the backport you need to subtract first the hours, then the minutes from the duration so only the seconds are left:

long hours = diff.toHours();
diff = diff.minusHours(hours);
long minutes = diff.toMinutes();
diff = diff.minusMinutes(minutes);
long seconds = diff.getSeconds();
String hms = String.format("%d:%02d:%02d", 
                 hours,
                 minutes, 
                 seconds);

Another difference is you need to import the java.time classes from the org.threeten.bp package (not the java.time package).

If you want to use the ThreeTen Backport API, just include it's dependency to your project.

Upvotes: 3

munipratap
munipratap

Reputation: 53

Just Try following line of code to get difference in minutes

import java.util.concurrent.TimeUnit; // predefined method from java 6.

  private long subtractTwoDates(Date date1, Date date2) {
    Long diffInMinutes=null,diff=null;  // just  declaration of variables
    diff = date1.getTime() - date2.getTime();
    diffInMinutes= TimeUnit.MILLISECONDS.toMinutes(diff);
    log.info("diff min : "+difInMin); 
    return  diffInMinutes; // returns long value in minutes.
}

Upvotes: 0

Alok
Alok

Reputation: 8978

You can use the SimpleDateFormat for getting the input. I'm using the predefined input, since you wanted the difference calculation between two given times. Here is the code fo you. Please note I have given out the answer for both 24 or 12 hours format.

Getting the value of sleep time and waking up time

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
Date sleepingTime = simpleDateFormat.parse("22:00");
Date wakeUptime = simpleDateFormat.parse("07:00");

For difference is less than zero, this happens in 12 hours format

long difference = sleepingTime.getTime() - wakeUpTime.getTime(); 
if(difference<0) {
  Date dateMax = simpleDateFormat.parse("24:00");
  Date dateMin = simpleDateFormat.parse("00:00");
  difference=(dateMax.getTime() -sleepingTime.getTime() )+(wakeUpTime.getTime()- 
  dateMin.getTime());
}

Calculating the difference

//days and minutes are optional
int days = (int) (difference / (1000*60*60*24));  
int hours = (int) ((difference - (1000*60*60*24*days)) / (1000*60*60)); 
int min = (int) (difference - (1000*60*60*24*days) - (1000*60*60*hours)) / 
(1000*60);
Log.e("log_tag",hours+" hours"); 

I hope it will answer your query. Thanks :)

Upvotes: 0

Related Questions