日付マスタ/カレンダーマスタ生成プログラムを作る Java編

#はじめに

かなり間が空きましたが前回の記事です。

セルフサービスBIの定着化はデータの下処理で決まる！　日付マスタ/カレンダーマスタに必要な項目
https://qiita.com/kitade58k/items/08db8147a7bb90a1bedd


日付マスタ/カレンダーマスタの重要性や利便性についてお伝えした記事です。
業務でBI製品を販売している関係で、お客様の創業期に合わせた日付マスタを作成してお客様へプレゼントしていたりします。

そのために作成した日付マスタ/カレンダーマスタ生成プログラムを社内展開したところ作り方を記事にしてみたら？との声があったので今回はその作り方を解説してみようと思います。


#完成版の動作
CUIでコマンドプロンプトから実行します。
こんな感じです。


```
C:\DateMasterCreator>create.bat
起点日(創業日)を入力してください。形式: yyyyMMdd 例:20000301
※日が1日以外の値の場合、自動的に1日に変換されます
20000401
作成年数を入力してください。例: 20
30
作成先のフォルダを入力してください 例 C:\data\
「.」を指定するとカレントディレクトリに作成します
※フォルダが存在しない場合作成します
.
2000/04/01,2000-04-01,20000401,2000,200004,4,Apr,1,2000年度,7,土,Sat,平成,平成12年,平成12年度,1,1,1,上期,1,14,1
2000/04/02,2000-04-02,20000402,2000,200004,4,Apr,2,2000年度,1,日,Sun,平成,平成12年,平成12年度,1,1,1,上期,2,15,2
2000/04/03,2000-04-03,20000403,2000,200004,4,Apr,3,2000年度,2,月,Mon,平成,平成12年,平成12年度,1,1,1,上期,2,15,2
～省略～
2030/03/29,2030-03-29,20300329,2030,203003,3,Mar,29,2029年度,6,金,Fri,令和,令和12年,令和11年度,30,4,2,下期,5,13,52
2030/03/30,2030-03-30,20300330,2030,203003,3,Mar,30,2029年度,7,土,Sat,令和,令和12年,令和11年度,30,4,2,下期,5,13,52
2030/03/31,2030-03-31,20300331,2030,203003,3,Mar,31,2029年度,1,日,Sun,令和,令和12年,令和11年度,30,4,2,下期,6,14,53
```

M日付.csv　のファイル名で日付マスタが生成されます。


#コンソール入力　java.util.Scanner　の利用

創業年月や作成年数等の入力値を取得する必用がありますが、java.util.Scannerクラスを使うと簡単に取得できます。
こんな感じです。

```Java
Scanner sc = null;
sc = new Scanner(System.in);

System.out.println( "起点日(創業日)を入力してください。形式: yyyyMMdd 例:20000301 " );
System.out.println( "※日が1日以外の値の場合、自動的に1日に変換されます" );
while (true){
    yyyymmdd = sc.next();
```


#日付フォーマット

日付の処理はやはりjava.util.Calendarクラスを利用します。

インスタンスを生成して以下のように年月日をセットします。

```Java
public synchronized void setDate(int y, int m, int d) {
    calendar__.set(y, m - 1, d);
}
```

文字列の生成は基本的に年、月、日を取得するメソッドを用意して、組み合わせて様々なフォーマットを作るようにします。
基本のメソッドはこんな感じです。

```Java
    public int getYear() {
        return calendar__.get(Calendar.YEAR);
    }
    
    public int getMonth() {
        int ret = -1;
        switch (calendar__.get(Calendar.MONTH)) {
            case Calendar.JANUARY : //1
                ret = JANUARY;
                break;
            case Calendar.FEBRUARY : //2
                ret = FEBRUARY;
                break;
            case Calendar.MARCH : //3
                ret = MARCH;
                break;
            case Calendar.APRIL : //4
                ret = APRIL;
                break;
            case Calendar.MAY : //5
                ret = MAY;
                break;
            case Calendar.JUNE : //6
                ret = JUNE;
                break;
            case Calendar.JULY : //7
                ret = JULY;
                break;
            case Calendar.AUGUST : //8
                ret = AUGUST;
                break;
            case Calendar.SEPTEMBER : //9
                ret = SEPTEMBER;
                break;
            case Calendar.OCTOBER : //10
                ret = OCTOBER;
                break;
            case Calendar.NOVEMBER : //11
                ret = NOVEMBER;
                break;
            case Calendar.DECEMBER : //12
            default:
                ret = DECEMBER;
                break;
        }
        return ret;
    }

    public int getDay() {
        return calendar__.get(Calendar.DATE);
    }
```

これらをゼロ埋めしたり、文字型で戻り値を返すメソッドを用意しておくと便利かと思います。
そうするとyyyyMMdd形式が必要な場合は以下のように記載することで値を取得できます。

```Java
getStrYear() + str + getStrMonth() + str + getStrDay();
```

生成したい値やフォーマットに応じて生成メソッドを用意しておけば良いかと思います。


#期等の計算系はミリ秒に直してから。
期や四半期といった計算が必要な項目はミリ秒に直して計算します。
こんな感じです。

```Java
diff = newDate.getTimeMillis() - oldDate.getTimeMillis();
long year = (long) 366 * (long) 24 * (long) 60 * (long) 60 * (long) 1000;
long a = ldiff / year;
```

閏年がどうこうといった面倒な計算についてはjava.util.Calendarをプラス1日づつしていくなどすると案外簡単に実装できます。


#最後に

最後に簡単ではありますが、日付マスタ/カレンダーマスタ生成プログラムの実装方法について解説しました。
一度作ってしまえば何かと使える機会があるかと思います。
プログラムに覚えのある方はぜひトライしてみていただければと思います。