先日コードレビューをしていると、日付の曜日を取得するUtilクラスを実装してもらったところがありました。
共通処理をUtilクラスに切り出していることはとても良いことでしたが、コードを見るともう少し簡潔に書ける方法がありそうだなと思いました。
調べたところ、非常に簡潔に記述できる方法がありましたので、備忘録のためにも記述しておきます!
※一部抜粋コードで説明します。
修正前のコード
import java.time.DayOfWeek;
import java.time.LocalDate;
public class DateUtil {
/**
* 曜日を取得する
*
* @param baseDate 基準日
* @return 基準日の曜日
*/
public static String getDayOfWeek(LocalDate baseDate) {
if (baseDate == null) {
return "";
}
DayOfWeek dayOfWeek = baseDate.getDayOfWeek();
switch (dayOfWeek) {
case SUNDAY:
return "日";
case MONDAY:
return "月";
case TUESDAY:
return "火";
case WEDNESDAY:
return "水";
case THURSDAY:
return "木";
case FRIDAY:
return "金";
case SATURDAY:
return "土";
default:
return "";
}
}
}
switch文のところが何やら臭いますね🤔
もっと簡潔に書ける方法がありそう・・
public class DateUtilTest {
@ParameterizedTest
@MethodSource("providerGetDayOfWeek")
void getDayOfWeek(LocalDate baseDate, String expected) {
var actual = DateUtil.getDayOfWeek(baseDate);
Assertions.assertEquals(expected, actual);
}
private static Stream<Arguments> providerGetDayOfWeek() {
return Stream.of(
Arguments.of(LocalDate.of(2023, 5, 21), "日"),
Arguments.of(LocalDate.of(2023, 5, 22), "月"),
Arguments.of(LocalDate.of(2023, 5, 23), "火"),
Arguments.of(LocalDate.of(2023, 5, 24), "水"),
Arguments.of(LocalDate.of(2023, 5, 25), "木"),
Arguments.of(LocalDate.of(2023, 5, 26), "金"),
Arguments.of(LocalDate.of(2023, 5, 27), "土")
);
}
}
現状のプロダクションコードでも、テストは期待値どおりきちんと成功します。
修正後のコード(パート1)
Java17以降であれば、switch文を拡張switch文に切り替えることができます。
import java.time.DayOfWeek;
import java.time.LocalDate;
public class DateUtil {
/**
* 曜日を取得する
*
* @param baseDate 基準日
* @return 基準日の曜日
*/
public static String getDayOfWeek(LocalDate baseDate) {
if (baseDate == null) {
return "";
}
DayOfWeek dayOfWeek = baseDate.getDayOfWeek();
- switch (dayOfWeek) {
- case SUNDAY:
- return "日";
- case MONDAY:
- return "月";
- case TUESDAY:
- return "火";
- case WEDNESDAY:
- return "水";
- case THURSDAY:
- return "木";
- case FRIDAY:
- return "金";
- case SATURDAY:
- return "土";
- default:
- return "";
- }
+ return switch (dayOfWeek) {
+ case SUNDAY -> "日";
+ case MONDAY -> "月";
+ case TUESDAY -> "火";
+ case WEDNESDAY -> "水";
+ case THURSDAY -> "木";
+ case FRIDAY -> "金";
+ case SATURDAY -> "土";
+ default -> "";
+ };
}
}
これでもちょっとは簡潔になりましたよね。
修正後のコード(パート2)
さらに簡潔に書ける方法を見ていきましょう。
import java.time.DayOfWeek;
import java.time.LocalDate;
public class DateUtil {
/**
* 曜日を取得する
*
* @param baseDate 基準日
* @return 基準日の曜日
*/
public static String getDayOfWeek(LocalDate baseDate) {
if (baseDate == null) {
return "";
}
DayOfWeek dayOfWeek = baseDate.getDayOfWeek();
- switch (dayOfWeek) {
- case SUNDAY:
- return "日";
- case MONDAY:
- return "月";
- case TUESDAY:
- return "火";
- case WEDNESDAY:
- return "水";
- case THURSDAY:
- return "木";
- case FRIDAY:
- return "金";
- case SATURDAY:
- return "土";
- default:
- return "";
- }
+ return dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.JAPANESE);
}
}
たった1行です!
コードの説明をすると、
DayOfWeek dayOfWeek = baseDate.getDayOfWeek();
ここで、getDayOfWeek()メソッドを使用して、baseDateというLocalDateオブジェクトから曜日を取得してdayOfWeekに格納しています。
dayOfWeekにはenumのDayOfWeek型が入っています。このenumには、MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAYといった値が定義されています。
dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.JAPANESE);
enumのDayOfWeek型のインスタンスは、getDisplayName()メソッドを持っており、このメソッドは、指定したTextStyleとLocale(ロケール、地域設定)に基づいて曜日の名前を取得します。
ここでは、TextStyle.SHORTとLocale.JAPANESEを指定しているため、曜日の日本語の短い名前(例えば、"月"、"火"、"水"など)を取得します。
TextStyle.FULLだと、"日曜日"や"月曜日"となります。
※詳しくは[参考]へ
最後にテストも確認しておきましょう!
以上です!
参考
https://docs.oracle.com/javase/jp/8/docs/api/java/time/DayOfWeek.html
https://docs.oracle.com/javase/jp/8/docs/api/java/time/format/TextStyle.html
https://docs.oracle.com/javase/jp/8/docs/api/java/util/Locale.html