java chrono unit difference between year - java

i have below code to get difference between two years..
long yearsBetween = ChronoUnit.YEARS.between(
customDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
LocalDate.now());
my date value is as below
customDate = 2022-03-07
LocalDate.now() = 2021-10-07
but when i execute ChronoUnit.YEARS.between, it returns "0", but i am expecting "1" as return value. i want to compare only years for the given date and get the difference, excluding days..

If you want to ignore the month and day components of the LocalDate, you can just get the year from each LocalDate and then compare them, like so:
// Let's say we have two LocalDates, date1 and date2:
LocalDate date1 = LocalDate.of(2021, 10, 6);
LocalDate date2 = LocalDate.of(2022, 3, 7);
// We can get the year for each object and then subtract the two years:
long yearsBetween = date2.getYear() - date1.getYear();
// This will print 1 because 2022 is 1 year ahead of 2021:
System.out.println(yearsBetween);
As a side note, there is no need for yearsBetween to be a long data type (64-bit integer). The getYear() method returns an int (32-bit integer), and I doubt you'll ever have to deal with years that far in the future. We can just use:
int yearsBetween = date2.getYear() - date1.getYear();
You can then just plug in your dates where date1 and date2 are like so:
int yearsBetween = customDate.toInstant().atZone(ZoneId.systemDefault())
.toLocalDate().getYear()
- LocalDate.now().getYear();

Related

Joda Time - difference in "complete" months between two dates

How to calculate the number of "full" months between two dates with joda time, dropping incomplete months?
For example, I have 2 dates
LocalDate from = new LocalDate (2018, 9, 10);
LocalDate to = new LocalDate (2018, 11, 15);
Between these dates there is one "full" month - October from 1 to 31.
So I want to get is the number "1" by dropping the "incomplete" months - September and November
I need something like this
System.out.println(Months.monthsBetween(from, to).getMonths()); // returns 2
System.out.println(Months.**completed**MonthsBetween(from, to).getMonths()); // returns 1
UPD 1.
I could achieve what I want as follows:
LocalDate from = new LocalDate (2018, 9, 10);
LocalDate to = new LocalDate (2018, 11, 15);
if (to.getDayOfMonth() != 1)
from = from.plusMonths(1).withDayOfMonth(1);
if (to.getDayOfMonth() != 1)
to = to.withDayOfMonth(1);
System.out.println(Months.monthsBetween(from, to).getMonths());
but maybe there is an out of the box method?
Wouldn't this means that you simply want to remove one month from each interval and do a difference between them?
LocalDate fromMinusOne = from.minus(Months.ONE);
LocalDate toMinusOne = to.minus(Months.ONE);
System.out.println(Months.monthsBetween(fromMinusOne, toMinusOne).getMonths());
Joda Time provides methods to extract days, months and years between two dates. Create two instances of you date.
DateTime startDate = DateTime.parse("1970-01-01", DateTimeFormat.forPattern("yyyy-MM-dd"))
DateTime endDate = DateTime.parse("2015-02-25", DateTimeFormat.forPattern("yyyy-MM-dd"))
You can create your date instances in LocalDate as well instead of DateTime.
Now, complete months between above two dates can be found easily with,
int months = Months.monthsBetween(startDate.withDayOfMonth(1), endDate.withDayOfMonth(1)).getMonths()
For days,
int days = Days.daysBetween(startDate, endDate).getDays()
Difference between two dates in months
For years,
int years = Years.yearsBetween(startDate, endDate).getYears();

Java 8 calculate months between two dates

