package sample.util;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.*;
import java.util.Optional;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;
/**
* 頻繁に利用される日時ユーティリティを表現します。
*/
public abstract class DateUtils {
private static WeekendQuery WeekendQuery = new WeekendQuery();
/** 指定された文字列(YYYY-MM-DD)を元に日付へ変換します。 */
public static LocalDate day(String dayStr) {
return dayOpt(dayStr).orElse(null);
}
public static Optional<LocalDate> dayOpt(String dayStr) {
if (StringUtils.isBlank(dayStr))
return Optional.empty();
return Optional.of(LocalDate.parse(dayStr.trim(), DateTimeFormatter.ISO_LOCAL_DATE));
}
/** 指定された文字列とフォーマット型を元に日時へ変換します。 */
public static LocalDateTime date(String dateStr, DateTimeFormatter formatter) {
return dateOpt(dateStr, formatter).orElse(null);
}
public static Optional<LocalDateTime> dateOpt(String dateStr, DateTimeFormatter formatter) {
if (StringUtils.isBlank(dateStr))
return Optional.empty();
return Optional.of(LocalDateTime.parse(dateStr.trim(), formatter));
}
/** 指定された文字列とフォーマット文字列を元に日時へ変換します。 */
public static LocalDateTime date(String dateStr, String format) {
return date(dateStr, DateTimeFormatter.ofPattern(format));
}
public static Optional<LocalDateTime> dateOpt(String dateStr, String format) {
return dateOpt(dateStr, DateTimeFormatter.ofPattern(format));
}
/** 指定された日付を日時へ変換します。*/
public static LocalDateTime dateByDay(LocalDate day) {
return dateByDayOpt(day).orElse(null);
}
public static Optional<LocalDateTime> dateByDayOpt(LocalDate day) {
return Optional.ofNullable(day).map((v) -> v.atStartOfDay());
}
/** 指定した日付の翌日から1msec引いた日時を返します。 */
public static LocalDateTime dateTo(LocalDate day) {
return dateToOpt(day).orElse(null);
}
public static Optional<LocalDateTime> dateToOpt(LocalDate day) {
return Optional.ofNullable(day).map((v) -> v.atTime(23, 59, 59));
}
/** 指定された日時型とフォーマット型を元に文字列(YYYY-MM-DD)へ変更します。 */
public static String dayFormat(LocalDate day) {
return dayFormatOpt(day).orElse(null);
}
public static Optional<String> dayFormatOpt(LocalDate day) {
return Optional.ofNullable(day).map((v) -> v.format(DateTimeFormatter.ISO_LOCAL_DATE));
}
/** 指定された日時型とフォーマット型を元に文字列へ変更します。 */
public static String dateFormat(LocalDateTime date, DateTimeFormatter formatter) {
return dateFormatOpt(date, formatter).orElse(null);
}
public static Optional<String> dateFormatOpt(LocalDateTime date, DateTimeFormatter formatter) {
return Optional.ofNullable(date).map((v) -> v.format(formatter));
}
/** 指定された日時型とフォーマット文字列を元に文字列へ変更します。 */
public static String dateFormat(LocalDateTime date, String format) {
return dateFormatOpt(date, format).orElse(null);
}
public static Optional<String> dateFormatOpt(LocalDateTime date, String format) {
return Optional.ofNullable(date).map((v) -> v.format(DateTimeFormatter.ofPattern(format)));
}
/** 日付の間隔を取得します。 */
public static Optional<Period> between(LocalDate start, LocalDate end) {
if (start == null || end == null)
return Optional.empty();
return Optional.of(Period.between(start, end));
}
/** 日時の間隔を取得します。 */
public static Optional<Duration> between(LocalDateTime start, LocalDateTime end) {
if (start == null || end == null)
return Optional.empty();
return Optional.of(Duration.between(start, end));
}
/** 指定営業日が週末(土日)か判定します。(引数は必須) */
public static boolean isWeekend(LocalDate day) {
Assert.notNull(day, "day is required.");
return day.query(WeekendQuery);
}
/** 指定年の最終日を取得します。 */
public static LocalDate dayTo(int year) {
return LocalDate.ofYearDay(year, Year.of(year).isLeap() ? 366 : 365);
}
/** 週末判定用のTemporalQuery>Boolean<を表現します。 */
public static class WeekendQuery implements TemporalQuery<Boolean> {
@Override
public Boolean queryFrom(TemporalAccessor temporal) {
DayOfWeek dayOfWeek = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
return dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY;
}
}
}