2

I want to define a date range like this:

  • start from "1396/8/9"
  • end to "1396/9/2"

And get the days date between these two dates.

I searched through the Internet and I found a DateInterval function in Time4j.

Is it possible to use this method for defining optional date range in Persian calendar? If yes, how can I use this method for my purpose?

Sameer
  • 55
  • 7

1 Answers1

1

Using conversions

The class DateInterval is designed for ISO-8601 only that is for the proleptic gregorian calendar. So you would be responsible yourself for conversions between the gregorian type PlainDate and the target type PersianCalendar:

DateInterval interval =
  DateInterval.between(
    PersianCalendar.of(1396, 8, 9).transform(PlainDate.axis()),
    PersianCalendar.of(1396, 9, 2)).transform(PlainDate.axis());

And for the reverse conversion:

PersianCalendar start = interval.getStartAsCalendarDate().transform(PersianCalendar.axis());

Of course, you can also loop daily through your interval:

interval
  .streamDaily()
  .map(d -> d.transform(PersianCalendar.axis()))
  .forEach(System.out::println);

Side note:

DateInterval is closed by default (as required in most business date-related applications) but can be configured as half-open by calling interval.withOpenEnd().

Alternative:

There is even an approach to store instances of PersianCalendar directly in an interval, namely SimpleInterval (attention: always half-open before release v4.31!). Example:

SimpleInterval<PersianCalendar> pInterval =
  SimpleInterval.onTimeLine(PersianCalendar.axis()).between(
    PersianCalendar.of(1396, 8, 9),
    PersianCalendar.of(1396, 9, 2).plus(CalendarDays.ONE)
  );

Daily looping via an ordinary for-loop:

for (
  PersianCalendar pcal = pInterval.getStart().getTemporal(); 
  pcal.isBefore(pInterval.getEnd().getTemporal(); 
  pcal = pcal.plus(CalendarDays.ONE)
) {
  System.out.println(pcal);
}

However, I don't really recommend to use SimpleInterval because a) it has less features than DateInterval and b) is mainly designed for non-calendrical types like java.util.Date (since such intervals are always half-open while calendrical intervals should better be closed in most business applications).

Optional ranges

About your term "optional date range", I am not clear about the meaning. Could you clarify? Maybe you are talking about infinite or half-infinite interval boundaries. This is possible. Just construct your intervals not by between(...) but by since(...) or until(...). But this has impact on your looping code (you cannot loop from or until infinity.).

Update (2017-10-21)

Starting with release v4.31, the class SimpleInterval has been enhanced such that it can process calendrical types in a better way, namely always closed instead of half-open (but instant-like intervals will still be half-open, of course). Some new methods were introduced for this purpose, for example on(TimeAxis). The javadoc behind the link shows an example:

 PersianCalendar start = PersianCalendar.of(1392, PersianMonth.ESFAND, 27);
 PersianCalendar end = PersianCalendar.of(1393, PersianMonth.FARVARDIN, 6);

 SimpleInterval<PersianCalendar> i1 =
   SimpleInterval.on(PersianCalendar.axis()).between(start, end);
 SimpleInterval<PersianCalendar> i2 =
   SimpleInterval.on(PersianCalendar.axis()).between(
     end.minus(CalendarDays.ONE),
     end.plus(CalendarDays.ONE));

 System.out.println(
   interval.findIntersection(
     SimpleInterval.on(PersianCalendar.axis()).between(
       end.minus(CalendarDays.ONE), end.plus(CalendarDays.ONE))).get());
 // [AP-1393-01-05/AP-1393-01-06]

Such a calendar interval can be processed within IntervalCollection or IntervalTree as usual.

Meno Hochschild
  • 38,305
  • 7
  • 88
  • 115
  • Thanks a lot for your useful notes. Is there any tutorials or code examples for DateInterval in Time4j for completing my knowledge? – Sameer Sep 12 '17 at 04:53
  • About the term "optional date range" , I mean the date range that is not related to just start day of one month to the end of it. I want to define it for 2 or 3 months and have the days specification between these two dates. – Sameer Sep 12 '17 at 05:09
  • It works perfectly. Can I store these dates in the array of string or date? – Sameer Sep 12 '17 at 06:22
  • @Sameer Unfortunately I have not yet found time to write a tutorial page especially about intervals (with examples). And Time4J-intervals can do so much. Should really write it one time. About your question how to store start or end, well, it is serializable, or you can format and parse it to/from string. Even whole intervals are formattable and serializable. – Meno Hochschild Sep 12 '17 at 19:19
  • @Sameer About your optional date range, it seems as if you look for a way to add 2 or 3 months to a Persian calendar date to achieve the end of an interval. Probably a suitable combination of `start.with(PersianCalendar.DAY_OF_MONTH.maximized())` and `start.plus(2, PersianCalendar.Unit.MONTHS)` or similar does it for you. This does not change the logic of daily looping which works with every finite start and end. – Meno Hochschild Sep 12 '17 at 19:25
  • @ Meno Hochschild Thank you for the tips about how to store dates in the array of string and the way of defining optional date range. With your guide ,I can write all of the codes that I have in my mind.Thank you for taking the time to help me. – Sameer Sep 13 '17 at 05:03