NOTE THIS IS NOT A DUPLICATE OF EITHER OF THE FOLLOWING
Calculating the difference between two Java date instances
calculate months between two dates in java [duplicate]
I have two dates:
Start date: "2016-08-31"
End date: "2016-11-30"
Its 91 days duration between the above two dates, I expected my code to return 3 months duration, but the below methods only returned 2 months. Does anyone have a better suggestion? Or do you guys think this is a bug in Java 8? 91 days the duration only return 2 months.
Thank you very much for the help.
Method 1:
Period diff = Period.between(LocalDate.parse("2016-08-31"),
LocalDate.parse("2016-11-30"));
Method 2:
long daysBetween = ChronoUnit.MONTHS.between(LocalDate.parse("2016-08-31"),
LocalDate.parse("2016-11-30"));
Method 3:
I tried to use Joda library instead of Java 8 APIs, it works. it loos will return 3, It looks like Java duration months calculation also used days value. But in my case, i cannot use the Joda at my project. So still looking for other solutions.
LocalDate dateBefore= LocalDate.parse("2016-08-31");
LocalDate dateAfter = LocalDate.parse("2016-11-30");
int months = Months.monthsBetween(dateBefore, dateAfter).getMonths();
System.out.println(months);
Since you don't care about the days in your case. You only want the number of month between two dates, use the documentation of the period to adapt the dates, it used the days as explain by Jacob. Simply set the days of both instance to the same value (the first day of the month)
Period diff = Period.between(
LocalDate.parse("2016-08-31").withDayOfMonth(1),
LocalDate.parse("2016-11-30").withDayOfMonth(1));
System.out.println(diff); //P3M
Same with the other solution :
long monthsBetween = ChronoUnit.MONTHS.between(
LocalDate.parse("2016-08-31").withDayOfMonth(1),
LocalDate.parse("2016-11-30").withDayOfMonth(1));
System.out.println(monthsBetween); //3
Edit from #Olivier Grégoire comment:
Instead of using a LocalDate and set the day to the first of the month, we can use YearMonth that doesn't use the unit of days.
long monthsBetween = ChronoUnit.MONTHS.between(
YearMonth.from(LocalDate.parse("2016-08-31")),
YearMonth.from(LocalDate.parse("2016-11-30"))
)
System.out.println(monthsBetween); //3
Since Java8:
ChronoUnit.MONTHS.between(startDate, endDate);
//Backward compatible with older Java
public static int monthsBetween(Date d1, Date d2){
if(d2==null || d1==null){
return -1;//Error
}
Calendar m_calendar=Calendar.getInstance();
m_calendar.setTime(d1);
int nMonth1=12*m_calendar.get(Calendar.YEAR)+m_calendar.get(Calendar.MONTH);
m_calendar.setTime(d2);
int nMonth2=12*m_calendar.get(Calendar.YEAR)+m_calendar.get(Calendar.MONTH);
return java.lang.Math.abs(nMonth2-nMonth1);
}
The documentation of Period#between states the following:
The start date is included, but the end date is not.
Furthermore:
A month is considered if the end day-of-month is greater than or equal to the start day-of-month.
Your end day-of-month 30 is not greater than or equal to your start day-of-month 31, so a third month is not considered.
Note the parameter names:
public static Period between​(LocalDate startDateInclusive, LocalDate endDateExclusive)
To return 3 months, you can increment the endDateExclusive by a single day.
In case you want stick to java.time.Period API
As per java.time.Period documentation
Period between(LocalDate startDateInclusive, LocalDate endDateExclusive)
where
#param startDateInclusive the start date, inclusive, not null
#param endDateExclusive the end date, exclusive, not null
So it is better to adjust your implementation to make your end date inclusive and get your desired result
Period diff = Period.between(LocalDate.parse("2016-08-31"),
LocalDate.parse("2016-11-30").plusDays(1));
System.out.println("Months : " + diff.getMonths());
//Output -> Months : 3
You have to be careful, never use LocalDateTime to calculate months between two dates the result is weird and incorrect, always use LocalDate !
here's is some code to prove the above:
package stack.time;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
public class TestMonthsDateTime {
public static void main(String[] args) {
/**------------------Date Time----------------------------*/
LocalDateTime t1 = LocalDateTime.now();
LocalDateTime t2 = LocalDateTime.now().minusMonths(3);
long dateTimeDiff = ChronoUnit.MONTHS.between(t2, t1);
System.out.println("diff dateTime : " + dateTimeDiff); // diff dateTime : 2
/**-------------------------Date----------------------------*/
LocalDate t3 = LocalDate.now();
LocalDate t4 = LocalDate.now().minusMonths(3);
long dateDiff = ChronoUnit.MONTHS.between(t4, t3);
System.out.println("diff date : " + dateDiff); // diff date : 3
}
}
My 2%
This example checks to see if the second date is the end of that month. If it is the end of that month and if the first date of month is greater than the second month date it will know it will need to add 1
LocalDate date1 = LocalDate.parse("2016-08-31");
LocalDate date2 = LocalDate.parse("2016-11-30");
long monthsBetween = ChronoUnit.MONTHS.between(
date1,
date2);
if (date1.isBefore(date2)
&& date2.getDayOfMonth() == date2.lengthOfMonth()
&& date1.getDayOfMonth() > date2.getDayOfMonth()) {
monthsBetween += 1;
}
After the short investigation, still not totally fix my question, But I used a dirty solution to avoid return the incorrect duration. At least, we can get the reasonable duration months.
private static long durationMonths(LocalDate dateBefore, LocalDate dateAfter) {
System.out.println(dateBefore+" "+dateAfter);
if (dateBefore.getDayOfMonth() > 28) {
dateBefore = dateBefore.minusDays(5);
} else if (dateAfter.getDayOfMonth() > 28) {
dateAfter = dateAfter.minusDays(5);
}
return ChronoUnit.MONTHS.between(dateBefore, dateAfter);
}
The Java API response is mathematically accurate according to the calendar. But you need a similar mechanism, such as rounding decimals, to get the number of months between dates that matches the human perception of the approximate number of months between two dates.
Period period = Period.between(LocalDate.parse("2016-08-31"), LocalDate.parse("2016-11-30"));
long months = period.toTotalMonths();
if (period.getDays() >= 15) {
months++;
}

