Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should the "first month of each quarteryear" be represented using joda-time?

Tags:

java

jodatime

I'm working on some accounting logic. The logic is that an accounting that happened in the first month of a quarter year must have a value date that is at the end of the preceding quarter year. I know that I can represent the month as a period. But I have no idea how to represent the recurring period of a quarter year.

I'm able to do the calculation using joda-time classes that would give me the value date at the end of the preceding quarter year. However I would like to represent "first month of each quarter year" as a single value that I use in my calculations.

So is there some API in joda-time that is well suitable for representing this kind of recurring period?

Some example dates are:

date of invoce | value date  
2013-01-01     | 2012-12-31  
2013-01-31     | 2012-12-31  
2013-02-01     | 2013-02-01  
2013-03-31     | 2013-03-31  
2013-04-01     | 2013-03-31 

OK, here is more explanative example as requested in comments: The accounting logic is about a kind of pension funds you have to apply for. You apply for the pensions of 2012 in the succeeding year, exactly on 1st of January 2013. It will be granted to you on the 15th of April 2013. Since April is the first month of the quarter year, the granting will have its value date set to the 31st of March. All pensions that are accounted within one quarter year are paid 1 month and 5 days after that quarter year has ended. So even if you have been granted your pension in April, you will still get it paid on 5th of May. Otherwise you would have to wait for it to be payed until 5th of September.

But I don't really know how this example should help. This question really is about modeling "every first month of each quarter year" with joda-time classes or even implementing some API of joda-time.

like image 858
SpaceTrucker Avatar asked Dec 11 '22 10:12

SpaceTrucker


1 Answers

I had to implement this too. Here is an implementation that seems ok at first glance.

public class QuarterPeriods {

    public static LocalDate quarterStartFor(LocalDate date) {
        return date.withDayOfMonth(1).withMonthOfYear((((date.getMonthOfYear() - 1) / 3) * 3) + 1);
    }

    public static LocalDate quarterEndFor(LocalDate date) {
        return quarterStartFor(date).plusMonths(3).minusDays(1);
    }
}

public class QuarterPeriodsTest {

    @Test
    public void startOfQuarter() throws Exception {
        assertThat(quarterStartFor(StubDates.dateOf("2011/02/02")), equalTo(StubDates.dateOf("2011/01/01")));
        assertThat(quarterStartFor(StubDates.dateOf("2011/01/01")), equalTo(StubDates.dateOf("2011/01/01")));
        assertThat(quarterStartFor(StubDates.dateOf("2011/02/02")), equalTo(StubDates.dateOf("2011/01/01")));
        assertThat(quarterStartFor(StubDates.dateOf("2011/04/01")), equalTo(StubDates.dateOf("2011/04/01")));
        assertThat(quarterStartFor(StubDates.dateOf("2011/07/01")), equalTo(StubDates.dateOf("2011/07/01")));
        assertThat(quarterStartFor(StubDates.dateOf("2011/12/19")), equalTo(StubDates.dateOf("2011/10/01")));
    }

    @Test
    public void endOfQuarter() throws Exception {
        assertThat(quarterEndFor(StubDates.dateOf("2011/02/02")), equalTo(StubDates.dateOf("2011/03/31")));
        assertThat(quarterEndFor(StubDates.dateOf("2011/01/01")), equalTo(StubDates.dateOf("2011/03/31")));
        assertThat(quarterEndFor(StubDates.dateOf("2011/02/02")), equalTo(StubDates.dateOf("2011/03/31")));
        assertThat(quarterEndFor(StubDates.dateOf("2011/04/01")), equalTo(StubDates.dateOf("2011/06/30")));
        assertThat(quarterEndFor(StubDates.dateOf("2011/07/01")), equalTo(StubDates.dateOf("2011/09/30")));
        assertThat(quarterEndFor(StubDates.dateOf("2011/12/19")), equalTo(StubDates.dateOf("2011/12/31")));
    }
}

public class StubDates {

    public static LocalDate dateOf(String date) {
        return DateTimeFormat.forPattern("yyyy/MM/dd").withZone(DateTimeZone.UTC).parseDateTime(date).toLocalDate();
    }
}
like image 168
time4tea Avatar answered May 01 '23 10:05

time4tea