Newer
Older
ASD2024 / AdapterTest.java
import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Calendar;
 
/**
 * 誕生日:通常は西暦で管理しており、年齢などを出力するが、
 * 必要に応じて和暦で表示する。
 */
public class AdapterTest {
    public static void main(String[] args) {
        ArrayList<JapaneseBirthDay> chkDays = new ArrayList<JapaneseBirthDay>();
        chkDays.add(new JapaneseBirthDay(2023, 5, 2));
        chkDays.add(new JapaneseBirthDay(2019, 5, 1));
        chkDays.add(new JapaneseBirthDay(2019, 4, 30));
        chkDays.add(new JapaneseBirthDay(1989, 1, 8));
        chkDays.add(new JapaneseBirthDay(1989, 1, 7));
 
        for (JapaneseBirthDay jbd : chkDays) {
            System.out.println(jbd);
            System.out.println(jbd.yearsOld());
            System.out.println(jbd.toWareki());
            System.out.println("-----");
        }
    }
}
 
/**
 * 誕生日クラス
 * Calendar や LocalDate など、年月日を保持するクラスを継承してもよかったが、
 * 今回はメンバーとして持つことにした。
 * 
 * 誕生日クラス自身も、Calendar に対するアダプタークラス(オブジェクト・アダプター:移譲を利用)といえる
 * (なぜなら、yearsOld() を追加しているので)
 * また、toString()をシンプルにしている。
 * もし、Calendar クラスを継承していたら、toString()はCalendarクラスのメソッドをオーバーライドすることになる。
 */
class BirthDay {
    protected Calendar cal;
 
    public BirthDay(int year, int month, int day) {
        cal = Calendar.getInstance();
        cal.set(year, month, day);
    }
 
    // 誕生日をYYYY/MM/DD で返す
    public String toString() {
        // return bd.toString();
        return String.format("%4d/%02d/%02d", cal.get(Calendar.YEAR),
                cal.get(Calendar.MONTH),
                cal.get(Calendar.DAY_OF_MONTH));
    }
 
    // 何歳何ヶ月?を返す
    public String yearsOld() {
        LocalDate curDate = LocalDate.now();
        Period sabun = Period.between(cal.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), curDate);
        return String.format("%3d yrs %2d months %2d days", sabun.getYears(), sabun.getMonths(),
                sabun.getDays());
    }
}
 
/**
 * 和暦で誕生日を表示できるクラス (継承によるAdapter)
 */
class JapaneseBirthDay extends BirthDay {
    public JapaneseBirthDay(int year, int month, int day) {
        super(year, month, day);
    }
 
    /**
     * 和暦での誕生日表記を返す
     * @return 和暦での誕生日表記
     */
    public String toWareki() {
        int month = cal.get(Calendar.MONTH);
        int day = cal.get(Calendar.DAY_OF_MONTH);
        return getNengo() + "/" + String.format("%02d/%02d", month, day);
    }
 
    /**
     * 年号アルファベット+年 を返す
     * @return 年号アルファベット+年
     */
    private String getNengo() {
        String[] nengoArray = { "M", "T", "S", "H", "R" }; // Meiji,Taisho,Showa,Heisei,Reiwa
        int[] fromYear = { 1868, 1912, 1926, 1989, 2019 };
        int[] fromMonth = { 1, 7, 12, 1, 5 };
        int[] fromDay = { 25, 30, 25, 8, 1 };
 
        int year = cal.get(Calendar.YEAR);
        String ymd = this.toString(); // 形式:YYYY/MM/DD (例: 1999/10/22)
        String nengo = null;
        int nengoYear = 0;
        for (int i = nengoArray.length - 1; i > 0; i--) {
            String fromYMD = new BirthDay(fromYear[i], fromMonth[i], fromDay[i]).toString();
            // System.out.print("      >> check "+fromYMD+" <= "+ymd);
            if (fromYMD.compareTo(ymd) <= 0) { // YYYY/MM/DD文字列の大小関係でチェックしている
                // System.out.println("  OK");
                nengo = nengoArray[i];
                nengoYear = year - fromYear[i]+1;
                break;
            } else {
                // System.out.println("  X");
            }
        }
        if (nengo == null) {
            nengo = "E";
            nengoYear = year - 1603 + 1;
        }
        return String.format("%s%02d", nengo, nengoYear); // ex. R05 H30
    }
}