3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PythonAdvent Calendar 2023

Day 18

Kivyで「西暦・和暦・年齢・干支」変換電卓作ってみた。

Last updated at Posted at 2023-12-17

はじめに

Pythonのkivyを使って西暦・和暦・年齢・干支の変換をする電卓を作ってみた。西暦、和暦または、年齢を指定して値を入力すると変換した値を出力する。活躍する場はそれほどないけど、あると少し便利な電卓。

image.png

目次

kivyで使ったウィジェット

今回kivyで使ったウィジェットは ButtonSpinnerTextInput。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()
	

戻る

以上

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?