Я придумал другое решение, используя несколько справочных таблиц:
public class PriceCalc {
private static final int FULL_WEEK_PRICE = 18;
private static final int REGULAR_DAYS = 50;
private static final int[] PREV_DAYS = {
0, 31, 61, 92, 122, 153, 183, 214, 244, 275, 305, 336
};
// remainders between start and end dates
private static final int[][] RESTS = {
// S M T W T F S
{ 0, 5, 7, 9, 11, 13, 16},
{13, 0, 2, 4, 6, 8, 10},
{11, 16, 0, 2, 4, 6, 8},
{ 9, 14, 16, 0, 2, 4, 6},
{ 7, 12, 14, 16, 0, 2, 4},
{ 5, 10, 12, 14, 16, 0, 2},
{ 3, 8, 10, 12, 14, 16, 0}
};
private int startDate;
private int startMonth;
private int endDate;
private int endMonth;
public PriceCalc(int startDate, int startMonth, int endDate, int endMonth) {
super();
this.startDate = startDate;
this.startMonth = startMonth;
this.endDate = endDate;
this.endMonth = endMonth;
}
private static int dayOfYear(int day, int month) {
return day + PREV_DAYS[(month - 1) % 12];
}
private static int dayOfWeek(int day, int month) {
return dayOfYear(day, month) % 7;
}
private static int isFlat(int duration) {
int flat = duration / REGULAR_DAYS;
try {
flat /= flat;
return flat;
}
catch(ArithmeticException e) {
return 0;
}
}
private int durationDays() {
int startDOY = dayOfYear(startDate, startMonth);
int endDOY = dayOfYear(endDate, endMonth);
return endDOY - startDOY;
}
public int calcPrice() {
int startDOW = dayOfWeek(startDate, startMonth);
int duration = durationDays();
int flat = isFlat(duration);
int regularDuration = duration * (1 - flat) + REGULAR_DAYS * flat;
int discount = flat * (duration - REGULAR_DAYS);
int fullWeeks = regularDuration / 7;
int rem = regularDuration % 7;
int endDOW = (dayOfYear(startDate, startMonth) + regularDuration) % 7;
int remainder = RESTS[startDOW][endDOW];
int price = fullWeeks * FULL_WEEK_PRICE + remainder + discount;
System.out.printf("Price for %3d days = %2d full weeks + %d days + %3d flat-rate days is: $%3d + $%2d + $%3d = $%3d%n",
duration, fullWeeks, rem, discount,
fullWeeks * FULL_WEEK_PRICE, remainder, discount, price
);
return price;
}
public static void main(String[] args) {
new PriceCalc(1, 1, 4, 1).calcPrice(); // $ 0 + $ 6 + $ 0 = $ 6
new PriceCalc(6, 1, 11, 1).calcPrice(); // $ 0 + $14 + $ 0 = $ 14
new PriceCalc(1, 1, 9, 1).calcPrice(); // $ 18 + $ 2 + $ 0 = $ 20
new PriceCalc(3, 1, 17, 1).calcPrice(); // $ 36 + $ 0 + $ 0 = $ 36
new PriceCalc(4, 1, 23, 1).calcPrice(); // $ 36 + $14 + $ 0 = $ 50
new PriceCalc(27, 1, 5, 3).calcPrice(); // $ 90 + $12 + $ 0 = $102
new PriceCalc(28, 2, 1, 6).calcPrice(); // $126 + $ 2 + $ 45 = $173
}
}