Oracle Database に 新しい元号(年号)「野球」を追加してみる。(NLSカレンダ・ユーティリティlxegen) ※2019/4/1追記：新元号「令和」の設定方法を追記

# 元号「野球」を Oracle Database に設定
![yakyu_gengo.jpg](https://qiita-image-store.s3.amazonaws.com/0/110066/e324b29e-fe5f-f0bc-2201-43a9b33ccba2.jpeg)
時代は野球や！彡(ﾟ)(ﾟ) Oracle Database の NLSカレンダ・ユーティリティで
新しい元号(年号)「野球」を追加してみるやで。マニュアルは下記の通り。

> Oracle Databaseグローバリゼーション・サポート・ガイド
> 12cリリース1 (12.1) B71319-05
> 12 ロケール・データのカスタマイズ
> NLSカレンダ・ユーティリティを使用したカレンダのカスタマイズ
> https://docs.oracle.com/cd/E57425_01/121/NLSPG/ch12custlocale.htm#GUID-8F9C2D9F-C6D0-447D-8780-33D6982D5B2C
> > Oracle Databaseは、複数のカレンダをサポートしています。
> > 場合によっては、その中に、今後の元号の追加が必要なものや、
> > 地域的な要件に合せて、うるう年の日数の増減が必要なものがあります。

まずはサンプルの定義ファイルを見てみるやで。マニュアルは下記の通り。

> https://docs.oracle.com/cd/E57425_01/121/NLSPG/ch12custlocale.htm#GUID-8F9C2D9F-C6D0-447D-8780-33D6982D5B2C
> テキスト定義ファイルの名前とlxegenユーティリティに対する位置は、プラットフォーム依存の値でハードコード化されています。
> UNIXプラットフォームの場合、ファイル名はlxecal.nltで、$ORACLE_HOME/nlsディレクトリにあります。
> テキスト定義ファイルのサンプルは、$ORACLE_HOME/nls/demoディレクトリに含まれています。
> デモ・ファイルのインストール方法の詳細は、『Oracle Database Examplesインストレーション・ガイド』』を参照してください。

Oracle Database Examples Linux x86-64版 の ダウンロード は 下記から。

> ※下記のリンクは 2017/1/12時点のものです。
> Oracle Database 12c Release 1 Examples (12.1.0.2.0) for Linux x86-64
> http://www.oracle.com/technetwork/database/enterprise-edition/downloads/database12c-linux-download-2240591.html?ssSourceSiteId=otnjp

Oracle Database Examplesをダウンロードしてインストールすると、
$ORACLE_HOME/nls/demo配下にサンプルの定義ファイルが展開されます。下記は サンプルlxecal.nlt の抜粋。

```py3
-- ***************************************************************************
-- Here is an example on defining Emperors for a Imperial Calendar
-- ***************************************************************************
--
--      DEFINE calendar
--
--         calendar_name              = "Japanese Imperial"
--
--         DEFINE calendar_era
--            era_full_name           = bebccfc2
--            era_abbr_name           = 53
--            start_date              = "DEC-25-1926 AD"
--            end_date                = "jAN-07-1989 AD"
--         ENDDEFINE calendar_era
--
--         DEFINE calendar_era
--            era_full_name           = cabfc0ae
--            era_abbr_name           = 48
--            start_date              = "JAN-08-1989 AD"
--            end_date                = "DEC-31-2099 AD"
--         ENDDEFINE calendar_era
--
--      ENDDEFINE calendar
--
```

「bebccfc2」はEUC文字コードで「昭和」、「cabfc0ae」は「平成」に対応します。

```sql
SQL> select CONVERT(CHR(TO_NUMBER('bebccfc2', 'xxxxxxxx')), 'AL32UTF8', 'JA16EUC') from dual;

CONVERT(CHR(TO_NUMBE
--------------------
昭和

SQL> select CONVERT(CHR(TO_NUMBER('cabfc0ae', 'xxxxxxxx')), 'AL32UTF8', 'JA16EUC') from dual;

CONVERT(CHR(TO_NUMBE
--------------------
平成
```

「野球」に対応するEUC文字コードは「cceeb5e5」なので、
こいつを lxecal.nlt に記述して、$ORACLE_HOME/nls配下に配置します。
※「野球」のバイトコードの調べ方を別記事に興しました。
http://qiita.com/ora_gonsuke777/items/c410f75f0a7a3dfd1872

```sql
$ pwd
/u01/app/oracle/product/12.1.0/dbhome_1/nls
$ ls -la lxecal.nlt
-rw-r--r-- 1 oracle oinstall 301 Jan 12 11:50 lxecal.nlt
$ cat lxecal.nlt
DEFINE calendar
    calendar_name         = "Japanese Imperial"
    DEFINE calendar_era
        era_full_name     = "cceeb5e5"
        era_abbr_name     = "59"
        start_date        = "JAN-01-2019 AD"
        end_date          = "DEC-31-2200 AD"
    ENDDEFINE calendar_era
ENDDEFINE calendar
```
「lxegen」コマンドを起動すると、「lxecal.nlt」がコンパイルされて
「lxecalji.nlb」と云うバイナリファイルが作成されます。

```py3
$ lxegen

NLS Calendar Utility: Version 12.1.0.2.0 - Production

Copyright (c) Oracle 1994, 2014.  All rights reserved.

CORE    12.1.0.2.0      Beta

$ ls -la lxecal*
-rw-r--r-- 1 oracle oinstall 301 Jan 12 11:50 lxecal.nlt
-rw-r--r-- 1 oracle oinstall 144 Jan 12 14:20 lxecalji.nlb ←コイツ
$
```
いよいよやで…DBをシャットダウン／再起動して、2019年1月1日を取得してみると……

```sql
SQL> SHUTDOWN IMMEDIATE;
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
SQL> STARTUP
ORACLEインスタンスが起動しました。

Total System Global Area 2399141888 bytes
Fixed Size                  2927192 bytes
Variable Size             654312872 bytes
Database Buffers         1728053248 bytes
Redo Buffers               13848576 bytes
データベースがマウントされました。
データベースがオープンされました。
SQL> ALTER SESSION SET NLS_CALENDAR="Japanese Imperial";

セッションが変更されました。

SQL> SELECT SYSDATE+719 FROM DUAL;

SYSDATE+719
---------------------------------------------
野球01年01月01日

SQL>
```

野球元年や！彡(ﾟ)(ﾟ)

# 新元号「令和」を Oracle Database に設定

元号「野球」の夢は潰えた…彡(-)(-)
新元号「令和」の設定方法を書いとくやで彡(ﾟ)(ﾟ)

```sql
-- 新元号「令和」と略称「R」のEUC文字コードを調べる。
SELECT DUMP(CONVERT('令和', 'JA16EUC' , 'AL32UTF8'), 16) FROM DUAL;
SELECT DUMP(CONVERT('R', 'JA16EUC' , 'AL32UTF8'), 16) FROM DUAL;

DUMP(CONVERT('令和','JA1
------------------------
Typ=1 Len=4: ce,e1,cf,c2

DUMP(CONVERT('R
---------------
Typ=1 Len=1: 52
```

```sh
# 定義ファイルlxecal.nlt作成とlxegen実行
cd ${ORACLE_HOME}/nls

vi lxecal.nlt

cat lxecal.nlt

DEFINE calendar
    calendar_name         = "Japanese Imperial"
    DEFINE calendar_era
        era_full_name     = "cee1cfc2"
        era_abbr_name     = "52"
        start_date        = "MAY-01-2019 AD"
        end_date          = "DEC-31-2200 AD"
    ENDDEFINE calendar_era
ENDDEFINE calendar

lxegen

ls -la lxecal*

-rw-r--r--. 1 oracle oinstall 297 Apr  1 11:40 lxecal.nlt
-rw-r--r--. 1 oracle oinstall 144 Apr  1 11:40 lxecalji.nlb
```

```sql
-- 動作確認
SHUTDOWN IMMEDIATE;

Database closed.

STARTUP;

Database mounted.
Database opened.

ALTER SESSION SET NLS_CALENDAR="Japanese Imperial";

Session altered.

SELECT SYSDATE FROM DUAL;

SYSDATE
---------------------------------------------
平成31年04月01日

SELECT SYSDATE+30 FROM DUAL;

SYSDATE+30
---------------------------------------------
令和01年05月01日
```

新元号「令和」の幕開けや！彡(^)(^)

※追記：JA16EUCTILDE(JA16EUC) の「令(0xCEE1)」のマッピング
Oracle Database の Locale Builder（lbuilderユーティリティ）で JA16EUCTILDE(JA16EUC)
の「令(0xCEE1)」が UNICODE のどのコードにマッピングされているか見てみました。

Oracle Database の JA16EUCTILDE(JA16EUC) の「令(0xCEE1)」は
UNICODE の「令(U+4EE4)」にマッピングされていました彡(ﾟ)(ﾟ)
![ja16euctilde.jpg](https://qiita-image-store.s3.amazonaws.com/0/110066/ca265a18-dd7b-3728-d579-161276543761.jpeg)

# My Oracle Supportドキュメント

サポートのドキュメントもご参照下さい。パッチも出てまっせ！彡(ﾟ)(ﾟ)
※My Oracle Support のアカウントが必要です。

 > 日本の元号の変更方法について (ドキュメントID 2416596.1)
 > https://support.oracle.com/epmos/faces/DocumentDisplay?id=2416596.1
 > Patch 28730253：SUPPORT NEW ERA REIWA FOR JAPANESE IMPERIAL CALENDAR
 > https://support.oracle.com/epmos/faces/ui/patch/PatchDetail.jspx?patchId=28730253