久しぶりのDBネタです。
まだまだ「和暦表示は必須」という仕様も多いですよね。やり方は色々あると思いますが、なるべく分かりやすい方法で実現したいと思います。
【和暦管理テーブル】
create table warekimaster(
id int not null -- 主キー
,wareki text not null -- 元号
,diff int not null -- 西暦(yyyy)との年数差
,startymd date not null -- その元号はいつから
,endymd date not null -- いつまで
,constraint pk_warekimaster primary key(id));
「西暦のyyyyから和暦との年数差を引く」という考え方でマスタを作ります。diff列(西暦(yyyy)と和暦の年数差)は無くても良いですが、あった方がSQLがスッキリします。
続いてデータ投入です。今回は昭和から令和までを変換対象とします。
insert into warekimaster(id, wareki, diff, startymd, endymd)
values(1, '昭和', 1925, '1926-12-25', '1989-1-7');
insert into warekimaster(id, wareki, diff, startymd, endymd)
values(2, '平成', 1988, '1989-1-8', '2019-4-30');
-- 令和のendymdは適当に入れておく
insert into warekimaster(id, wareki, diff, startymd, endymd)
values(3, '令和', 2018, '2019-5-1', '2099-12-31');
sandambara=> select * from warekimaster order by id;
id | wareki | diff | startymd | endymd
----+--------+------+------------+------------
1 | 昭和 | 1925 | 1926-12-25 | 1989-01-07
2 | 平成 | 1988 | 1989-01-08 | 2019-04-30
3 | 令和 | 2018 | 2019-05-01 | 2099-12-31
(3 rows)
例えば今日の日付を和暦に変換する場合はこうです。
select
wareki || (to_char(now(), 'yyyy')::int - diff)::text || '年' ||
to_char(now(), 'mm') || '月' ||
to_char(now(), 'dd') || '日'
from
warekimaster
where
now() >= startymd and now() <= endymd;
「1年」を「元年」と出力させるのはcaseを使えば良いですし、selectをまるっとfunctionにすればスマートですよね。折角なのでfunctionにしてみましょう!
create or replace function wareki(date) returns text as $$
declare
returnstring text;
begin
select
case
when to_char($1, 'yyyy')::int - diff = 1 then wareki || '元年'
else wareki || (to_char($1, 'yyyy')::int - diff)::text || '年'
end ||
to_char($1, 'mm') || '月' ||
to_char($1, 'dd') || '日'
into
returnstring
from
warekimaster
where
$1 >= startymd and $1 <= endymd;
return returnstring;
end $$ language plpgsql;
では、早速実行してみましょう。
sandambara=> select wareki('2019-06-13');
wareki
------------------
令和元年06月13日
(1 row)
sandambara=> select wareki('2021-06-13');
wareki
-----------------
令和3年06月13日
(1 row)
この手法は例えば消費税率の切り替えなどにも応用できます。お役に立てば幸いです!
コメント