Display date and time comparing present date with past date in java - java

I am using JodaTime to compare the dates
DateTime past = new DateTime(quitYear, quitMonth, quitDay, quitTimeHour, quitTimeMin);
DateTime today = new DateTime();
int days = Days.daysBetween(new DateTime(past), new DateTime(today)).getDays();
This gives me the number of days difference. How do i display the time difference aswell. For example it shows that the difference is 5:23(5 hours and 23 minutes).

I don't think you can get that from one query, you must do more operations.
Probably you can do this
Duration duration = new Interval(past, today).toDuration();
int days = duration.toStandardDays().getDays();
int hours = duration.toStandardHours().getHours() - days * 24;
int minutes = duration.toStandardMinutes().getMinutes() - days * 24 * 60 - hours * 60;

Related

What is a best way to find the number of days and months between two java.time.Instant objects?

NOTE: search Google before marking this question as duplicate. I did search and browse this question and all answers that I found were either for LocalDate, Joda or legacy Java Date.
It took me quite some time to investigate this so I've decided to share this as an answer.
I'd like a way to calculate the (approximate) number of months and days between two Java Instants (objects of java.time.Instant)?
First, what you are asking is not well-defined. For example between the instants 2020-03-01T06:00:00Z and 2020-03-31T05:00:00Z could be:
29 days 23 hours in Australia/Melbourne time zone;
30 days in Europe/Paris time zone;
1 month 1 day in America/Los_Angeles time zone.
Accurate result in a given time zone
ZoneId zone = ZoneId.of("America/Los_Angeles");
Instant start = Instant.parse("2020-03-01T06:00:00Z");
Instant end = Instant.parse("2020-03-31T05:00:00Z");
ZonedDateTime startZdt = start.atZone(zone);
LocalDate startDate = startZdt.toLocalDate();
ZonedDateTime endZdt = end.atZone(zone);
LocalDate endDate = endZdt.toLocalDate();
Period p = Period.between(startDate, endDate);
if (startZdt.plus(p).isAfter(endZdt)) {
// The time of day on the end date is earlier, so don’t count a full date
endDate = endDate.minusDays(1);
p = Period.between(startDate, endDate);
}
System.out.println(p);
Output:
P1M1D
Read as a period of 1 month 1 day.
Approximate result independent of time zone
Prefer to leave as much of the calculation to java.time as possible. This includes the estimate of the length of a month.
Duration diff = Duration.between(start, end);
Duration durationOfAMonth = ChronoUnit.MONTHS.getDuration();
long months = diff.dividedBy(durationOfAMonth);
diff = diff.minus(durationOfAMonth.multipliedBy(months));
long days = diff.toDays();
System.out.println("" + months + " months " + days + " days");
0 months 29 days
I've opted out to approximate solution (it assumes all months have 30.44 days). I've opted out to use something like this:
Duration duration = Duration.between(instant1, instant2).abs(); /* if want negative values remove .abs() */
long hours = duration.toHours();
double daysAndMonthsInDays = hours / 24.0;
int months = daysAndMonthsInDays / 30.44; //average number of days per month
int days = daysAndMonthsInDays - months * 30.44;
Please post another answer if there is a better solution using Duration class or something else. I've decided not to convert Instant to LocalDate and to perform the conversion on that level. That would not use an approximation of 30.44 days in a month, but rather the actual number.

Java Difference between current date and past date in Years, Months, Days, Hours, Minutes, Seconds [duplicate]

