1.はじめに
平成23年は西暦何年?頭の中にすぐ変換できない?そうです。東日本大震災が発生した2011年です。これぐらいは覚えていられるとしても、こんな年ばかりではありませんが、私達は、国や都道府県の書類は必ず元号で書かなければならないという場面に何度も出会います。
またある出来事から何年経過した?なんていうことを考えるときは、西暦での引き算が便利です。人の年齢を計算する場合もこれに該当します。
ネットで検索すると、これを頭の中でやる方法が見つかります(西暦の下二桁にある数字を足したり引いたりする方法)が、私には真似できません。覚えていられません。またネット上で変換するサービスも見つかりますが、これもネット環境がない場合には使えません。エクセルなど手元のアプリを立ち上げてやる方法もあるけど、これだけのことでわざわざ重いアプリを立ち上げるのが面倒です。
そこで、bash の勉強がてら、西暦と元号を相互に変換できるスクリプトを作成してみました。
2.全体の構成
- 元号から変換するのか、西暦から変換するのかを選択できるようにする
- 西暦から元号に変換するコードを関数にして、コードを少なくする
- 不正な日付の入力をエラーとする
- 不正な表示がそのまま表示されるのを防ぐ
3.西暦から元号に変換する関数の定義
元号を西暦に変換する場合も、元号を西暦に変換してからその西暦を元に元号に再変換するやり方ですが、2つ目の工程は西暦から入力する場合にも共通するので、この作業を関数にしました。
入力選択 | 元号 | 西暦 |
---|---|---|
工程1 | 元号から西暦に変換 | |
工程2 | 西暦を元に元号に再変換 | 西暦を元に元号に変換 |
function g_change
{
str="${seireki}"'/'"${month}"'/'"${day}"
int4=`date +%Y -d "${str}"`
int5=`date +%-m -d "${str}"`
int6=`date +%-d -d "${str}"`
if [ "${int4}" -eq 2019 ] && [ "${int5}" -ge 5 ];then
int7=$(("${int4}"-2019+1))
echo '--------------------------------------------------'
echo '==>西暦'"${seireki}"'年'"${int5}"'月'"${int6}"'日'
echo '==>令和'"${int7}"'年'"${int5}"'月'"${int6}"'日'
echo '--------------------------------------------------'
elif [ "${int4}" -ge 2020 ] ;then
int7=$(("${int4}"-2019+1))
echo '--------------------------------------------------'
echo '==>西暦'"${seireki}"'年'"${int5}"'月'"${int6}"'日'
echo '==>令和'"${int7}"'年'"${int5}"'月'"${int6}"'日'
echo '--------------------------------------------------'
elif [ "${int4}" -eq 1989 ] && [ "${int5}" -eq 1 ] && [ "${int6}" -ge 8 ];then
int7=$(("${int4}"-1989+1))
echo '--------------------------------------------------'
echo '==>西暦'"${seireki}"'年'"${int5}"'月'"${int6}"'日'
echo '==>平成'"${int7}"'年'"${int5}"'月'"${int6}"'日'
echo '--------------------------------------------------'
elif [ "${int4}" -eq 1989 ] && [ "${int5}" -ge 2 ];then
int7=$(("${int4}"-1989+1))
echo '--------------------------------------------------'
echo '==>西暦'"${seireki}"'年'"${int5}"'月'"${int6}"'日'
echo '==>平成'"${int7}"'年'"${int5}"'月'"${int6}"'日'
echo '--------------------------------------------------'
elif [ "${int4}" -ge 1990 ];then
int7=$(("${int4}"-1989+1))
echo '--------------------------------------------------'
echo '==>西暦'"${seireki}"'年'"${int5}"'月'"${int6}"'日'
echo '==>平成'"${int7}"'年'"${int5}"'月'"${int6}"'日'
echo '--------------------------------------------------'
elif [ "${int4}" -eq 1926 ] && [ "${int5}" -eq 12 ] && [ "${int6}" -ge 25 ];then
int7=$(("${int4}"-1926+1))
echo '--------------------------------------------------'
echo '==>西暦'"${seireki}"'年'"${int5}"'月'"${int6}"'日'
echo '==>昭和'"${int7}"'年'"${int5}"'月'"${int6}"'日'
echo '--------------------------------------------------'
elif [ "${int4}" -ge 1927 ];then
int7=$(("${int4}"-1926+1))
echo '--------------------------------------------------'
echo '==>西暦'"${seireki}"'年'"${int5}"'月'"${int6}"'日'
echo '==>昭和'"${int7}"'年'"${int5}"'月'"${int6}"'日'
echo '--------------------------------------------------'
else
echo '==>大正には対応しておりません。'
fi
}
目新しいコードはないと思いますが、例えば令和1年2月28日なんていう入力がそのまま結果表示されておりましたが、元号に変換した後に結果表示させることに変更したため、このような場合は正しく平成31年2月28日表示されるようになりました。
4.元号から西暦に変換するコード
例えば令和1年2月29日と入力すると、実際には存在しないので、不正な入力として再入力を求めることにしました。コードは以下のとおりです。
元号年月日が入力されるまでは入力を促す画面が表示されますが、入力されると元号のコードに従って一旦西暦に直します。
その途中に、whiile コマンドを内部に入れて、西暦に変換してみた値をdateコマンドで実際にあり得る日付なのかを判定するとともに、不正な入力の場合は「閏年ではない?または不正な入力だ」と注意を促し、入力された変数の値をクリアー、再度変数の入力を促すことにしました。
dateコマンドを実際に存在する日の判定に使うと、date: invalid date ‘2019/2/29’ が表示されますが、無視してください。本当はこれを/dev/null 2>&1 に入れて表示させないよう試みておりますが、成功しておりません。なんか良い方法がないかな?
while [ -z "${ketsugo}" ]
do
echo '計算する元号年月日を入力してください。'
read -p "元号(1:昭和 2:平成 3:令和):" gengo
read -p "年(1~ ):" year
read -p "月(1~12):" month
read -p "日(1~31):" day
ketsugo="${gengo}"/"${year}"/"${month}"/"${day}"
#---------西暦変換
if [ "${gengo}" -eq 3 ];then
seireki=$((2019+"${year}"-1))
elif [ "${gengo}" -eq 1 ];then
seireki=$((1926+"${year}"-1))
elif [ "${gengo}" -eq 2 ];then
seireki=$((1989+"${year}"-1))
else
echo '==> 昭和・平成・令和しか対応しておりません。'
fi
#入力ミスの判定→不正な日付が入力されるとdate: invalid date ‘2019/2/29’が表示され、"${s_ketsugo}"は空になる、
s_ketsugo=`date +%Y/%-m/%-d -d "${seireki}"/"${month}"/"${day}"`>/dev/null 2>&1
while [ -z "${s_ketsugo}" ]
do
echo '閏年でない?または入力形式が不正です' && unset ketsugo s_ketsugo && break
done
done
# 西暦を元号に変換する関数の実行
g_change
# 変数の値をクリアーして最初のメニュー表示へもどります
unset gengo year month day seireki ketsugo
5.西暦から元号に変換するコード
元号から西暦に変換するコードに比べれば非常にシンプルだと思いますが、ここでも不正な入力の場合エラー処理するコードを挿入しました。
while [ -z "${ketsugo2}" ]
do
echo '計算する西暦年月日を入力してください'
read -p '年(yyyy) :' seireki
read -p '月 (1-12):' month
read -p '日 (1-31):' day
ketsugo2=`date +%Y/%-m/%-d -d "${seireki}"/"${month}"/"${day}"` && >/dev/null 2>&1
while [ -z "${ketsugo2}" ]
do
echo '閏年でない?または入力形式が不正です' && unset ketsugo2 && break
done
done
g_change
unset gengo year month day seireki ketsugo2
6.実行例
[ 1:元号→西暦 | 2:西暦→元号 | q:終了 ] どれを実行しますか?[ 1 / 2 / q ]:1
計算する元号年月日を入力してください。
元号(1:昭和 2:平成 3:令和):3
年(1~ ):1
月(1~12):2
日(1~31):29
date: invalid date ‘2019/2/29’
閏年でない?または入力形式が不正です
計算する元号年月日を入力してください。
元号(1:昭和 2:平成 3:令和):3
年(1~ ):1
月(1~12):2
日(1~31):28
--------------------------------------------------
==>西暦2019年2月28日
==>平成31年2月28日
--------------------------------------------------
[ 1:元号→西暦 | 2:西暦→元号 | q:終了 ] どれを実行しますか?[ 1 / 2 / q ]:2
計算する西暦年月日を入力してください
年(yyyy) :2019
月 (1-12):2
日 (1-31):29
date: invalid date ‘2019/2/29’
閏年でない?または入力形式が不正です
計算する西暦年月日を入力してください
年(yyyy) :2019
月 (1-12):2
日 (1-31):28
--------------------------------------------------
==>西暦2019年2月28日
==>平成31年2月28日
--------------------------------------------------
[ 1:元号→西暦 | 2:西暦→元号 | q:終了 ] どれを実行しますか?[ 1 / 2 / q ]:q
7.スクリプト全文
#!/bin/bash
function g_change
{
#---西暦に変換後にもう一度元号に直して表示する。
str="${seireki}"'/'"${month}"'/'"${day}"
int4=`date +%Y -d "${str}"`
int5=`date +%-m -d "${str}"`
int6=`date +%-d -d "${str}"`
#---閏年でない場合の2月29日はerror表示される。ここが課題。できればエラー表示させないで再度の入力を促したい。
#---現在はこのエラー表示をクリアしてごまかしている。
if [ -z `date +%Y/%-m/%-d -d "${str}"` ]
then
clear
echo 'ありえない年月日です。'
#exit
else
#----西暦を元号で分割
#----新元号が出現した場合には、令和の前に新元号を挿入
if [ "${int4}" -eq 2019 ] && [ "${int5}" -ge 5 ];then
int7=$(("${int4}"-2019+1))
echo '--------------------------------------------------'
echo '==>西暦'"${seireki}"'年'"${int5}"'月'"${int6}"'日'
echo '==>令和'"${int7}"'年'"${int5}"'月'"${int6}"'日'
echo '--------------------------------------------------'
elif [ "${int4}" -ge 2020 ] ;then
int7=$(("${int4}"-2019+1))
echo '--------------------------------------------------'
echo '==>西暦'"${seireki}"'年'"${int5}"'月'"${int6}"'日'
echo '==>令和'"${int7}"'年'"${int5}"'月'"${int6}"'日'
echo '--------------------------------------------------'
elif [ "${int4}" -eq 1989 ] && [ "${int5}" -eq 1 ] && [ "${int6}" -ge 8 ];then
int7=$(("${int4}"-1989+1))
echo '--------------------------------------------------'
echo '==>西暦'"${seireki}"'年'"${int5}"'月'"${int6}"'日'
echo '==>平成'"${int7}"'年'"${int5}"'月'"${int6}"'日'
echo '--------------------------------------------------'
elif [ "${int4}" -eq 1989 ] && [ "${int5}" -ge 2 ];then
int7=$(("${int4}"-1989+1))
echo '--------------------------------------------------'
echo '==>西暦'"${seireki}"'年'"${int5}"'月'"${int6}"'日'
echo '==>平成'"${int7}"'年'"${int5}"'月'"${int6}"'日'
echo '--------------------------------------------------'
elif [ "${int4}" -ge 1990 ];then
int7=$(("${int4}"-1989+1))
echo '--------------------------------------------------'
echo '==>西暦'"${seireki}"'年'"${int5}"'月'"${int6}"'日'
echo '==>平成'"${int7}"'年'"${int5}"'月'"${int6}"'日'
echo '--------------------------------------------------'
elif [ "${int4}" -eq 1926 ] && [ "${int5}" -eq 12 ] && [ "${int6}" -ge 25 ];then
int7=$(("${int4}"-1926+1))
echo '--------------------------------------------------'
echo '==>西暦'"${seireki}"'年'"${int5}"'月'"${int6}"'日'
echo '==>昭和'"${int7}"'年'"${int5}"'月'"${int6}"'日'
echo '--------------------------------------------------'
elif [ "${int4}" -ge 1927 ];then
int7=$(("${int4}"-1926+1))
echo '--------------------------------------------------'
echo '==>西暦'"${seireki}"'年'"${int5}"'月'"${int6}"'日'
echo '==>昭和'"${int7}"'年'"${int5}"'月'"${int6}"'日'
echo '--------------------------------------------------'
else
echo '==>大正には対応しておりません。'
fi
fi
}
#----- menu
while
echo '---------------------'
echo '| 昭和 ⇔ 1926年以降 |'
echo '| 平成 ⇔ 1989年以降 |'
echo '| 令和 ⇔ 2019年以降 |'
echo '---------------------'
read -p "[ 1:元号→西暦 | 2:西暦→元号 | 3:終了 ] どれを実行しますか?[1/2/3]" choice
do
#--------
if [ "${choice}" -eq 1 ];then
echo '計算する元号年月日を入力してください。'
read -p "元号(1:昭和 2:平成 3:令和):" gengo
read -p "年(1~ ):" year
read -p "月(1~12):" month
read -p "日(1~31):" day
#---------西暦変換
if [ "${gengo}" -eq 3 ];then
seireki=$((2019+"${year}"-1))
#echo '西暦では==>'"${seireki}"
elif [ "${gengo}" -eq 1 ];then
seireki=$((1926+"${year}"-1))
#echo '西暦では==>'"${seireki}"
elif [ "${gengo}" -eq 2 ];then
seireki=$((1989+"${year}"-1))
#echo '西暦では==>'"${seireki}"
else
echo '==> 昭和・平成・令和しか対応しておりません。'
fi
g_change
elif [ "${choice}" -eq 2 ];then
echo '計算する西暦年月日を入力してください'
read -p '年(yyyy) :' seireki
read -p '月 (1-12):' month
read -p '日 (1-31):' day
g_change
elif [ "${choice}" -eq 3 ];then
exit
else
clear
echo "不正な入力です。再度入力してください。"
fi
done
コメント