Ok, I was busy with the excellent JodaTime library trying to implement a retail / fiscal (4-5-4) general business calendar. I have already found a specific case for my company, but the general cases (mainly in determining the beginning of the year and leap years) are a killer; for example, there is a set of dates when two years (usually 364 days, usually) begin within one year of ISO.
In the process of defining the rules of the beginning of the year, I ended up with an abstract class and several specific classes to determine the beginning of the year, based on which side of the ISO lipday they fall.
(abbreviated) abstract class:
private static abstract class SimpleFiscalYearEndPattern implements FiscalYearEndPattern {
protected final int leapYearCountOffset;
protected final int doomsdayOffset;
private final int startingDayOfWeek;
private final int yearOffset;
private final long millisFromEpochToFiscalYearStart;
private final long millisElapsedToEpochDividedByTwo;
protected SimpleFiscalYearEndPattern(final int fiscalYear, final LocalDate startingOn, final MonthDay inFirstWeek) {
this.yearOffset = fiscalYear - startingOn.getYear();
this.doomsdayOffset = getDoomsdayOffset(inFirstWeek);
this.startingDayOfWeek = startingOn.getDayOfWeek();
final int startingDoomsday = getDoomsdayOffset(new MonthDay(startingOn, REFERENCE_CHRONOLOGY));
this.leapYearCountOffset = calculateLeapYearCountOffset(startingDoomsday : doomsdayOffset, doomsdayOffset);
final int leapYearsBefore = getPreviousLeapYears(fiscalYearBeforeEpoch);
}
}
(reduced) specific class (for dates in the range 1/7 - 2/28):
private static final class BeforeLeapYearEndPattern extends SimpleFiscalYearEndPattern {
private static final int FIRST_YEAR_LEAP_YEAR_OFFSET = -1;
private BeforeLeapYearEndPattern(final int fiscalYear, final LocalDate startingOn, final MonthDay onOrBefore) {
super(fiscalYear, startingOn, onOrBefore);
}
public static final BeforeLeapYearEndPattern create(final int fiscalYear, final LocalDate startingOn, final MonthDay onOrBefore) {
return new BeforeLeapYearEndPattern(fiscalYear, startingOn, onOrBefore);
}
@Override
protected int getPreviousLeapYears(final int isoYear) {
final int previousYear = isoYear - 1;
return (previousYear + leapYearCountOffset + (previousYear / 4) - (previousYear / 100) + (previousYear / 400)) / 7 + (leapYearCountOffset == FIRST_YEAR_LEAP_YEAR_OFFSET ? 1 : 0);
}
, leapYearCountOffset, ( ) , getPreviousLeapYears(), . - 3/1-12/31; - - leapYearCountOffset.
:. leapYearCountOffset () ? - , , ? , , , ? , , (?), ?