This question already has answers here:
integer giving negative values in java in multiplication using positive numbers [duplicate]
(4 answers)
Closed 3 years ago.
I know this has been asked on here many times previously, but I'm haven't been able to find anything specific to my case. I'm trying to find the difference between the current datetime and a previous datetime, each with the format yyyy-MM-dd HH:mm:ss.s. Based on the answer given here, I've come up with the following code:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.s");
String earliestRunTime = "2017-12-16 01:30:08.0";
Date currentDate = new Date();
log.info("Current Date: {}", format.format(currentDate));
try {
Date earliestDate = format.parse(earliestRunTime);
long diff = currentDate.getTime() - earliestDate.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) % 30;
long diffMonths = diff / (30 * 24 * 60 * 60 * 1000) % 12;
long diffYears = diff / (12 * 30 * 24 * 60 * 60 * 1000);
return String.format("%s years, %s months, %s days, %s hours, %s minutes, %s seconds",
diffYears, diffMonths, diffDays, diffHours, diffMinutes, diffSeconds);
}
catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
When I run the code, the JSON returns the following result:
lifetime: "41 years, -1 months, 14 days, 9 hours, 42 minutes, 37 seconds"
I have two questions here:
Where am I going wrong in my calculations 41 years and a negative number?
Is there a better way for me to do this? My current setup does not consider leap years or a 365 day year, and I need to take these into account.
Where am I going wrong in my calculations 41 years and a negative number?
Because the denominator will overflow. You need to use Long:
long diffMonths = diff / (30 * 24 * 60 * 60 * 1000L) % 12; //Notice the L at the end
long diffYears = diff / (12 * 30 * 24 * 60 * 60 * 1000L); //Notice the L at the end
Also note that 12 * 30 is a really bad approximation of the number of days in a year.
Is there a better way for me to do this?
Yes. Use Duration api from Java 8. https://www.mkyong.com/java8/java-8-period-and-duration-examples/
It's hard to give precise answer, because the question is a bit vague. For example - If one of the year was a leap year and you were comparing dates 2020/03/28 and 2021/03/28, what should be the result? 1 year or 1 years, 1 days? (2020 is a leap year so after 03/28, there's also 03/29)
Where am I going wrong in my calculations 41 years and a negative number?
Apart from using the notoriously troublesome and long outdated SimpleDateFormat class and the just as outdated Date there are the following bugs in your code:
You are parsing 08.0 as 8 seconds 0 seconds. On my JDK-11 SimpleDateFormat opts for the 0 seconds and discards the 8 seconds that I think are correct. SimpleDateFormat cannot parse one decimal on the seconds (only exactly three decimals), so the solution to this bug is discarding SimpleDateFormat altogether.
As others have said you have an int overflow in your multiplications. For example, 30 * 24 * 60 * 60 * 1000 should give 2 592 000 000, but since an int cannot hold this number, you get -1 702 967 296 instead. Since this is a negative number, the following division gives you a negative number of months.
As Solomon Slow pointed out in a comment, a month may be 28, 29, 30 or 31 days. When setting all months to 30 days you risk incorrect numbers of days and months and in the end also years. When I ran your code today, the correct answer would have been 1 year, 4 months, 13 days, but I got 19 days instead, 6 days too much.
You are not taking summer time (DST) and other time anomalies into account. These may cause a day to be for example 23 or 25 hours, giving an error.
Or to sum up: Your error was that you tried to do the calculation “by hand”. Date and time math is too complex and error-prone to do this. You should always leave it to well-proven library classes instead.
Is there a better way for me to do this? My current setup does not consider leap years or a 365 day year, and I need to take these into
account.
Yes, there is a much better way. The best way may be to use the PeriodDuration class from the ThreeTen Extra project, see the link below. I am not going to install that library in my computer right now, so I will just show the good and modern solution using built-in classes:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.S");
LocalDateTime currentDateTime = LocalDateTime.now(ZoneId.of("Australia/Sydney"));
String earliestRunTime = "2017-12-16 01:30:08.0";
LocalDateTime earliestDateTime = LocalDateTime.parse(earliestRunTime, dtf);
// We want to find a period (years, months, days) and a duration (hours, minutes, seconds).
// To do that we cut at the greatest possible whole number of days
// and then measure the period before the cut and the duration after it.
LocalDateTime cut = earliestDateTime.plusDays(
ChronoUnit.DAYS.between(earliestDateTime, currentDateTime));
Period p = Period.between(earliestDateTime.toLocalDate(), cut.toLocalDate());
Duration d = Duration.between(cut, currentDateTime);
String result = String.format("%s years, %s months, %s days, %s hours, %s minutes, %s seconds",
p.getYears(), p.getMonths(), p.getDays(),
d.toHours(), d.toMinutesPart(), d.toSecondsPart());
System.out.println(result);
When I ran the code just now I got:
1 years, 4 months, 13 days, 19 hours, 26 minutes, 7 seconds
In java.time, the modern Java date and time API, a Period is an amount of years, months and days, and a Duration is an amount of hours, minutes, seconds and fraction of second (down to nanoseconds). Since you wanted both, I am using both classes.
The toXxxPart methods of Duration I am using were introduced in Java 9. If you are using Java 8 (or the ThreeTen Backport) printing the minutes and seconds is a little bit more complicated. Search for java format duration or similar to learn how.
I am still not taking summer time into account. To do that we would need to know the time zone of the earliest run time string and then use ZonedDateTime instead of LocalDateTime. The code would otherwise be very similar.
Links
ThreeTen Extra
Documentation of PeriodDuration
Oracle Tutorial: Date Time explaining how to use java.time
Using the same approach you did, you need to explicitly identify the denominator as long values. Currently, it assumes them to be integers, which causes a numeric overflow - meaning the value computed is too large for a integer. This would explain why you get negative/arbitrary values. Fix is simple:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.s");
String earliestRunTime = "2017-12-16 01:30:08.0";
Date currentDate = new Date();
log.info("Current Date: {}" + format.format(currentDate));
try {
Date earliestDate = format.parse(earliestRunTime);
long diff = currentDate.getTime() - earliestDate.getTime();
long diffSeconds = diff / 1000L % 60L;
long diffMinutes = diff / (60L * 1000L) % 60L;
long diffHours = diff / (60L * 60L * 1000L) % 24L;
long diffDays = diff / (24L * 60L * 60L * 1000L) % 30L;
long diffMonths = diff / (30L * 24L * 60L * 60L * 1000L) % 12L;
long diffYears = diff / (12L * 30L * 24L * 60L * 60L * 1000L);
return String.format("%s years, %s months, %s days, %s hours, %s minutes, %s seconds",
diffYears, diffMonths, diffDays, diffHours, diffMinutes, diffSeconds);
}
catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}

