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()
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 an answer here:
Incorrect jodatime period - years months days
(1 answer)
Closed 6 years ago.
I just started to use Joda Time and for a week now I was satisfied with the results. I am trying to get the time range period between two dates of the format 'yyyy-MM-dd HH'.
Until I came to a test case I am writing and it seems to me the result is wrong:
2014-02-05 05 - 2016-02-04 05
Joda Results:
Years: 1 Months: 11 Days: 2 Hours: 0
Expected Results:
Years: 1 Months: 11 Days: 30 Hours: 0
I only need 1 more day to get it to a FULL 2 years....
I am not a QA but certainly this is a bug to me... I also talked to our QA about this and she agreed.
I want to raise a bug in Github but it pointed me to use Stackoverflow first.. any clarification will be greatly appreciated.
String hourFormat = "yyyy-MM-dd HH";
String startTime = "2014-02-05 05";
String endTime = "2016-02-04 05";
DateTimeFormatter hourFormatter = DateTimeFormat.forPattern(hourFormat);
DateTime start = hourFormatter.parseDateTime(startTime);
DateTime end = hourFormatter.parseDateTime(endTime );
Interval interval = new Interval(start, end);
Period period = interval.toPeriod();
System.out.println(String.format(
"Years: %d Months: %d Days: %d Hours: %d",
period.getYears(), period.getMonths(), period.getDays(), period.getHours()
));
Change the following lines of code
Interval interval = new Interval(start, end);
Period period = interval.toPeriod();
To
Period period = new Period(start, end, PeriodType.yearMonthDay());
This does seem like a bug to me. Definitely, as Interval actually stores the begin and end dates internally, it should be able to make a proper conversion to a Period (interval.toPeriod()).
I bet when you simply calculate the Period directly from the two dates (without the intermediate step to an Interval), it will work just fine. Example:
Period period = new Period(start,end);
Or if the calculation is not correct with differences in week, you might need to use (as per Incorrect jodatime period - years months days):
Period period = new Period(start,end,PeriodType.yearMonthDay());
In the case of Java 8 java.time.* libraries (JSR-310), Interval was actually omitted, and only Period and Duration are allowed. So in Java 8, you could do something like this:
String hourFormat = "yyyy-MM-dd HH";
DateTimeFormatter hourFormatter = DateTimeFormatter.ofPattern(hourFormat);
LocalDateTime start = LocalDateTime.parse("2014-02-05 05",hourFormatter);
LocalDateTime end = LocalDateTime.parse("2016-02-04 05",hourFormatter);
// Duration duration = Duration.between(start, end);
Period period = Period.between(start.toLocalDate(), end.toLocalDate());
System.out.println(
String.format("Years: %d Months: %d Days: %d Hours: xxx",
period.getYears(), period.getMonths(), period.getDays())
);
Other obvious limitation is that Period in JSR-310 only has a resolution up-to days (not hours).
See also this for further reference: Is there a class in java.time comparable to the Joda-Time Interval?
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.
I need to calculate period between two dates, one date is now. And I'm using SimpleDateFormat for formatting date.
public String getPeriod(Date endDate) {
String format;
Date now = new Date();
long period = endDate.getTime() - now.getTime();
if (now.after(endDate)) {
return "passed";
} else {
if (period < 1000 * 60 * 60)
format = "m'M' s'S'";
else if (period < 1000 * 60 * 60 * 24)
format = "k'H' m'M'";
else
format = "'Too much'";
SimpleDateFormat formatter = new SimpleDateFormat(format);
return formatter.format(new Date(period)) + " / for testing - " + period / 3600000 + " hours";
}
}
As a result I have following input for example if endDate equals Wed Nov 12 13:30:02 EET 2014 (EST):
1 H 36 M / for testing - 22 hours
As you can see my test calculation and format's method result do not match. What am i doing wrong?
The difference is due to the timezone. For example, in my case, given as the parameter the time that would be in an hour, I get 3H as output, because the date would be Thu Jan 01 03:00:00 EET 1970. Notice the EET (I'm from Eastern Europe).
Your code would work if you'd notify java to use GMT time, as it says in the new Date(long) description:
Allocates a Date object and initializes it to represent the specified
number of milliseconds since the standard base time known as "the
epoch", namely January 1, 1970, 00:00:00 GMT.
Also, keep in mind that Date does not give perfect results. Using programatically determined dates exactly 1h appart (no millies / minutes difference), date calculations give an offset of 59 minutes, 59 seconds and 999 milies. If you require more exact values, you should use nanoseconds.
However, the other commenters are right. You should not use Java Date / Calendar in such a way, as it is a bug factory (this is only one corner case). You should check out other libraries (such as yoda time), or if you only need simple calculations such as this, do it yourself.
Hope it helps.
I am trying to write a java block to find the number of mid-nights in a particular date range.
For example:
begin date: 05/01/2014 00:00:00
end date : 05/03/2014 00:00:00
this range has 3 mid-nights in it.
or
begin date : 05/01/2014 00:00:00
end date : 05/02/2014 23:59:59
this has only one.
It basically has to tell me how many times the time "00:00:00" occurrs in the date range.
Please help me out. I tried many approaches but none work correct.
I would just count the days (the actual dates), and add one if the earliest date has a time of 00:00:00.
begin date: 05/01/2014 00:00:00 end date : 05/03/2014 00:00:00
03 - 01 = 2 days.
Since the begin date has a time of 00:00:00, then add one:
2 + 1 = 3 midnights.
or
begin date : 05/01/2014 00:00:00 end date : 05/02/2014 23:59:59
02 - 01 = 1 day.
Since the begin date has a time of 00:00:00, then add one:
1 + 1 = 2 midnights.
Also,
begin date : 5/01/2014 23:59:59 end date : 5/02/2014 00:00:01
02 - 01 = 1 day.
Since the begin date doesn't have a time of 00:00:00, then don't add one:
1 midnight.
The answer using Joda-Time is not correct. As #khriskooper has noted the count of midnights between
2014-05-01 00:00:00 and 2014-05-02 23:59:59
is not one but two midnights!
So here the correction using Joda-Time (not tested), but it could also be any other library which supports day-range calculations (not true for old Java-pre8). I leave out the timezone detail because I do not consider it as really relevant for the question. If OP wants he can replace LocalDateTime by DateTime and apply a timezone.
LocalDateTime ldt1 = new LocalDateTime(2014, 5, 1, 0, 0, 0);
LocalDateTime ldt2 = new LocalDateTime(2014, 5, 2, 23, 59, 59);
int days = Days.daysBetween(ldt1.toLocalDate(), ldt2.toLocalDate()).getDays();
if (ldt1.toLocalTime().equals(new LocalTime(0, 0))) {
days++;
}
One option is to use Joda-Time library:
DateTimeZone zone = DateTimeZone.forID("America/New_York");
int days = Days.daysBetween(new DateTime(startDate, zone), new DateTime(endDate, zone)).getDays();
I think this is the easiest way. The drawback is that you need one more library..
Hope this can help!
Using Joda's DateTime library (one I would recommmend anyway), an elegant way to do so would be:
private int getNumberOfNights(DateTime start, DateTime end) {
int nightCount = 0;
DateTime tempEnd = new DateTime(end);
while (tempEnd.withTimeAtStartOfDay().isAfter(start)) {
nightCount++;
tempEnd = tempEnd.minusDays(1);
}
return nightCount;
}
... or if you want to avoid a while loop:
private int getNumberOfNights(DateTime start, DateTime end) {
int nightCount = Days.daysBetween(start, end).getDays();
DateTime leftOver = new DateTime(end.minusDays(nightCount));
if (leftOver.withTimeAtStartOfDay().isAfter(start)) {
nightCount++;
}
return nightCount;
}
With Java 7
public long countDays(Date dtStart, Date dtEnd) {
long startDay = TimeUnit.DAYS.convert(dtStart.getTime(), TimeUnit.MILLISECONDS)
long endDay = TimeUnit.DAYS.convert(dtEnd.getTime(), TimeUnit.MILLISECONDS)
return endDay - startDay
}