西暦和暦 変換プログラム Javaコマンドライン版

Javaの練習用に、OCamlで作成した yearx(西暦<=>和暦変換)プログラムを Java に移植してみた。

OCamlでは、タプルという組(ペア)になったデータを使うことができたが、Javaにはないみたい。

かわりに、Mapを使ってみた。
Mapは連想配列で、今回は、LinkedHashMapを使った。これは、登録の順番にデータを並べるものである。

基本的なアルゴリズムは、OCamlと同じである。

あと、和暦のデータは、配列のときのようにリテラル表記で指定したかったが、それはできないみたい。

Mapを初期化するときに、putメソッドで要素を入れていくしかなさそう。

それから、Windows版のJavacでコンパイルする場合、文字コードをcp932にしとかないといけない。
Windowsは、UTF-8にすることはできないだろうなあ。
今までの資産がおおすぎるからなあ。
でも、インターネットはUTF-8だし、MacもUTF-8だし、Windowsだけ孤立しているっぽい。
どこかのタイミングで UTF-8 にするほうがいいんだろうけど。

Xnengo.java

// x2nengo -- 西暦から年号を求めるプログラム
import java.io.*;
import java.io.IOException;
import java.util.*;

public class Xnengo {

    // クラス定数
    // static final String FILENAME = "yearx.dat";
    static final String VERSION = "0.1";

    static final Map<String, Integer> yeardata = new LinkedHashMap<String, Integer>() {{
        put ("文禄", 1591);
        put ("慶長", 1594);
        put ("元和", 1614);
        put ("寛永", 1623);
        put ("正保", 1643);
        put ("慶安", 1647);
        put ("承応", 1651);
        put ("明暦", 1654);
        put ("万治", 1657);
        put ("寛文", 1660);
        put ("延宝", 1672);
        put ("天和", 1680);
        put ("貞享", 1683);
        put ("元禄", 1687);
        put ("宝永", 1703);
        put ("正徳", 1710);
        put ("享保", 1715);
        put ("元文", 1735);
        put ("寛保", 1740);
        put ("延享", 1743);
        put ("寛延", 1747);
        put ("宝歴", 1750);
        put ("明和", 1763);
        put ("安永", 1771);
        put ("天明", 1780);
        put ("寛政", 1788);
        put ("享和", 1800);
        put ("文化", 1803);
        put ("文政", 1817);
        put ("天保", 1829);
        put ("弘化", 1843);
        put ("嘉永", 1847);
        put ("安政", 1853);
        put ("万延", 1859);
        put ("文久", 1860);
        put ("元治", 1863);
        put ("慶応", 1864);
        put ("明治", 1866);
        put ("大正", 1911);
        put ("昭和", 1925);
        put ("平成", 1988);
        put ("令和", 2018);
        put ("未来", 2100);
        }};

        static final String MES = "java Xnengo -g => 西暦を求める\njava Xnengo -n => 和暦を求める";
        static final String VERMES = "西暦<=>和暦 変換プログラム Java版 ver_"
            + VERSION
            + "\nCopyright 2019 Seiichi Nukayama";

    /**
     * 年号の一覧を作る
     *
     * @return -- String 年号を " " で連結した文字列。
     */
    private String makeHelp () {
        String text = "";
        for (Map.Entry<String, Integer> s : yeardata.entrySet()) {
            text = text + s.getKey() + " ";
        }
        return text;
    }
    
    /**
     * nengoArray -- 西暦の数字から、年号と元号年を求める。
     * @param: year -- 0 < year < 2100 の数字
     * 
     * @return: String[] -- [0] 年号  [1] 元年からの数字の文字
     */
    private String[] nengoArray (int year) {
        String nengoIt = null;
        int yearIt = 0, gengoYear = 0;
        String[] data = {null, null};
        
        for (Map.Entry<String, Integer> s : yeardata.entrySet()) {
            // System.out.println(s.getKey() + ":" + s.getValue());  // チェック用
            if (year > s.getValue()) {
                nengoIt = s.getKey();
                yearIt = s.getValue();
                // System.out.println(nengoIt + yearIt);  // チェック用
            } else {
                gengoYear = year - yearIt;
                break;
            }
        }
        data[0] = nengoIt;
        data[1] = gengoYear == 1 ? "元" : String.valueOf(gengoYear);
        // System.out.println(data[0] + ":" + data[1]);  // チェック用
        return data;
    }

    /**
     * ユーザーに文字列の入力をしてもらい、それを返す
     * 
     * @param: prompt -- ユーザーに表示する文字列
     *                   (例)"入力 > "
     *
     * @raturn: String -- 半角英数字を想定。日本語の場合はどうなるか?
     */
    private String getUserInput (String prompt) {
        String inputLine = null;
        System.out.print (prompt + " ");
        try {
            BufferedReader is = new BufferedReader(
                new InputStreamReader (System.in));
            inputLine = is.readLine();
            if (inputLine.length() == 0) return null;
        } catch (IOException e) {
            System.out.println ("IOException: " + e);
        }
        return inputLine.toLowerCase ();
    }
    
    public static void main (String [] args) {
        String[] nengo = {null, null};
        int n = 0, year = 0;
        Xnengo job = new Xnengo();

        String helpMES = job.makeHelp();
        
        
        // 引数チェック
        switch (n = args.length) {
        case 0:
            System.out.println(MES);
            System.exit(1);
            break;
        case 1:
            // g の場合 -- 西暦を求める処理
            if ("-g".equals(args[0])) {
                do {
                    nengo[0] = job.getUserInput("和暦を入力 (help: 和暦一覧)> ");
                    if ("help".equals(nengo[0])) {
                        System.out.println(helpMES);
                    }
                } while ("help".equals(nengo[0]));
                nengo[1] = job.getUserInput("年を半角数字で入力 > ");
                // 年号も数字も null で無ければ
                if (nengo[0] != null && nengo[1] != null) {
                    // Mapの getメソッドで一発で検索できる
                    year = job.yeardata.get(nengo[0]) + Integer.parseInt(nengo[1]);
                    System.out.println(nengo[0] + nengo[1] + "年は、西暦 " + year + "年です。");
                } else {
                    if (nengo[0] == null) {
                        System.out.println("和暦がnull値です。");
                    } else {
                        System.out.println("年がnull値です。");
                    }
                    System.exit(1);
                }
            }
            // n の場合 -- 年号を求める処理
            else if ("-n".equals(args[0])) {
                String text = job.getUserInput("西暦を半角数字で入力 > ");
                if (text != null) {
                    year = Integer.parseInt(text);
                } else {
                    System.out.println ("西暦が null値です。");
                }
                if (year < 1592 || year > 2100) {
                    System.out.println("引数で指定できる西暦年は、1592 <= 数字 <= 2100 の範囲です。");
                    System.exit(1);
                } else { 
                    nengo = job.nengoArray(year);
                    System.out.println("西暦 " + year + "年は、" + nengo[0] + " " + nengo[1] + "年です。");
                }
            }
            // v の場合
            else if ("-v".equals(args[0])) {
                System.out.println(VERMES);
            }
            else {
                System.out.println(MES);
                System.exit(1);
            }
            break;
        default:
            System.out.println(MES);
            System.exit(1);
        }
    }
}