Different time interval util.date and DAYS.between(Localtime)

Something doesn't seem right and i just dont know how I can fix it.
I want to know the difference in days between 2 dates. Now I implemented a function, which calculates the differences from milliseconds to days for util.date objects
public long calculateNumberOfDays(Date from, Date to) {
return (to.getTime() - from.getTime()) / (1000*60*60*24);
}
My jUnit test told me, there was an error with this function, so I rewrote it using LocalDate and the ChronoUnit.DAYS.between function. It worked like a charm.
Wanting to know what the differences between those two functions were, I wrote this little test:
for(int numberDays = 1; numberDays<10; numberDays++){
LocalDate fromLD = LocalDate.now();
LocalDate toLD = fromLD.plusDays(numberDays);
Date fromD = Date.valueOf(fromLD);
Date toD = Date.valueOf(toLD);
long diffMS = toD.getTime() - fromD.getTime();
double diffDays = diffMS/(1000*60*60*24);
long numDaysDate = DAYS.between(fromLD, toLD);
System.out.println(numberDays+" = "+diffDays+"/"+numDaysDate);
}
It resulted in the following output:
1 = 1.0/1
2 = 2.0/2
3 = 3.0/3
4 = 4.0/4
5 = 4.0/5
6 = 5.0/6
7 = 6.0/7
8 = 7.0/8
9 = 8.0/9
Can someone explain to me, how this is possible? (1-4 it works, 5-9 util.date has lost a day)
Dates are hard. A java Date is a date and time, so when you set it to an actual date, it means midnight on that date.
Daylight savings time kicks in any day now (at least over here), so midnight on Monday will be 23 hours after midnight on Sunday.
Dividing integers rounds down, so 4 days and 23 hours is 4 days
Casting the result of an integer division to a double is too late; you need to cast either or both of the inputs:
double diffDays = diffMS/(1000*60*60*24);
4.0
double diffDays = diffMS/(1000.0*60*60*24);
4.958333...

Subtract four weeks from current time stamp [duplicate]

This question already has answers here:
How to subtract X days from a date using Java calendar?
(11 answers)
Closed 9 years ago.
long epoch = System.currentTimeMillis() / 1000;
String dateStr = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'.0Z'").format(new java.util.Date(epoch * 1000));
System.out.println(dateStr);
Can anyone please tell me how to get the time stamp of 4 weeks from the current one? I'm working on payroll testing.
Subtract the number of milliseconds in 4 weeks from the current time.
long now = System.currentTimeMillis();
long fourWeeksAgo = now - 1000 * 60 * 60 * 24 * 28;
java.util.Calendar provides a means of manipulating dates so that code is readable:
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.WEEK_OF_YEAR, -4);
long fourWeeksAgo = calendar.getTime().getTime();
java.util.Calendar c = java.util.Calendar.getInstance();
c.add(java.util.Calendar.WEEK_OF_MONTH, -4);

How to write a method that returns number (int) of days from provided day to the todays date?

Please help me to write a method that returns number (int) of days from a provided day to the todays date.
So let's say, I am providing into a method an int 110515 (for May 15, 2011). It should return 9 (inclusive or exclusive is not important to me).
If you can use Joda, this is super simple:
Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();
Of course you could combine these.
int days = Days.daysBetween(startDate, endDate).getDays();
Joda objects can go back and forth between the JDK's date class pretty easily.
For the first part, make a DateFormatter then parse the string based on it, like this:
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyyMMdd");
DateTime dt = fmt.parseDateTime(strInputDateTime);
(After turning the int into a string of course.)
Should dates in the future include the current day? Meaning if today is May 24th 2011, should 110529 result in 4 or 5?
public static long numberOfDays(final long date) throws ParseException {
final Calendar compare = Calendar.getInstance();
compare.setTime(new SimpleDateFormat("yyMMdd").parse(String.valueOf(date)));
final int dstOffset = compare.get(Calendar.DST_OFFSET);
final long currentTimeMillis = System.currentTimeMillis();
final long compareTimeInMillis = compare.getTimeInMillis();
long difference = 0;
if (currentTimeMillis >= compareTimeInMillis) {
difference = currentTimeMillis - compareTimeInMillis - dstOffset;
} else {
difference = compareTimeInMillis - currentTimeMillis + dstOffset;
}
return difference / (24 * 60 * 60 * 1000);
}
Since this seems like a homework question I will help you out. You will want to use Calendar.getTimeInMillis. Then you will want to create a constant that is NUMBER_OF_MILLIS_IN_DAY . From there you subtract the initialDate from the currentDate (both time in millis) and divide by the constant.

Categories