PostgreSQL小ネタ(西暦・和暦変換 税率変更などにも応用可!)

PostgreSQL database

久しぶりの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)

この手法は例えば消費税率の切り替えなどにも応用できます。お役に立てば幸いです!

コメント