JAVAでn営業日後を求める
業務ロジックを書いていると、n営業日後の日付が必要になることがあります。
(n営業日以内に処理を行わない場合アラートなど)
が、これを求めるのは結構面倒です。
休日が土日だけなら簡単に計算できますが、祝日には決まった法則がありません。
自システム上にマスタを作成して管理するか、外部から情報を取得する必要があります。
前者は自分でマスタを管理する必要があり面倒なので、今回は後者の手段で営業日を確認するクラスを作ってみました。
できたもの
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class BusinessDayApiAccessorServiceImpl implements BusinessDayApiAccessor {
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("uuuuMMdd");
private final OkHttpClient client;
@Override
public LocalDate getBusinessDayAfter(LocalDate baseDate, int days) {
return getBusinessDay(true, baseDate, days);
}
@Override
public LocalDate getBusinessDayBefore(LocalDate baseDate, int days) {
return getBusinessDay(false, baseDate, days);
}
private LocalDate getBusinessDay(boolean isNext, LocalDate baseDate, int days) {
if (days == 0) {
return baseDate;
}
return getBusinessDay(isNext, sendRequest(isNext, isNext ? baseDate.plusDays(1) : baseDate.minusDays(1)),
days - 1);
}
private LocalDate sendRequest(boolean isNext, LocalDate baseDate) {
HttpUrl httpUrl = new HttpUrl.Builder().scheme("http").host("s-proj.com").addPathSegment("utils")
.addPathSegment("getBusinessDay.php").addQueryParameter("kind", isNext ? "next" : "prev")
.addQueryParameter("date", baseDate.format(DATE_FORMATTER)).build();
Request request = new Request.Builder().url(httpUrl).get().build();
try (Response response = client.newCall(request).execute()) {
String resultBody = response.body().string();
return LocalDate.parse(resultBody, DATE_FORMATTER);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean isBusinessDay(LocalDate date) {
return sendRequest(true, date).isEqual(date);
}
}
解説
国民の祝日チェックさんの公開されている国民の祝日APIを営業日判定の元ネタとして利用します。
このAPIは対象の日付が営業日だったらその日付を、営業日ではなかった場合は次または前の営業日を返してくれます。
よって、nに達するまで1日ずつ日付をずらしながら、APIを叩くメソッドを実行すればn営業日後(あるいは前)の日付を求めることが出来ます。
なお、APIを叩くのにOkHttpを利用しています。
注意点
外部へのAPIアクセスを挟む上に再帰ロジックなのでnの値は多くても10前後までが現実的です。
100営業日後とかを求めようとすると大変なことになります。(業務上あまりないとは思いますが)
万が一必要な場合は別な手段を使ったほうが無難です。