元号と西暦を相互に変換するBashスクリプト

1.はじめに

平成23年は西暦何年?頭の中にすぐ変換できない?そうです。東日本大震災が発生した2011年です。これぐらいは覚えていられるとしても、こんな年ばかりではありませんが、私達は、国や都道府県の書類は必ず元号で書かなければならないという場面に何度も出会います。

またある出来事から何年経過した?なんていうことを考えるときは、西暦での引き算が便利です。人の年齢を計算する場合もこれに該当します。

ネットで検索すると、これを頭の中でやる方法が見つかります(西暦の下二桁にある数字を足したり引いたりする方法)が、私には真似できません。覚えていられません。またネット上で変換するサービスも見つかりますが、これもネット環境がない場合には使えません。エクセルなど手元のアプリを立ち上げてやる方法もあるけど、これだけのことでわざわざ重いアプリを立ち上げるのが面倒です。

そこで、bash の勉強がてら、西暦と元号を相互に変換できるスクリプトを作成してみました。

2.全体の構成

  • 元号から変換するのか、西暦から変換するのかを選択できるようにする
  • 西暦から元号に変換するコードを関数にして、コードを少なくする
  • 不正な日付の入力をエラーとする
  • 不正な表示がそのまま表示されるのを防ぐ

3.西暦から元号に変換する関数の定義

元号を西暦に変換する場合も、元号を西暦に変換してからその西暦を元に元号に再変換するやり方ですが、2つ目の工程は西暦から入力する場合にも共通するので、この作業を関数にしました。

入力選択元号西暦
工程1元号から西暦に変換 
工程2西暦を元に元号に再変換西暦を元に元号に変換
工程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

コメント

タイトルとURLをコピーしました