プログラミングBlog

日付書式変更処理をリファクタリング

目的

Javaの学習をしていたら、改善できる箇所を見つけたため、リファクタリングを行う
リファクタリング対象は日付書式を英語書式に変更するクラス

条件① 月によって日にちは変わるが、1-31日あるとする
条件② 入力データの書式は yyyy年MM月dd日 とする
(変換例) 2021年11月7日 ⇨ 7th-Nov-2021

リファクタリング対象

import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

class ChangeDateFormat {

    // 日付の英語表記一覧
    private static final Map<String, String> dateNotations_En = new HashMap<>()
    {
        {
            put("01", "1st");
            put("02", "2nd");
            put("03", "3rd");
            put("04", "4th");
            put("05", "5th");
            put("06", "6th");
            put("07", "7th");
            put("08", "8th");
            put("09", "9th");
            put("10", "10th");
            put("11", "11th");
            put("12", "12th");
            put("13", "13th");
            put("14", "14th");
            put("15", "15th");
            put("16", "16th");
            put("17", "17th");
            put("18", "18th");
            put("19", "19th");
            put("20", "20th");
            put("21", "21st");
            put("22", "22nd");
            put("23", "23rd");
            put("24", "24th");
            put("25", "25th");
            put("26", "26th");
            put("27", "27th");
            put("28", "28th");
            put("29", "29th");
            put("30", "30th");
            put("31", "31st");
        }
    };

    // 月の英語表記一覧
    private static final Map<String, String> monthNotions_En = new HashMap<>()
    {
        {
            put("01", "Jan");
            put("02", "Feb");
            put("03", "Mar");
            put("04", "Apr");
            put("05", "May");
            put("06", "Jun");
            put("07", "Jul");
            put("08", "Aug");
            put("09", "Sep");
            put("10", "Oct");
            put("11", "Nov");
            put("12", "Dec");
        }
    };
    
    // 日付書式を日本語表記から英語表記に変換
    public String DateConvertJpToEn(Date inputDate) {

        String result = "";

        String date = new SimpleDateFormat("yyyy年MM月dd日").format(inputDate).replaceAll("[^0-9]", "");

        Integer strLen = date.length();

        result += dateNotation_En.get(date.substring(strLen - 2)) + "-";

        result += monthNotion_En.get(date.substring(strLen - 4, strLen - 2)) + "-";

        result += date.substring(0, strLen - 4);

        System.out.println(result);
        
        return result;
    }
}

リストを定数化する

日付と月の英語表記一覧は不変な値なため変更できないよう読み取り専用にする

    // 月の英語表記一覧
    private static final Map<String, String> monthNotions_En = Collections.unmodifiableMap(new HashMap<>()
    {
        {
            put("01", "Jan");
            put("02", "Feb");  
            //  省略
        }
    });

SimpleDateFormat

SimpleDateFormatはスレッドセーフではないため、複数のスレッドから使用する場合は意図した値とならない
スレッドセーフなAPIに変更する
入力データに時間は必要がないためjava.time.LocalDateを使用する

public String DateConvertJpToEn(LocalDate inputDate) {

String date = DateTimeFormatter.ofPattern("yyyy年MM月dd日").format(inputDate).replaceAll("[^0-9]", "");

参考サイト

日付フォーマットは同期化されません。スレッドごとに別のフォーマット・インスタンスを作成することをお薦めします。複数のスレッドがフォーマットに並行してアクセスする場合は、外部的に同期化する必要があります。

docs.oracle.com  

リストメモ
qiita.com

GitHub

github.com