-2

I know there's a lot of questions about this but I couldn't find one that match with my case. I have to know if a date is exactly x months after another.

With ChonoUnit it's just not possible because 2020/05/25 and 2020/07/27or 2020/07/25 will return the same number of month and I can't handle the difference with the days. I have the same type of response with JodaTime

I tried with Perdiod and it's not relevant either.

LocalDate localDate = LocalDate.of(2020,1,30);
LocalDate toTest = localDate.plusMonths(1L); // returns 2020/02/29
Period.between(localDate, toTest);

returns months 0, days 30

I read that the endDate is exclusive, so I tried adding a day

LocalDate localDate = LocalDate.of(2020,1,30);
LocalDate toTest = localDate.plusMonths(1L); // returns 2020/02/29
Period.between(localDate, toTest.plusDays(1L));

returns months 1, days 1

So my question is : Is there a method to get this information that is compatible with the way LocalDate handles the months ?

Edit

Ok, I was not precise enough in my request. I know a month is not an absolute value, and my conception of a month doesn't matter.

In my case I have a LocalDate input that I can't contraint. I have to generate outputs every X months minus Y number of days.

Knowing that I test in a schedule if today is exactly X months after my input minus Y days (to be precise, I test if the number of month between the two dates modulo X equals 0). But if my input is the 31st of the month, Period will never return me 1 months, 0 days. If it's the 30st and my output should trigger in february it will never be neither.

Given that if on the short months the output occurs one day before the inexistant logic date it's not a problem.

The exemple I gave with LocalDate is just extracted from my tests but it's the way I thank I could do the thing, thus without doing myself a complicated algorithm with many conditions.

jona303
  • 1,358
  • 1
  • 9
  • 27
  • 2
    Could you clarify what your expected result is here and what you consider to be exactly one month? Is it for instance exactly one month between the 25th of June and the 25th of July or is that more than a month? – Joakim Danielson Dec 30 '20 at 11:44
  • Check this solution [Java 8 - Date Calculation](https://stackoverflow.com/questions/48950145/java-8-calculate-months-between-two-dates/48951547). I try your example with the first/second option of the accepted solution and show me 1 month – Andres Sacco Dec 30 '20 at 11:59
  • If you (and/or your users) like the way `LocalDate.plusMonth()` does, why not just use that in your test? `if (ld1.plusMonths(numberOfMonths).equals(ld2))` …? – Ole V.V. Dec 30 '20 at 13:14
  • @AndresSacco yes, but it's hard to know if it's x month plus 5 days, or x month plus 0 days. – jona303 Dec 30 '20 at 15:04
  • @OleV.V. because it's recurrent. Every X month I should do the thing. I can't make it in a loop. – jona303 Dec 30 '20 at 15:05

4 Answers4

0

I think you in your description you tried with January and February. That might be causing problem. So you have to manually handle this case. Otherwise your code is working.

0

A month is not exact time unit. Think about it: we can tell exactly how many seconds are in 1 minute, in 1 hour, 1 day and 1 week. But the number of seconds for different months would be different. So you need to define the logic what do you see as two dates that differ exactly one month? Once you define all the expected behaviors (including such cases as what is exactly one month from January 30th? Feb 28/29? or march 1st?) then you can see if there is anything out of the box that works for you or you need to implement your own logic

Michael Gantman
  • 7,315
  • 2
  • 19
  • 36
0

I have to know if a date is exactly x months after another.

That is an unclear request. One obvious interpretation would appear to be:

int monthA = a.getYear() * 12 + a.getMonthValue();
int monthB = b.getYear() * 12 + b.getMonthValue();
// Months.between can probably also be used instead of this math.
return a.getDayOfMonth() == b.getDayOfMonth() && (monthA - monthB) == x;

But that does mean it is -impossible- for a date to exist that is 'exactly 1 month after' March 30th: There is no feb 30th and there never will be.

Is that what you really wanted? Given that the length of a month depends on which month you ask, 'exactly 1 month later' is not a sensible question to ask. Hence: What do you actually mean?

  • Same day-of-month, X months later? (And realizing that there are many dates for which there cannot be such a date).
  • X days afterwards, where X is some formulaic approach based on which month we are in.
rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • That's the ambigous part of what is asked me. And the answer could be anything. This is why I give the exemple of `LocalDate.plusMonths()` because they took a decision (that we can discuss) and we know how it will behave. I'm searching about the same kind of things, but for difference between two date in months. I suppose I will have to do mine. – jona303 Dec 30 '20 at 15:10
0

I probably still haven’t got it. Allow me a shot in spite, elaborating on my idea from the comment: If you like the way LocalDate.plusMonths() does, then use that method.

    int monthsBetween = 3; // X
    int daysBefore = 11; // Y
    LocalDate originalDate = LocalDate.of(2020, Month.JANUARY, 30);
    
    int nextTimeCount = 1; // next time to generate output will be the 1st time
    LocalDate nextDate = originalDate.plusMonths(nextTimeCount * monthsBetween).minusDays(daysBefore);
    LocalDate today = LocalDate.now(ZoneId.systemDefault());
    while (! nextDate.isAfter(today)) {
        System.out.format("Generating output no. %d for %s%n", nextTimeCount, nextDate);
        
        nextTimeCount++;
        nextDate = originalDate.plusMonths(nextTimeCount * monthsBetween).minusDays(daysBefore);
    }

Output when I ran just now (December 30):

Generating output no. 1 for 2020-04-19
Generating output no. 2 for 2020-07-19
Generating output no. 3 for 2020-10-19

Assuming that your program will not be running uninterrupted for months you will need some way to persist the data, of course. So my code will not work as it stands, but if the behaviour is otherwise as expected, you can probably use the same mthod calls that I am using.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • 1
    That's my plan B. I was just writing you a comment when I think I had the right idea. Instead of persisting years of planned outputs, I just have to persist the next output date (maintained on update or delete). When the next output occurs I process the date to find the new next output date and it's done. – jona303 Dec 31 '20 at 08:24