I am trying to calculate the difference between two dates. The difference consist of remaining Days, Hours, Minutes, Seconds.
I'm using this method:
public static void computeDiff(Date date2) {
Date date1 = new Date();
long diffInMillies = date2.getTime() - date1.getTime();
long milliesRest = diffInMillies;
for ( TimeUnit unit : timeUnitsArrayList ) {
long diff = unit.convert(milliesRest, TimeUnit.MILLISECONDS);
long diffInMilliesForUnit = unit.toMillis(diff);
milliesRest -= diffInMilliesForUnit;
result.put(unit, diff);
}
}
/*
TimeUnit = java.util.concurrent.TimeUnit
timeUnitsArrayList = A list with units: DAYS, HOURS, MINUTES, SECONDS
date1 = java.util.Date (date now)
date2 = java.util.Date (a date with time 00:00:00)
*/
I'm giving an example: If i want the difference between today and and 20 March 2015, the difference will be ok (8 days, X hours, Y minutes, Z seconds), but if i choose an older date like 20 April 2015 the difference will be 39 days (ok), X - 1 hours (which isn't ok because is calculating wrong), Y minutes (ok), Z seconds(ok).
Is a Java bug or a bug in my code? Because if i choose an earlier date, the hours are ok, but if i choose an older date i get the hours wrong (one less hour)
Thank you
This is most probably an issue with the switch to daylight saving time - in central europe the change is on 29 March, so in your timezone (wherever that is) it might be similar and would account for the 1 hour.
Related
This question already has an answer here:
Difference in time - from before midnight to after midnight without date
(1 answer)
Closed 3 years ago.
i need java code to find difference between two times in 24 hour format
for example:
20:00:00 - 04:00:00
and the expected output is 8 hrs
but now output is 16 hrs
when i tried 12 hour format out put is coming 4.
below is the code used to parse and to find difference
SimpleDateFormat readFormat = new SimpleDateFormat("HH:mm");
Date d1 = readFormat.parse(txtshiftIn);
Date d2 = readFormat.parse(txtshiftOut);
long diff = d2.getTime() - d1.getTime();
input is just 20:00 and 04:00 no seconds and AM/PM part.
The issue with using Date is it still expects an actual date even though you are using just the time portion of it, so if you're just sending it the time it will not be correct.
Instead use LocalTime and ChronoUnit.HOURS to get the difference between the time.
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm");
LocalTime lt1 = LocalTime.parse(txtshiftIn, dtf);
LocalTime lt2 = LocalTime.parse(txtshiftOut, dtf);
long diff = ChronoUnit.HOURS.between(lt1, lt2);
This will show -16 which means that lt1 is ahead of lt2 which indicates lt2 is the next day so we can modify it to get the differences as such
if (diff < 0) {
diff += 24;
}
This will give you the 8 hour difference you're expecting.
UPDATE
To account the difference in minutes you can do the following:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm");
LocalTime lt1 = LocalTime.parse(txtshiftIn, dtf);
LocalTime lt2 = LocalTime.parse(txtshiftOut, dtf);
long diff = ChronoUnit.MINUTES.between(lt1, lt2); //get diff in minutes
if (lt2.isBefore(lt1)) {
diff += TimeUnit.DAYS.toMinutes(1); //add a day to account for day diff
}
long hours = diff / 60;
long minutes = diff % 60;
LocalTime newTime = LocalTime.parse(String.format("%02d:%02d", hours, minutes), dtf); //Format the difference to be converted to LocalTime
System.out.println(newTime);
This will produce the difference in minutes:
08:30
Update 2
Here is a cleaner method that returns a Duration
public Duration timeDifference(String txtshiftIn, String txtshiftOut) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm");
LocalTime lt1 = LocalTime.parse(txtshiftIn, dtf);
LocalTime lt2 = LocalTime.parse(txtshiftOut, dtf);
Duration between = Duration.between(lt1, lt2);
if (lt2.isBefore(lt1)) { //account for lt2 being on the next day
between = Duration.ofMinutes(TimeUnit.DAYS.toMinutes(1)).plus(between);
}
return between;
}
While it is strongly recommended you use a more up-to-date Java time library like LocalTime your logic so far actually is correct with one little caveat:
SimpleDateFormat readFormat = new SimpleDateFormat("HH:mm");
Date d1 = readFormat.parse(txtshiftIn);
Date d2 = readFormat.parse(txtshiftOut);
long diff = d2.getTime() - d1.getTime();
In your code if d1 is after d2 you will get a negativ result for long diff
So when you say
"but now output is 16 hrs"
The actual output is -16 hrs
Of course minus sixteen hours doesn't make much sense in your case, but you can easily fix that with the simple trick of just adding 24 hours in case of a negative result for diff. (And -16+24 is the 8 you expected as a result).
So just add the following lines at the end of your posted code
if(diff < 0) {
diff = 86400000 + diff;
}
And you will get the results you expect!
(86400000 is the 24h expressed in milliseconds)
This question already has answers here:
How can I create a Java 8 LocalDate from a long Epoch time in Milliseconds?
(8 answers)
Calculate days between two Dates in Java 8
(14 answers)
Closed 4 years ago.
I want to calculate how many day difference between 2 timestamps, but i do not want to consider the time difference.
For example :
long time1 = 1546258765000 (Mon 31 December 2018 13:19:25)
long time2 = 1546005915367 (Fri 28 December 2018 15:05:15)
The result should be 3, 3 days left for expire...
Due to time I get 2 from this method:
TimeUnit.DAYS.convert(time1 - time2 , TimeUnit.MILLISECONDS))
I just need to set the time same for both time1 and time2, and then go back to timestamp and calculate like this... but I am not sure what is the best way to do it.
NOTE: As noted by Ole V.V: this only works for UTC. Since timestamps are always on UTC, if you are in another timezone it might return undesired results. Example:
In GMT + 1:
time1 = 1546216200000L (Mon 31 December 2018 01:30:00) (31/12 00:30 on UTC)
time2 = 1545953400000L (Fri 28 December 2018 00:30:00) (27/12 11:30 on UTC)
This will result in a 4 days difference, since that's the difference on UTC.
To compensate that, you should offset the difference so the timestamps show your current time, instead of UTC time. (If you are in GMT+1, for example, you will need to add 1 hour (3600000 ms) to each timestamp).
I believe the simplest way might be using module:
final long MILLIS_PER_DAY = 1000*60*60*24;
long time1 = 1546258765000L; // (Mon 31 December 2018 13:19:25)
long time2 = 1546005915367L; // (Fri 28 December 2018 15:05:15)
// Set both times to 0:00:00
time1 -= time1 % MILLIS_PER_DAY;
time2 -= time2 % MILLIS_PER_DAY;
And then
TimeUnit.DAYS.convert(time1 - time2 , TimeUnit.MILLISECONDS))
should give you the desired result.
Convert millis to LocalDateTime then calculate the Duration:
LocalDateTime start = LocalDateTime
.ofInstant(Instant.ofEpochMilli(1546005915367L), ZoneId.systemDefault())
.truncatedTo(ChronoUnit.DAYS);
LocalDateTime stop = LocalDateTime
.ofInstant(Instant.ofEpochMilli(1546258765000L), ZoneId.systemDefault())
.truncatedTo(ChronoUnit.DAYS);
Duration duration = Duration.between(start, stop);
long dayDifference = duration.toDays();
Converts the given time duration in the given unit to this unit.
Conversions from finer to coarser granularities truncate, so lose precision. For example, converting 999 milliseconds to seconds results in 0.
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/TimeUnit.html#convert(long,%20java.util.concurrent.TimeUnit)
Use joda-time lib:
long time1 = 1546258765000L;
long time2 = 1546005915367L;
DateTime dateTime1 = new DateTime(time1);
DateTime dateTime2 = new DateTime(time2);
int hours = Hours.hoursBetween(dateTime2, dateTime1).getHours();
int days = hours % 24 == 0 ? hours / 24 : hours / 24 + 1;
System.out.println(days);
joda-time lib has method to calculate days between two time,but the result is not your want:
Days.daysBetween(dateTime1,dateTime2).getDays()
The variable dateSubtract comes out to 16 but I want to find the total number of days in between the 2 days, which should be 165. How can I do this WITHOUT JODA TIME?
String date = "06/17/2014";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy");
LocalDate d1 = LocalDate.parse("01/01/2014", formatter);
LocalDate d2 = LocalDate.parse(date, formatter);
int dateSubtract = Period.between(d1, d2).getDays();
Period is a combination of day, month, year. So in your case, the period is 5 months and 16 days. It is explained in the javadoc although not necessarily very clear if you read it casually.
The days unit is not automatically normalized with the months and years unit. This means that a period of "45 days" is different to a period of "1 month and 15 days" and getDays() will return 45 and 15 respectively.
To get the total number of days between two dates, you can use:
//including d1, excluding d2:
ChronoUnit.DAYS.between(d1, d2);
//or, to exclude d1 AND d2, one of these:
ChronoUnit.DAYS.between(d1.plusDays(1), d2);
ChronoUnit.DAYS.between(d1, d2) - 1;
Without JODA time:
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");
Date dateStart = null;
Date dateEnd = null;
try {
dateStart = format.parse("01/01/2014");
dateEnd = format.parse("06/17/2014");
long diffTime = dateEnd.getTime() - dateStart.getTime();
long diffDays = diffTime / (24 * 60 * 60 * 1000);
} catch (Exception e) {
e.printStackTrace();
}
Period models a quantity or amount of time in terms of years, months and days,
such as 2 years, 3 months and 4 days.
To calculate days between two date use ChronoUnit.DAYS.between
long days = ChronoUnit.DAYS.between(LocalDate.of(2020,4,1), LocalDate.now());
I have to calculate the difference between to dates, I have found a way but I have this strange result, Am I missing something?
public static void main(String[] args) throws ParseException {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
long result = format.parse("2012-03-25 24:00").getTime() - format.parse("2012-03-25 00:00").getTime();
System.out.println("Difference in hours: " + result/(1000*60*60));
result = format.parse("2012-03-26 24:00").getTime() - format.parse("2012-03-26 00:00").getTime();
System.out.println("Difference in hours: " + result/(1000*60*60));
}
This is the result:
Difference in hours: 23
Difference in hours: 24
Thanks for the advices, now I'm using the Joda libray, I have this question, when I calculate the difference in this way:
DateTime begin = new DateTime("2012-03-25T00:00+01:00");
DateTime end = new DateTime("2012-03-26T00:00+01:00");
Hours m = Hours.hoursBetween(begin, end);
If I use this way to calculate the hours I get 24 hours (because the DST is not considered I assume)
What class/calculus should I use in order to get as result the 23 hours considering the DST (I have already tried different ways but I don't get it) the Period class?
Thanks for all the help...
Chances are you happen to have picked a date where daylight saving time changed in that time zone, so the day could really have been only 23 hours long. (March 25th 2012 certainly was the DST change date for Europe, e.g. Europe/London. We don't know what your default time zone is though.)
If you set your date format to use UTC, you shouldn't see this effect. (It's somewhat odd to use 24:00 in a string representation, mind you.) It's not clear what your data is meant to represent though, or what you're trying to measure. You should work out what time zone your data is really meant to be in, if you want to work out how much time actually elapsed between those local times.
(As noted in another answer, Joda Time is a much better API in general - but you still need to know how to use it properly, and when trying to work out the actual elapsed time, you'd still have seen the same results here.)
Must place the library file like explained below.
import java.util.Date;
String dateStart = dateChooserCombo1.getText();
String dateStop =dateChooserCombo2.getText();
//HH converts hour in 24 hours format (0-23), day calculation
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");
Date d1 = null;
Date d2 = null;
try {
d1 = format.parse(dateStart);
d2 = format.parse(dateStop);
//in milliseconds
long diff = d2.getTime() - d1.getTime();
long diffSeconds = diff / 1000 % 60;
long diffMinutes = diff / (60 * 1000) % 60;
long diffHours = diff / (60 * 60 * 1000) % 24;
long diffDays = diff / (24 * 60 * 60 * 1000);
//System.out.print(diffDays + " days, ");
jTextField3.setText(""+diffDays);
} catch (Exception e) {
e.printStackTrace();
}
I have two Date objects and I need to get the time difference so I can determine the total hours between them. They happen to be from the same day. The result I would like would have the hours and minutes.
When I use .toString() on my Date object I get this: Fri Dec 18 08:08:10 CST 2009
I've tried the following:
long diff = (this.endDate.getTime() - this.startDate.getTime()) / (60 * 60 * 1000);
But this only gives me hours, not the minutes.
I know this is a simple problem, but I can't figure it out atm.
Edits:
Final solution for those interested. Thanks to Michael Brewer-Davis
Period p = new Period(this.startDate, this.endDate);
long hours = p.getHours();
long minutes = p.getMinutes();
String format = String.format("%%0%dd", 2);
return Long.toString(hours) + ":" + String.format(format, minutes);
This should work.
long secs = (this.endDate.getTime() - this.startDate.getTime()) / 1000;
int hours = secs / 3600;
secs = secs % 3600;
int mins = secs / 60;
secs = secs % 60;
Here's how it works with Joda time:
DateTime startTime, endTime;
Period p = new Period(startTime, endTime);
int hours = p.getHours();
int minutes = p.getMinutes();
You could format with Joda's formatters, e.g., PeriodFormat, but I'd suggest using Java's. See this question for more details.
EDIT: be careful using this method to check hours between. This function don't respect days between. It get just hours between two times. 2022-07-20 11.00 and 2022-07-21 12.00 will return 1 hour, not 25 hours.
Here's simple way:
private static int hoursDifference(Date date1, Date date2) {
final int MILLI_TO_HOUR = 1000 * 60 * 60;
return (int) (date1.getTime() - date2.getTime()) / MILLI_TO_HOUR;
}
java.time.Duration
I should like to contribute the modern (java 8+) answer. The solutions using Joda-Time are fine. The Joda-Time project is in maintenance mode, so for new code we should not use it. I follow the official recommendation from the Joda-Time project and use java.time, the modern Java date and time API:
Duration dur = Duration.between(startDate, endDate);
String result = String.format("%d:%02d", dur.toHours(), dur.toMinutesPart());
System.out.println(result);
This works if startDate and endDate both have type Instant or OffsetDateTime or ZonedDateTime or LocalDateTime or LocalTime. All of the mentioned types are from java.time package. If starting with LocalDate, call either of the atStartOfDay methods.
The toMinutesPart methof was introduced in Java 9. If you are using Java 8 (ot ThreeTen Backport), search for java format duration or similar to learn how to format the duration into hours and minutes.
Two quotes from the Joda-Time home page:
Users are now asked to migrate to java.time (JSR-310).
Note that Joda-Time is considered to be a largely “finished” project.
No major enhancements are planned. If using Java SE 8, please migrate
to java.time (JSR-310).
Links
Oracle tutorial: Date Time explaining how to use java.time.
Joda-Time home page
Please follow Somaiah's suggestion in a comment, use Hours instead:
Hours hours = Hours.hoursBetween(startTime, endTime);
The call to getHours() will only return the hour section of the time difference and ignore all year, month differences so it would not be correct in some cases.
If you use Period.toStandardHours() to try to convert the time difference into hours the calculation will throw an exception if the time difference between the two dates includes difference in either year or month, since the length of month is unknown.
So the getTime() method, I presume, returns an integer.
In which case, the left set of parentheses has type int, right?
and
(60*60*1000)
is also an int.
Which means you get long diff = ((int)/(int)) so the integer division is done BEFORE you cast stuff to long. And hence you lose your minutes.
Try casting them BEFORE you divide.
for kotlin, you can use below function and get hours between two date
private val dateFormat: String = "yyyy-MM-dd # hh:mm a"
val startDate = SimpleDateFormat(dateFormat).parse("2018-10-01 # 12:33 PM")
val endDate = SimpleDateFormat(dateFormat).parse("2018-10-01 # 02:46 PM")
private fun hoursDifference(date1: Date, date2: Date): Int {
val milliToHour : Long = 1000 * 60 * 60
return ((date1.time - date2.time) / milliToHour).toInt()
}
println(hoursDifference(endDate,startDate).toString())
Output:
2
Even though there's already an accepted answer, this is what worked for me using the Joda time library.
/**
*
* #param date1
* #param date2
* #return hours between two dates rounded down
*/
public static int hoursBetween(DateTime date1, DateTime date2) {
if(date1 == null || date2 == null) return NOT_FOUND;
return Math.abs(Hours.hoursBetween(date1.toLocalDateTime(), date2.toLocalDateTime()).getHours());
}
private void getHours(Date d1, Date d2){
long diff = d2.getTime() - d1.getTime();
long diffSeconds = diff / 1000 % 60;
long diffMinutes = diff / (60 * 1000) % 60;
long diffDays = diff / (24 * 60 * 60 * 1000);
long diffHours = diff / (60 * 60 * 1000) % 24;
System.out.print(diffDays + " days, ");
System.out.print(diffHours + " hours, ");
System.out.print(diffMinutes + " minutes, ");
System.out.print(diffSeconds + " seconds.\n");
}`
//Displays:
/* 1 days, 1 hours, 1 minutes, 50 seconds. */
Here's a pure Java 8+ solution that does not involve Joda or mathematical operations
import java.time.*;
import java.time.temporal.*;
// given two java.util.Dates
Date startDate ...
Date endDate ...
// convert them to ZonedDateTime instances
ZonedDateTime start = ZonedDateTime.ofInstant(startDate.toInstant(), ZoneId.systemDefault());
ZonedDateTime end = ZonedDateTime.ofInstant(endDate.toInstant(), ZoneId.systemDefault());
// get the total duration of minutes between them
Duration total = Duration.ofMinutes(ChronoUnit.MINUTES.between(start, end));
// use the duration to determine the hours and minutes values
long hours = total.toHours();
long minutes = total.minusHours(hours).toMinutes();
Here is the simple method :-
Check your Date format,if your date not in this format then change it and pass to this method it will give you a String which is your result. Modify the method as per the requirement.
private String getDateAsTime(String datePrev) {
String daysAsTime = "";
long day = 0, diff = 0;
String outputPattern = "yyyy:MM:dd HH:mm:ss";
SimpleDateFormat outputFormat = new SimpleDateFormat(outputPattern);
Calendar c = Calendar.getInstance();
String dateCurrent = outputFormat.format(c.getTime());
try {
Date date1 = outputFormat.parse(datePrev);
Date date2 = outputFormat.parse(dateCurrent);
diff = date2.getTime() - date1.getTime();
day = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
} catch (ParseException e) {
e.printStackTrace();
}
if (day == 0) {
long hour = TimeUnit.HOURS.convert(diff, TimeUnit.MILLISECONDS);
if (hour == 0)
daysAsTime = String.valueOf(TimeUnit.MINUTES.convert(diff, TimeUnit.MILLISECONDS)).concat(" minutes ago");
else
daysAsTime = String.valueOf(hour).concat(" hours ago");
} else {
daysAsTime = String.valueOf(day).concat(" days ago");
}
return daysAsTime;
}
Hope this will help,