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...
Related
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.
I'm finding it difficult that what it sounds.
So, I have a max date and a min date and I need to find the median date between these two dates. I use Java 8 to find my max and min dates,
LocalDate gerbutsmin = YearMonth.now().plusMonths(2).atDay(1);
LocalDate gerbutsmax = YearMonth.now().plusMonths(15).atDay(1);
How would I go ahead after this? Maybe I need to switch back to Calander?
Try using DAYS.between():
LocalDate gerbutsmin = YearMonth.now().plusMonths(2).atDay(1);
LocalDate gerbutsmax = YearMonth.now().plusMonths(15).atDay(1);
long numDays = ChronoUnit.DAYS.between(gerbutsmin, gerbutsmax);
LocalDate median = gerbutsmin.plusDays(numDays / 2L); // plusDays takes a long
System.out.println(median);
2019-03-17
(output as of today, which is 2019-07-26)
Demo
There is a boundary condition should the difference between your min and max dates be an odd number. In this case, there is no formal median day, but rather the median would fall in between two days.
Note:
If you're wondering what happens exactly in the edge case, if the low date were today (2018-07-26) and the high date three days away (2018-07-29), then the median would be reported as 2018-07-27.
LocalDate gerbutsmin = YearMonth.now().plusMonths(2).atDay(1);
LocalDate gerbutsmax = YearMonth.now().plusMonths(15).atDay(1);
LocalDate median = gerbutsmin.plusDays(ChronoUnit.DAYS.between(gerbutsmin, gerbutsmax) / 2);
"Middle of two dates" is not unambiguously defined - you must decide how to handle dates an odd number of days apart (e.g. what is the middle date between 1st and 4th of a month, or between 1st and 2nd), and what to do with the time portion of the date object.
The concrete problem with your approach is that dates are not numbers, so you cannot add them and divide them by two. To do that, use the getTime() method to obtain the number of seconds since the epoch, and operate on that:
var middate = new Date((startdate.getTime() + enddate.getTime()) / 2.0);
This will give you the middle between two dates, treating them as points in time.
Click here
LocalDateTime startime = LocalDateTime.now();
LocalDateTime endtime = startime.plusDays(4);
long diff = endtime.until(startime, ChronoUnit.MINUTES);
LocalDateTime middleTime = startime.plusMinutes(diff / 2);
I am trying to obtaining remaining years, months, and days between two dates:
So I have used Joda Time to do so:
DateTime endDate = new DateTime(2018,12,25,0,0);
DateTime startDate = new DateTime();
Period period = new Period(startDate,endDate,PeriodType.yearMonthDay());
PeriodFormatter formatter = new PeriodFormatterBuilder().appendYears().appendSuffix(" Year ").
appendMonths().appendSuffix(" Month ").appendDays().appendSuffix(" Day ").appendHours()..toFormatter();
String time = formatter.print(period);
This gives me string time: 2 Year 4 Month 22 Day
However, I want integer values of each number of remaining years, months, days.
So, Instead of "2 Year 4 Month 22 Day", I want to set my variables:
int year = 2
int month = 4
int day = 22
Is there any way to obtain these values separately instead of obtaining one string? Thank you so much! :)
i had the same requirement once ,here is the code snippet
LocalDate d=LocalDate.of(yy,mm,dd);
LocalDate d2=LocalDate.of(yy, mm, dd);
Period p=Period.between(d, d2);
long day,month,year;
day=p.getDays();
month=p.getMonths();
year=p.getYears();
System.out.println(day+" : "+month+" : "+year);
Invoke the methods provided by the DateTime class and just subtract them. An example for years is below:
int year = (int) dateTime#year#getField() - (int) dateTime2#year#getField()
UNTESTED code!! I'll be looking into it later but the general idea is the same, get the field information then just subtract it to get a value
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.
I am calculating the difference between two sql dates, TripStartDate and TripEndDate.
If TripStartDate= 2011-03-04 09:35:00 and TripEndDate = 2011-03-04 10:35:00 then I should get the number of day is 1 (because trip happened on that day).
Like this:
If TripStartDate = 2011-03-04 09:35:00 and TripEndDate = 2011-03-05 09:35:00 then method should return 2 days (because trip happened on both days).
If TripStartDate = 2011-03-04 09:35:00 and TripEndDate = 2011-04-04 09:35:00 then method should return 32 days. (because 28 days in march and 4 days in April).
Calculation should be based on only dates and month of year (not taking time in consideration). Please help me . Thanks in advance...
In Java I guess you would drop the time and calculate the day difference
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal1.set(2011, 03, 04);
cal2.set(2011, 04, 04);
long milis1 = cal1.getTimeInMillis();
long milis2 = cal2.getTimeInMillis();
long diff = milis2 - milis1;
long days = diff / (24 * 60 * 60 * 1000);
EDIT Quite surprisingly for me, that ^ code really doesn't work always... apparently there are some 'leap seconds' that mess up the maths. There are quite enough links already proposed to you in comments. I would go with joda time library.
FYI, in Groovy this would be something along the lines of:
fourthMarch = Date.parse( 'yyyy-MM-dd', '2011-03-04' )
fifthMarch = Date.parse( 'yyyy-MM-dd', '2011-03-05' )
fourthApril = Date.parse( 'yyyy-MM-dd', '2011-04-04' )
assert 2 == fifthMarch - fourthMarch + 1
assert 32 == fourthApril - fourthMarch + 1
We need to add 1 as the dates are inclusive
Here's the usual way to do this, in Java 8.
LocalDate start = LocalDate.of(2011, 3, 4); // Or whatever - this is Y, M, D
LocalDate end = LocalDate.of(2011, 4, 4);
return ChronoUnit.DAYS.between(start, end) + 1;
// The +1 is for the inclusive reckoning