title: How to calculate monthly occurrence in java
body: <p>I need to be able manage dates in flexible way for calculating monthly events.</p>
  <p>If I use</p>
  <pre><code>    SimpleDateFormat sdf = new SimpleDateFormat(&quot;dd-M-yyyy hh:mm:ss&quot;);
  
      Calendar calendar = Calendar.getInstance();
      calendar.set(2017, Calendar.AUGUST, 31, 9, 30, 15);
      Calendar next = calendar;
      for (int i = 1; i++&lt;10;) {
          next = (Calendar) calendar.clone();
          next.add(Calendar.MONTH, i);
          System.out.println(sdf.format(next.getTime()));
      }
  </code></pre>
  <p>in result you can see</p>
  <blockquote>
  <p>31-10-2017 09:30:15</p>
  <p>30-11-2017 09:30:15</p>
  <p>31-12-2017 09:30:15</p>
  <p>31-1-2018 09:30:15</p>
  <p>28-2-2018 09:30:15</p>
  <p>31-3-2018 09:30:15</p>
  <p>30-4-2018 09:30:15</p>
  <p>31-5-2018 09:30:15</p>
  <p>30-6-2018 09:30:15</p>
  </blockquote>
  <p>It seems following <strong>month semantic</strong> if we add one moth to date we should get next month (it's correct), but following <strong>occurrence semantic</strong> it has an issue, because of acceptance is to get same date day but in next month (as you can see it is not same sometimes. There are <code>31</code>, <code>30</code>, <code>28</code>). If there is no same date, we should <code>null</code> for example.</p>
  <p>Does java provides ability calculate months following <strong>occurrence semantic strategy</strong> to handle my issue?</p>
  <h2>More explanation examples.</h2>
  <p><strong>I DO NOT NEED LAST MONTH DAY</strong> I need occurrences only from first explanation for 31th month day. I simplified question as it was possible.</p>
  <p>I can do workarounds with <code>calendar</code> but I expected more elegant solution.</p>
  <p>If you use <a href="https://github.com/ical4j/ical4j" rel="nofollow noreferrer">ical4j</a> to calculate occurrences, you'll get this result. And occurrences calculation should be fixed (it's a bug because of <a href="https://www.rfc-editor.org/rfc/rfc5545" rel="nofollow noreferrer">rfc5545</a>).</p>
  <pre><code>import net.fortuna.ical4j.model.*
  import net.fortuna.ical4j.model.component.VEvent
  
  void testCalculateRecurrenceSetOn31th() {
      VEvent event = new ContentBuilder().vevent {
          dtstart('20100831T061500Z', parameters: parameters() {
              value('DATETIME')})
          dtend('20100831T064500Z', parameters: parameters() {
              value('DATETIME')})
          rrule('FREQ=MONTHLY;UNTIL=20110101')
      }
  
      def dates = event.calculateRecurrenceSet(new Period('20100831T000000/20110131T000000'))
  
      def expected = new PeriodList(true)
      expected.add new Period('20100831T061500Z/PT30M')
      expected.add new Period('20101031T061500Z/PT30M')
      expected.add new Period('20101231T061500Z/PT30M')
  
      println dates
      assert dates == expected
  
      /*
      Assertion failed:
  
      assert dates == expected
      |     |  |
      |     |  [20100831T061500Z/PT30M, 20101031T061500Z/PT30M, 20101231T061500Z/PT30M]
      |     false
      [20100831T061500Z/PT30M, 20100930T061500Z/PT30M, 20101030T061500Z/PT30M, 20101130T061500Z/PT30M, 20101230T061500Z/PT30M]
      */
  }
  </code></pre>
  <p>but if I use same library with small change:</p>
  <blockquote>
  <pre><code>      rrule('FREQ=MONTHLY;UNTIL=20110101')
  </code></pre>
  <p>--&gt;</p>
  <pre><code>      rrule('FREQ=MONTHLY;UNTIL=20110101;BYMONTHDAY=31')
  </code></pre>
  </blockquote>
  <p>it is calculated than correctly. But I need same calculation for both cases because of <em>rfc5545</em>.</p>
  <p>The root issue in the <a href="https://github.com/ical4j/ical4j" rel="nofollow noreferrer">ical4j</a> is in <code>Recur.java</code>:</p>
  <pre><code>private void increment(final Calendar cal) {
      final int calInterval = (getInterval() &gt;= 1) ? getInterval() : 1;
      cal.add(calIncField, calInterval);
  }
  </code></pre>