はじめに
Pythonのkivyを使って西暦・和暦・年齢・干支の変換をする電卓を作ってみた。西暦、和暦または、年齢を指定して値を入力すると変換した値を出力する。活躍する場はそれほどないけど、あると少し便利な電卓。
目次
kivyで使ったウィジェット
今回kivyで使ったウィジェットは Button
、Spinner
、TextInput
。Spinnerは、和暦の明治、大正、昭和、平成、令和を選択する際に使った。kivyについては(記事:PythonのGUIライブラリKivyを使う)を参照。
変換式
今回作った、Pythonコードの補足説明をする。
西暦⇔和暦変換
-
西暦→和暦
和暦それぞれの元年の西暦の明治(1868年)、大正(1912年)、昭和(1926年)、平成(1989年)、令和(2019年)を辞書型の変換テーブルにしてあげれば、西暦から和暦の変換ができる。変換時の注意点として、和暦は1オリジンなので+1することを忘れずに。
def selreki_to_wareki(self, seireki):
# 明治、大正、昭和、平成、令和それぞれの元年の西暦
wareki_dic ={'明治(年)':1868,'大正(年)':1912,'昭和(年)':1926,'平成(年)':1989,'令和(年)':2019}
if wareki_dic['令和(年)'] <= int(seireki):
self.root.ids.spn_wareki.text = '令和(年)'
return str(int(seireki) - wareki_dic['令和(年)']+1)
elif wareki_dic['平成(年)'] <= int(seireki):
self.root.ids.spn_wareki.text = '平成(年)'
return str(int(seireki) - wareki_dic['平成(年)']+1)
elif wareki_dic['昭和(年)'] <= int(seireki):
self.root.ids.spn_wareki.text = '昭和(年)'
return str(int(seireki) - wareki_dic['昭和(年)']+1)
elif wareki_dic['大正(年)'] <= int(seireki):
self.root.ids.spn_wareki.text = '大正(年)'
return str(int(seireki) - wareki_dic['大正(年)']+1)
else:
self.root.ids.spn_wareki.text = '明治(年)'
return str(int(seireki) - wareki_dic['明治(年)']+1)
-
和暦→西暦
同じく、変換テーブルを使えば変換できる。和暦は1オリジンなので-1することを忘れずに。
def wareki_to_seireki(self, wareki):
# 明治、大正、昭和、平成、令和それぞれの元年の西暦
wareki_dic ={'明治(年)':1868,'大正(年)':1912,'昭和(年)':1926,'平成(年)':1989,'令和(年)':2019,'和暦(年)':2019}
return str(int(wareki) + wareki_dic[self.root.ids.spn_wareki.text]-1)
西暦⇔年齢変換
-
西暦→年齢
現在の西暦から指定した西暦を引けばよい。
def seireki_to_toshi(self, seireki):
# 現在の西暦は datetime.now().year で出力
return str(datetime.now().year - int(seireki))
-
年齢→西暦
現在の西暦から、年齢を引けばよい。
def toshi_to_seireki(self, toshi):
# 現在の西暦は datetime.now().year で出力
return str(datetime.now().year - int(toshi))
西暦→干支変換
干支は12なので西暦を12の剰余演算すれば干支を計算できる。2023年は'卯(うさぎ)年'で、2023の剰余演算は、2023%12=7。'卯(うさぎ)'=7を基準に12干を辞書型の変換テーブルにしてあげれば、西暦から干支の変換ができる。
def serireki_to_eto(self, seireki):
# 12の剰余演算 2023%12=7 2023年は卯で7
eto_dic ={7:'卯(う)',8:'辰(たつ)',9:'巳(み)',10:'午(うま)',11:'未(ひつじ)',0:'申(さる)',1:'酉(とり)',2:'戌(いぬ)',3:'亥(い)',4:'子(ね)',5:'丑(うし)',6:'寅(とら)'}
return eto_dic[int(seireki)%12]
作成したコード
西暦、和暦または、年齢を指定して値を入力。決定ボタンで変換する。干支は12年周期で一意に変換できないので、干支を指定した場合は西暦を入れる形にしている。kivyで作ったので、Androidアプリ化も可能( 記事:PythonでAndroidアプリを作る。)。
seiwa_calc.py
from kivy.app import App
from kivy.lang import Builder
import japanize_kivy # https://github.com/momijiame/japanize-kivy 日本語化
from datetime import datetime
#kivy GUI
Layout = Builder.load_string('''
#計算ボタン
CalBox:
GridLayout:
cols:2
size_hint_y:0.2
SetBtn:
id:btn_seireki
text:'西暦(年)'
background_color:(0,0.5,0,1)
CalTxt:
id:txt_seireki
text:''
GridLayout:
cols:2
size_hint_y:0.2
SetSpn:
id:spn_wareki
text:'和暦(年)'
CalTxt:
id:txt_wareki
text:''
GridLayout:
cols:2
size_hint_y:0.2
SetBtn:
id:btn_toshi
text:'年齢(歳)'
CalTxt:
id:txt_toshi
text:''
GridLayout:
cols:2
size_hint_y:0.2
SetBtn:
id:btn_eto
text:'干支'
CalTxt:
id:txt_eto
text:''
GridLayout:
size_hint_y:0.6
cols:3
#------------------------
NumBtn:
id:btn_7
text:'7'
NumBtn:
id:btn_8
text:'8'
NumBtn:
id:btn_9
text:'9'
#------------------------
NumBtn:
id:btn_4
text:'4'
NumBtn:
id:btn_5
text:'5'
NumBtn:
id:btn_6
text:'6'
#------------------------
NumBtn:
id:btn_1
text:'1'
NumBtn:
id:btn_2
text:'2'
NumBtn:
id:btn_3
text:'3'
#------------------------
SymBtn:
id:btn_clear
text:'クリア'
NumBtn:
id:btn_0
text:'0'
SymBtn:
id:btn_ent
text:'決定'
#部品=================================
<CalBox@BoxLayout>:
#背景色
canvas.before:
Color:
rgb:(0,0,0,0) #背景色なし
Rectangle:
size: self.size
pos: self.pos
orientation:'vertical'
<CalTxt@TextInput>:
size_hint_x:0.7
font_size:30
<SetBtn@Button>:
size_hint_x:0.3
font_size:30
background_color:(0,1,0,1)
on_press:app.btn_on('Settype', self.text)
<SetSpn@Spinner>:
size_hint_x:0.3
font_size:30
background_color:(0,1,0,1)
values:'明治(年)','大正(年)','昭和(年)','平成(年)','令和(年)'
on_press:app.btn_on('Settype', self.text)
<NumBtn@Button>:
font_size:30
background_color:(0,1,0,1)
on_press:app.btn_on('Number', self.text)
<SymBtn@Button>:
font_size:30
background_color:(0,1,0,1)
on_press:app.btn_on('Symbol', self.text)
''')
#--------------------
# 計算アプリ
#--------------------
class Calc_app(App):
#Global
settype='西暦(年)'
#----------------------
# Kivy初期化
#----------------------
def build(self):
self.title = 'Calc_app'
return Layout
#----------------------
# Kivy終了
#----------------------
def on_stop(self):
pass
#----------------------
# btn_on()
#----------------------
def btn_on(self,btn_type, btn_id):
# 西暦/和暦/年齢/(干支:無効)
if btn_type == 'Settype':
self.calc_clear()
if btn_id == '西暦(年)':
self.settype = '西暦(年)'
self.root.ids.btn_seireki.background_color=(0,0.5,0,1)
elif btn_id == '和暦(年)' or btn_id in self.root.ids.spn_wareki.values:
self.settype = '和暦(年)'
self.root.ids.spn_wareki.background_color=(0,0.5,0,1)
elif btn_id == '年齢(歳)':
self.settype = '年齢(歳)'
self.root.ids.btn_toshi.background_color=(0,0.5,0,1)
elif btn_id == '干支':
self.settype = '西暦(年)'
self.root.ids.btn_seireki.background_color=(0,0.5,0,1)
# 0~9
elif btn_type == 'Number':
if self.settype == '西暦(年)':
self.root.ids.txt_seireki.text += btn_id
elif self.settype == '和暦(年)':
self.root.ids.txt_wareki.text += btn_id
elif self.settype == '年齢(歳)':
self.root.ids.txt_toshi.text += btn_id
else:
pass
# 決定/クリア
if btn_type == 'Symbol':
if btn_id == '決定':
if self.settype == '西暦(年)'and self.root.ids.txt_seireki.text.isdecimal():
self.root.ids.txt_wareki.text = self.selreki_to_wareki(self.root.ids.txt_seireki.text)
self.root.ids.txt_toshi.text = self.seireki_to_toshi(self.root.ids.txt_seireki.text)
self.root.ids.txt_eto.text = self.serireki_to_eto(self.root.ids.txt_seireki.text)
elif self.settype == '和暦(年)'and self.root.ids.txt_wareki.text.isdecimal():
self.root.ids.txt_seireki.text = self.wareki_to_seireki(self.root.ids.txt_wareki.text)
self.root.ids.txt_wareki.text = self.selreki_to_wareki(self.root.ids.txt_seireki.text)
self.root.ids.txt_toshi.text = self.seireki_to_toshi(self.root.ids.txt_seireki.text)
self.root.ids.txt_eto.text = self.serireki_to_eto(self.root.ids.txt_seireki.text)
elif self.settype == '年齢(歳)'and self.root.ids.txt_toshi.text.isdecimal():
self.root.ids.txt_seireki.text = self.toshi_to_seireki(self.root.ids.txt_toshi.text)
self.root.ids.txt_wareki.text = self.selreki_to_wareki(self.root.ids.txt_seireki.text)
self.root.ids.txt_eto.text = self.serireki_to_eto(self.root.ids.txt_seireki.text)
else:
self.calc_clear()
#----------------------
# 西暦→干支計算
#----------------------
def serireki_to_eto(self, seireki):
# 12の剰余演算 2023%12=7 2023年は卯で7
eto_dic ={7:'卯(う)',8:'辰(たつ)',9:'巳(み)',10:'午(うま)',11:'未(ひつじ)',0:'申(さる)',1:'酉(とり)',2:'戌(いぬ)',3:'亥(い)',4:'子(ね)',5:'丑(うし)',6:'寅(とら)'}
return eto_dic[int(seireki)%12]
#----------------------
# 西暦→年齢計算
#----------------------
def seireki_to_toshi(self, seireki):
# 現在の西暦は datetime.now().year で出力
return str(datetime.now().year - int(seireki))
#----------------------
# 西暦→和暦計算
#----------------------
def selreki_to_wareki(self, seireki):
# 明治、大正、昭和、平成、令和それぞれの元年の西暦
wareki_dic ={'明治(年)':1868,'大正(年)':1912,'昭和(年)':1926,'平成(年)':1989,'令和(年)':2019}
if wareki_dic['令和(年)'] <= int(seireki):
self.root.ids.spn_wareki.text = '令和(年)'
return str(int(seireki) - wareki_dic['令和(年)']+1)
elif wareki_dic['平成(年)'] <= int(seireki):
self.root.ids.spn_wareki.text = '平成(年)'
return str(int(seireki) - wareki_dic['平成(年)']+1)
elif wareki_dic['昭和(年)'] <= int(seireki):
self.root.ids.spn_wareki.text = '昭和(年)'
return str(int(seireki) - wareki_dic['昭和(年)']+1)
elif wareki_dic['大正(年)'] <= int(seireki):
self.root.ids.spn_wareki.text = '大正(年)'
return str(int(seireki) - wareki_dic['大正(年)']+1)
else:
self.root.ids.spn_wareki.text = '明治(年)'
return str(int(seireki) - wareki_dic['明治(年)']+1)
#----------------------
# 年齢→西暦計算
#----------------------
def toshi_to_seireki(self, toshi):
# 現在の西暦は datetime.now().year で出力
return str(datetime.now().year - int(toshi))
#----------------------
# 和暦→西暦計算
#----------------------
def wareki_to_seireki(self, wareki):
# 明治、大正、昭和、平成、令和それぞれの元年の西暦
wareki_dic ={'明治(年)':1868,'大正(年)':1912,'昭和(年)':1926,'平成(年)':1989,'令和(年)':2019,'和暦(年)':2019}
return str(int(wareki) + wareki_dic[self.root.ids.spn_wareki.text]-1)
#----------------------
# 値クリア
#----------------------
def calc_clear(self):
self.root.ids.txt_seireki.text = ''
self.root.ids.txt_wareki.text = ''
self.root.ids.txt_toshi.text = ''
self.root.ids.txt_eto.text = ''
self.root.ids.spn_wareki.text = '和暦(年)'
self.root.ids.btn_seireki.background_color=(0,1,0,1)
self.root.ids.spn_wareki.background_color=(0,1,0,1)
self.root.ids.btn_toshi.background_color=(0,1,0,1)
if __name__ == '__main__':
Calc_app().run()
以上