Joda Time - difference in months between two dates [duplicate]

This question already has answers here:
Number of days between two dates in Joda-Time
(9 answers)
Closed 7 years ago.
I need to get the difference in months between two dates, I'm using Joda Time, the problem is this:
DateTime date1 = new DateTime().withDate(2015, 2, 1);
DateTime date2 = new DateTime().withDate(2015, 1, 1);
Months m = Months.monthsBetween(date1, date2);
int monthDif = m.getMonths();//this return 0
it returns 0 because there is no month in the middle of the two dates, I need to return the difference in months not a few months in between, and add 1 would be problematic when the dates are the same.
Changing the first date to 2015-02-02, Joda correctly returns 1 month:
DateTime date1 = new DateTime().withDate(2015, 2, 2);
DateTime date2 = new DateTime().withDate(2015, 1, 1);
System.out.println(Months.monthsBetween(date2, date1).getMonths());
// Returns 1.
So my guess is that because you didn't provide a time portion, Joda cannot be precise about exactly which point in time of 2015-01-01 date2 refers to. You might have as well referred to 23:59:59, in which case a full month wouldn't have elapsed yet, technically.
If you provide a zero time portion explicitly, it works as you initially expected:
DateTime date1 = new DateTime().withDate(2015, 2, 1).withTime(0, 0, 0, 0);
DateTime date2 = new DateTime().withDate(2015, 1, 1).withTime(0, 0, 0, 0);
System.out.println(Months.monthsBetween(date2, date1).getMonths());
// Returns 1.
Therefore, I recommend you specify a 00:00:00 time portion in each date explicitly.
While other answers are correct they still mask the real problem.
it returns 0 because there is no month in the middle of the two dates
No. It returns 0 because there is time part of DateTime object. You creating two istances of DateTime filled with current moment in time (with hours, minutes, seconds and milliseconds) and then modify just date part. There is no reasons to do it if you want to compare just two dates. use LocalDate instead.
LocalDate date1 = new LocalDate(2015, 2, 1);
LocalDate date2 = new LocalDate(2015, 1, 1);
Months m = Months.monthsBetween(date1, date2);
int monthDif = Math.abs(m.getMonths());//this return 1
Also need to pay attention to the fact that despite the fact that Months docs say nothing about it, Month can contain negative value if first date is after second date. So we need to use Math.abs to really count the number of months between two dates.
The docs say:
Creates a Months representing the number of whole months between the two specified partial datetimes.
But it isn't true. It really calculates the difference in months. Not the number of months.
The way this is calculated depends on the business logic that is to be used. Each month varies in length. One option would be to, in the monthsBetween() function, get the start of the month for both date1 and date2, and compare that.
Something like:
DateTime firstOfMonthDate1 = new DateTime(date1.getYear(), date1.getMonthOfYear(), 1, 0, 0);
DateTime firstOfMonthDate2 = new DateTime(date2.getYear(), date2.getMonthOfYear(), 1, 0, 0);
Months m = Months.monthsBetween(firstOfMonthDate1, firstOfMonthDate2)

Im trying to calculate the number off days between 2 date objects [duplicate]

This question already has answers here:
Calculating the difference between two Java date instances
(45 answers)
Closed 8 years ago.
public static int countWeeks() {
// setting dates
Calendar calStart = GregorianCalendar.getInstance();
calStart.set(2014, 8, 30);
Date dateStart = calStart.getTime();
Date dateEnd = new Date();
// count days and weeks
int diffInDays = Days.daysBetween(new DateTime(dateStart), new DateTime(dateEnd)).getDays(); // int weekNumber = (int) diffInDays / 7;
return weekNumber;
}
I'm trying to calculate the number of days and weeks between today and last week but I always get -3 as weekNumber. I have no idea what i'm doing wrong.
Thanks in advance.
First, I will assume that
int weekNumber = (int) diffInDays / 7;
is not commented since otherwise you would get a compilation error.
Now, as explained in my comment, by doing
calStart.set(2014, 8, 30);
You are setting the date at the end of setember, not of august. So, it is 3 weeks ahead of now, so you get a -3. Use the Calendar constants.
calStart.set(2014, Calendar.AUGUST, 30);
You set the startdate to Sep. 30th because te month is zero bases!
See the documentation from java.util.Calendar:
public final void set(int year,
int month,
int date) Sets the values for the calendar fields YEAR, MONTH, and DAY_OF_MONTH. Previous values of other calendar fields are
retained. If this is not desired, call clear() first. Parameters: year
- the value used to set the YEAR calendar field. month - the value used to set the MONTH calendar field. Month value is 0-based. e.g., 0
for January. date - the value used to set the DAY_OF_MONTH calendar
field. See Also:
You are getting -3 as the weeknumber since you have commented that out so it showing some random value. Also note that 8 shows the September month not Aug since months are 0 based.
So if you are aiming at August month then you may try this:
calStart.set(2014, 7, 30);
^^-- This represents August month
If you are on Java 8 you can use the Java time API:
LocalDate start = LocalDate.of(2014, 8, 30);
LocalDate end = LocalDate.now();
long days = ChronoUnit.DAYS.between(start, end);
return (int) days / 7;

adding/removing days from date code fix needed

I have this code here:
public static String AddRemoveDays(String date, int days) throws ParseException
{
SimpleDateFormat k = new SimpleDateFormat("yyyyMMdd");
Date d = k.parse(date);
d = new Date(d.getTime() + days*86400000);
String time = k.format(d);
return time;
}
It take String formed "yyyyMMdd", and adds int days to it. It should work then the days is negative - then he would substract the days from the date. When it does it's math, it returns String formated "yyyyMMdd".
At least that is what it should do. It works for small numbers, but if I try to add (or remove), for example, a year (365 or -365), it returns wierd dates.
What's the problem?
Should I do it a completley another way?
d = new Date(d.getTime() + days*86400000);
If you multiply 86400000 by 365 integer cant hold it. Change 86400000 to Long
d = new Date(d.getTime() + days*86400000L);
and it will be fine.
Hard to say what's going on without specific dates.
If you're committed to doing this with the raw Java classes, you might want to look at using Calendar -e.g.
Calendar calendar = Calendar.getInstance();
calendar.setTime(d);
calendar.add(Calendar.DATE, days); // this supports negative values for days;
d = calendar.getTime();
That said, I would recommend steering clear of the java Date classes, and look to use jodaTime or jsr310 instead.
e.g. in jsr310, you could use a DateTimeFormatter and LocalDate:
DateTimeFormatter format = DateTimeFormatters.pattern("yyyyMMdd");
LocalDate orig = format.parse(dateString, LocalDate.rule());
LocalDate inc = orig.plusDays(days); // again, days can be negative;
return format.print(inc);

Categories

Resources