【Oracle】日付を和暦で取得する方法|TO_CHARとNLS_CALENDARで令和・平成変換

Oracleデータベースで日付を和暦(令和・平成・昭和など)で表示するには、TO_CHAR関数NLS_CALENDARパラメータを組み合わせます。帳票出力や官公庁システムなど、和暦表示が必須となる場面は多く、正しい設定方法を知っておくことは実務で非常に重要です。

この記事では、TO_CHARとNLS_CALENDAR=’Japanese Imperial’による基本的な和暦変換から、ALTER SESSIONでの設定元号一覧和暦→西暦変換CASE文による手動変換PL/SQL関数化他RDBMS比較よくあるエラーと対処法実務パターンまで網羅的に解説します。

この記事で学べること

  • TO_CHAR + NLS_CALENDAR による和暦表示の基本
  • 和暦フォーマット要素(EE / E / RR / EEYYなど)の使い分け
  • NLS_DATE_LANGUAGE の設定と影響
  • ALTER SESSION でのNLSパラメータ設定方法
  • 明治〜令和の元号一覧テーブル
  • 和暦→西暦の変換方法
  • CASE文による手動変換テクニック
  • PL/SQL関数化で再利用可能にする方法
  • 他RDBMS比較(SQL Server・MySQL・PostgreSQL)
  • よくあるエラーと対処法
  • 実務パターン(帳票出力・年度計算等)
スポンサーリンク

和暦とは?

和暦とは日本独自の暦法で、西暦を元号(明治・大正・昭和・平成・令和)と組み合わせて表記します。たとえば西暦2025年は令和7年、1989年は平成元年に相当します。

官公庁や金融機関の帳票、契約書、公文書などでは和暦表記が求められることが多く、データベースレベルで正しく変換できることが重要です。

元号 読み 開始日 終了日 略称
明治 めいじ 1868年1月25日 1912年7月29日 M
大正 たいしょう 1912年7月30日 1926年12月24日 T
昭和 しょうわ 1926年12月25日 1989年1月7日 S
平成 へいせい 1989年1月8日 2019年4月30日 H
令和 れいわ 2019年5月1日 (現在) R

TO_CHAR + NLS_CALENDARによる和暦変換の基本

Oracleで和暦表示を行うには、TO_CHAR関数の第3引数にNLS_CALENDAR=’Japanese Imperial’を指定します。これにより、日本の元号に基づいた日付フォーマットが有効になります。

基本構文

構文
TO_CHAR(
  日付値,
  'フォーマット',
  'NLS_CALENDAR=Japanese Imperial'
)

最も基本的な和暦変換

SQL
-- SYSDATEを和暦で表示
SELECT
  TO_CHAR(
    SYSDATE,
    'EEYY"年"MM"月"DD"日"',
    'NLS_CALENDAR=Japanese Imperial'
  ) AS wareki
FROM DUAL;

実行結果

WAREKI
-----------------
令和07年06月15日

EEが元号の正式名称(令和・平成など)、YYが元号内の年数を2桁で表示します。ダブルクォーテーションで囲んだ「年」「月」「日」はリテラル文字としてそのまま出力されます。

和暦フォーマット要素の詳細

TO_CHARで和暦を表示する際に使えるフォーマット要素を確認しましょう。NLS_CALENDARをJapanese Imperialに設定した場合のみ有効になる要素があります。

要素 説明 出力例
EE 元号の正式名称(漢字) 令和
E 元号の略称(アルファベット1文字) R
YY 元号内の年数(2桁ゼロ埋め) 07
Y 元号内の年数(ゼロ埋めなし) 7
MM 月(2桁ゼロ埋め) 06
DD 日(2桁ゼロ埋め) 15
“文字列” リテラル文字(そのまま出力) 年、月、日

さまざまなフォーマットパターン

SQL
SELECT
  -- 正式表記: 令和07年06月15日
  TO_CHAR(SYSDATE, 'EEYY"年"MM"月"DD"日"',
    'NLS_CALENDAR=Japanese Imperial') AS full_wareki,
  -- 略称表記: R07/06/15
  TO_CHAR(SYSDATE, 'EYY/MM/DD',
    'NLS_CALENDAR=Japanese Imperial') AS short_wareki,
  -- 略称+年付き: R07.06.15
  TO_CHAR(SYSDATE, 'EYY.MM.DD',
    'NLS_CALENDAR=Japanese Imperial') AS dot_wareki,
  -- 元号と年のみ: 令和07年
  TO_CHAR(SYSDATE, 'EEYY"年"',
    'NLS_CALENDAR=Japanese Imperial') AS year_only
FROM DUAL;

実行結果

FULL_WAREKI        SHORT_WAREKI  DOT_WAREKI  YEAR_ONLY
-----------------  ------------  ----------  ---------
令和07年06月15日   R07/06/15     R07.06.15   令和07年

注意:NLS_CALENDARを指定しない場合、EEやEフォーマットは西暦のまま「AD」等が出力されます。必ずNLS_CALENDAR=Japanese Imperialをセットで使いましょう。

NLS_DATE_LANGUAGEの設定

NLS_DATE_LANGUAGEは日付の言語設定を制御するパラメータです。和暦表示で元号を日本語(漢字)で出力するには、NLS_DATE_LANGUAGEをJAPANESEに設定する必要があります。

SQL
-- NLS_DATE_LANGUAGEによる出力の違い
SELECT
  -- JAPANESE: 令和07年06月15日
  TO_CHAR(SYSDATE, 'EEYY"年"MM"月"DD"日"',
    'NLS_CALENDAR=Japanese Imperial NLS_DATE_LANGUAGE=JAPANESE'
  ) AS jp_wareki,
  -- ENGLISH: Reiwa 07/06/15
  TO_CHAR(SYSDATE, 'EE YY/MM/DD',
    'NLS_CALENDAR=Japanese Imperial NLS_DATE_LANGUAGE=ENGLISH'
  ) AS en_wareki
FROM DUAL;

実行結果

JP_WAREKI           EN_WAREKI
------------------  ----------------
令和07年06月15日    Reiwa 07/06/15

NLS_DATE_LANGUAGEがJAPANESEの場合は元号が漢字(令和)で、ENGLISHの場合は英語(Reiwa)で出力されます。デフォルトのセッション言語設定によって変わるため、確実に日本語で出力したい場合は明示的にJAPANESEを指定しましょう。

NLS_DATE_LANGUAGE EE出力 E出力
JAPANESE 令和 R
ENGLISH Reiwa R
AMERICAN Reiwa R

ALTER SESSIONでの設定方法

毎回TO_CHARの第3引数にNLSパラメータを指定するのが面倒な場合は、ALTER SESSIONでセッション全体のカレンダーを変更できます。一度設定すれば、そのセッション内のすべてのTO_CHAR呼び出しで和暦が使われます。

セッション設定の変更

SQL
-- セッションのカレンダーを和暦に変更
ALTER SESSION SET NLS_CALENDAR = 'Japanese Imperial';
ALTER SESSION SET NLS_DATE_LANGUAGE = 'JAPANESE';

-- 以降、NLSパラメータ指定なしで和暦が使える
SELECT
  TO_CHAR(SYSDATE, 'EEYY"年"MM"月"DD"日"') AS wareki
FROM DUAL;

実行結果

WAREKI
-----------------
令和07年06月15日

現在のNLS設定を確認する

SQL
-- セッションのNLSパラメータを確認
SELECT parameter, value
FROM NLS_SESSION_PARAMETERS
WHERE parameter IN (
  'NLS_CALENDAR',
  'NLS_DATE_LANGUAGE',
  'NLS_DATE_FORMAT'
);

実行結果

PARAMETER             VALUE
--------------------  --------------------
NLS_CALENDAR          Japanese Imperial
NLS_DATE_LANGUAGE     JAPANESE
NLS_DATE_FORMAT       RR/MM/DD

元に戻す(西暦に戻す)

SQL
-- セッションを西暦(グレゴリオ暦)に戻す
ALTER SESSION SET NLS_CALENDAR = 'Gregorian';

注意:ALTER SESSIONの設定はそのセッション内でのみ有効です。新しい接続を確立すると、データベースのデフォルト設定に戻ります。永続的に変更したい場合はデータベースレベルまたは初期化パラメータで設定する必要があります。

特定の日付を和暦に変換する

SYSDATEだけでなく、任意の日付を和暦に変換するケースも多くあります。TO_DATEで作成した日付値にTO_CHARを適用します。

SQL
-- さまざまな時代の日付を和暦で表示
SELECT
  TO_CHAR(TO_DATE('2025-06-15', 'YYYY-MM-DD'),
    'EEYY"年"MM"月"DD"日"',
    'NLS_CALENDAR=Japanese Imperial') AS reiwa,
  TO_CHAR(TO_DATE('2015-04-01', 'YYYY-MM-DD'),
    'EEYY"年"MM"月"DD"日"',
    'NLS_CALENDAR=Japanese Imperial') AS heisei,
  TO_CHAR(TO_DATE('1985-03-20', 'YYYY-MM-DD'),
    'EEYY"年"MM"月"DD"日"',
    'NLS_CALENDAR=Japanese Imperial') AS showa
FROM DUAL;

実行結果

REIWA              HEISEI             SHOWA
-----------------  -----------------  -----------------
令和07年06月15日   平成27年04月01日   昭和60年03月20日

テーブルの日付列を和暦で表示する

SQL
-- 社員テーブルの入社日を和暦で表示
SELECT
  emp_name,
  hire_date,
  TO_CHAR(hire_date,
    'EEYY"年"MM"月"DD"日"',
    'NLS_CALENDAR=Japanese Imperial'
  ) AS hire_date_wareki
FROM employees
ORDER BY hire_date;

実行結果

EMP_NAME    HIRE_DATE    HIRE_DATE_WAREKI
----------  -----------  -----------------
田中太郎    2018-04-01   平成30年04月01日
鈴木花子    2020-04-01   令和02年04月01日
佐藤一郎    2023-10-15   令和05年10月15日

和暦→西暦変換

和暦文字列を西暦の日付に変換する場合は、TO_DATE関数にNLS_CALENDARパラメータを指定します。

SQL
-- 和暦文字列を西暦DATEに変換
SELECT
  TO_DATE(
    '令和07年06月15日',
    'EEYY"年"MM"月"DD"日"',
    'NLS_CALENDAR=Japanese Imperial NLS_DATE_LANGUAGE=JAPANESE'
  ) AS seireki_date
FROM DUAL;

実行結果

SEIREKI_DATE
------------
2025-06-15

略称からの変換

SQL
-- 略称形式(R07/06/15)から西暦に変換
SELECT
  TO_DATE(
    'R07/06/15',
    'EYY/MM/DD',
    'NLS_CALENDAR=Japanese Imperial'
  ) AS seireki_date
FROM DUAL;

実行結果

SEIREKI_DATE
------------
2025-06-15

ポイント:TO_DATEとTO_CHARで同じフォーマット文字列とNLSパラメータを指定すれば、和暦→西暦→和暦の相互変換が正確に行えます。

CASE文による手動変換方法

NLS_CALENDARが使えない環境や、独自のフォーマットで和暦を出力したい場合は、CASE文を使って手動で元号を判定・変換できます。

西暦→和暦の手動変換

SQL
-- CASE文で元号を判定して和暦を組み立てる
SELECT
  hire_date,
  CASE
    WHEN hire_date >= TO_DATE('2019-05-01', 'YYYY-MM-DD')
      THEN '令和' || LPAD(EXTRACT(YEAR FROM hire_date) - 2018, 2, '0')
    WHEN hire_date >= TO_DATE('1989-01-08', 'YYYY-MM-DD')
      THEN '平成' || LPAD(EXTRACT(YEAR FROM hire_date) - 1988, 2, '0')
    WHEN hire_date >= TO_DATE('1926-12-25', 'YYYY-MM-DD')
      THEN '昭和' || LPAD(EXTRACT(YEAR FROM hire_date) - 1925, 2, '0')
    WHEN hire_date >= TO_DATE('1912-07-30', 'YYYY-MM-DD')
      THEN '大正' || LPAD(EXTRACT(YEAR FROM hire_date) - 1911, 2, '0')
    WHEN hire_date >= TO_DATE('1868-01-25', 'YYYY-MM-DD')
      THEN '明治' || LPAD(EXTRACT(YEAR FROM hire_date) - 1867, 2, '0')
    ELSE '対象外'
  END
  || '年'
  || TO_CHAR(hire_date, 'MM"月"DD"日"') AS wareki_manual
FROM employees;

実行結果

HIRE_DATE    WAREKI_MANUAL
-----------  ------------------
2023-10-15   令和05年10月15日
2015-04-01   平成27年04月01日
1985-03-20   昭和60年03月20日

元年表記への対応

日本の慣習では、各元号の最初の年を「元年」と表記します。CASE文を使えばこの対応も可能です。

SQL
-- 元年表記に対応した和暦変換
SELECT
  CASE
    WHEN hire_date >= TO_DATE('2019-05-01', 'YYYY-MM-DD') THEN
      '令和' ||
      CASE WHEN EXTRACT(YEAR FROM hire_date) = 2019
        THEN '元'
        ELSE TO_CHAR(EXTRACT(YEAR FROM hire_date) - 2018)
      END
    WHEN hire_date >= TO_DATE('1989-01-08', 'YYYY-MM-DD') THEN
      '平成' ||
      CASE WHEN EXTRACT(YEAR FROM hire_date) = 1989
        THEN '元'
        ELSE TO_CHAR(EXTRACT(YEAR FROM hire_date) - 1988)
      END
    ELSE 'その他'
  END
  || '年'
  || TO_CHAR(hire_date, 'MM"月"DD"日"') AS wareki_gannen
FROM employees;

実行結果

WAREKI_GANNEN
------------------
令和元年06月15日    ← 2019年の場合
令和05年10月15日    ← 2023年の場合

PL/SQL関数で和暦変換を再利用可能にする

和暦変換のロジックをPL/SQL関数にまとめておけば、SQL文やアプリケーションから簡単に呼び出せます。元年対応やNULLチェックも組み込んだ実用的な関数を紹介します。

PL/SQL
CREATE OR REPLACE FUNCTION to_wareki(
  p_date IN DATE
) RETURN VARCHAR2
IS
  v_year   NUMBER;
  v_era    VARCHAR2(10);
  v_offset NUMBER;
  v_era_yr NUMBER;
BEGIN
  -- NULL チェック
  IF p_date IS NULL THEN
    RETURN NULL;
  END IF;

  v_year := EXTRACT(YEAR FROM p_date);

  -- 元号と基準年を判定
  IF p_date >= TO_DATE('2019-05-01', 'YYYY-MM-DD') THEN
    v_era := '令和'; v_offset := 2018;
  ELSIF p_date >= TO_DATE('1989-01-08', 'YYYY-MM-DD') THEN
    v_era := '平成'; v_offset := 1988;
  ELSIF p_date >= TO_DATE('1926-12-25', 'YYYY-MM-DD') THEN
    v_era := '昭和'; v_offset := 1925;
  ELSIF p_date >= TO_DATE('1912-07-30', 'YYYY-MM-DD') THEN
    v_era := '大正'; v_offset := 1911;
  ELSIF p_date >= TO_DATE('1868-01-25', 'YYYY-MM-DD') THEN
    v_era := '明治'; v_offset := 1867;
  ELSE
    RETURN '対象外';
  END IF;

  v_era_yr := v_year - v_offset;

  -- 元年対応
  IF v_era_yr = 1 THEN
    RETURN v_era || '元年'
      || TO_CHAR(p_date, 'MM"月"DD"日"');
  ELSE
    RETURN v_era
      || LPAD(v_era_yr, 2, '0') || '年'
      || TO_CHAR(p_date, 'MM"月"DD"日"');
  END IF;
END;
/

関数の使用例

SQL
-- 関数を使って和暦変換
SELECT
  to_wareki(SYSDATE) AS today_wareki,
  to_wareki(TO_DATE('2019-05-01', 'YYYY-MM-DD')) AS reiwa_first,
  to_wareki(TO_DATE('1989-01-08', 'YYYY-MM-DD')) AS heisei_first
FROM DUAL;

実行結果

TODAY_WAREKI       REIWA_FIRST      HEISEI_FIRST
-----------------  ---------------  ----------------
令和07年06月15日   令和元年05月01日  平成元年01月08日

ポイント:PL/SQL関数にしておけば、将来新しい元号が追加された場合も関数内のIF文を1か所修正するだけで対応できます。保守性が大幅に向上します。

他RDBMSとの和暦変換比較

和暦変換の方法はRDBMSによって異なります。主要なRDBMSでの和暦対応状況を比較します。

RDBMS 和暦対応 方法
Oracle ネイティブ対応 TO_CHAR + NLS_CALENDAR='Japanese Imperial'
SQL Server ネイティブ対応 FORMAT(date, 'ggy年M月d日', 'ja-JP')
PostgreSQL 非対応 独自関数の作成が必要
MySQL 非対応 独自関数の作成が必要

SQL Serverでの和暦変換

SQL Server
-- SQL Server: FORMAT関数で和暦
SELECT
  FORMAT(GETDATE(), 'ggy年M月d日', 'ja-JP') AS wareki;
-- 出力例: 令和7年6月15日

-- SQL Server: 略称表記
SELECT
  FORMAT(GETDATE(), 'gy/MM/dd', 'ja-JP') AS wareki_short;
-- 出力例: R7/06/15

SQL ServerではFORMAT関数の第3引数にカルチャja-JPを指定するだけで和暦が使えます。Oracleと違ってALTER SESSIONは不要で、より直感的に記述できます。

Oracle vs SQL Server フォーマット対応表

表示内容 Oracle SQL Server
元号(正式) EE → 令和 gg → 令和
元号(略称) E → R g → R
年(2桁) YY → 07 yy → 07
NLSパラメータ NLS_CALENDAR ja-JPカルチャ

よくあるエラーと対処法

和暦変換で遭遇しやすいエラーとその対処法をまとめます。

ORA-01821: 日付書式が無効です

項目 内容
エラー ORA-01821: 日付書式が無効です
原因 NLS_CALENDARを指定せずにEE/Eフォーマットを使用した
対処 TO_CHARの第3引数にNLS_CALENDAR=Japanese Imperialを追加する
エラーになるSQL
-- NG: NLS_CALENDARなしでEEを使用
SELECT TO_CHAR(SYSDATE, 'EEYY"年"MM"月"DD"日"') FROM DUAL;
-- → ORA-01821

-- OK: NLS_CALENDARを指定
SELECT TO_CHAR(SYSDATE, 'EEYY"年"MM"月"DD"日"',
  'NLS_CALENDAR=Japanese Imperial') FROM DUAL;

ORA-01898: リテラルが長すぎます

項目 内容
エラー ORA-01898: リテラルが長すぎます
原因 フォーマット文字列内のリテラル(ダブルクォート部分)が長すぎる
対処 リテラル部分を短くするか、複数のTO_CHARを連結(||)する

元号が英語で表示される

項目 内容
症状 「令和」ではなく「Reiwa」と表示される
原因 NLS_DATE_LANGUAGEがENGLISHまたはAMERICANに設定されている
対処 NLS_DATE_LANGUAGE=JAPANESEを明示的に指定する
SQL
-- 日本語で元号を表示するにはNLS_DATE_LANGUAGEを指定
SELECT TO_CHAR(SYSDATE, 'EEYY"年"MM"月"DD"日"',
  'NLS_CALENDAR=Japanese Imperial NLS_DATE_LANGUAGE=JAPANESE'
) FROM DUAL;

明治以前の日付でエラーが発生する

注意:OracleのJapanese Imperialカレンダーは明治(1868年)以降の日付のみ対応しています。それ以前の日付を和暦変換しようとするとエラーが発生します。明治以前の日付はCASE文による手動変換で対応するか、西暦のまま扱いましょう。

実務パターン

実際のシステム開発で和暦が必要となる代表的なパターンを紹介します。

帳票出力での和暦表示

帳票やレポートで和暦を使用する場合のSQLパターンです。

SQL
-- 帳票ヘッダー用の日付(和暦フル表記)
SELECT
  '発行日:' ||
  TO_CHAR(SYSDATE, 'EEYY"年"MM"月"DD"日"',
    'NLS_CALENDAR=Japanese Imperial'
  ) AS issue_date,
  '作成者:管理部' AS author
FROM DUAL;

実行結果

ISSUE_DATE                AUTHOR
------------------------  -----------
発行日:令和07年06月15日  作成者:管理部

年度計算(和暦ベース)

日本の会計年度(4月始まり)を和暦で表示するパターンです。

SQL
-- 年度(4月始まり)を和暦で取得
SELECT
  TO_CHAR(
    ADD_MONTHS(SYSDATE, -3),
    'EEYY',
    'NLS_CALENDAR=Japanese Imperial'
  ) || '年度' AS fiscal_year_wareki
FROM DUAL;

実行結果

FISCAL_YEAR_WAREKI
------------------
令和07年度

ADD_MONTHS(SYSDATE, -3)で3か月前の日付を基準にすることで、4月〜翌3月を同一年度として扱えます。

契約書の日付範囲を和暦で表示

SQL
-- 契約期間を和暦で表示
SELECT
  contract_id,
  TO_CHAR(start_date,
    'EEYY"年"MM"月"DD"日"',
    'NLS_CALENDAR=Japanese Imperial'
  ) || ' 〜 ' ||
  TO_CHAR(end_date,
    'EEYY"年"MM"月"DD"日"',
    'NLS_CALENDAR=Japanese Imperial'
  ) AS contract_period
FROM contracts;

実行結果

CONTRACT_ID  CONTRACT_PERIOD
-----------  ----------------------------------------
1001         令和05年04月01日 〜 令和08年03月31日
1002         平成30年10月01日 〜 令和03年09月30日

元号をまたぐ期間の処理

平成から令和にまたがるデータを扱う場合の注意点です。

SQL
-- 元号の境界日付を確認
SELECT
  TO_CHAR(TO_DATE('2019-04-30', 'YYYY-MM-DD'),
    'EEYY"年"MM"月"DD"日"',
    'NLS_CALENDAR=Japanese Imperial') AS heisei_last,
  TO_CHAR(TO_DATE('2019-05-01', 'YYYY-MM-DD'),
    'EEYY"年"MM"月"DD"日"',
    'NLS_CALENDAR=Japanese Imperial') AS reiwa_first
FROM DUAL;

実行結果

HEISEI_LAST        REIWA_FIRST
-----------------  -----------------
平成31年04月30日   令和01年05月01日

注意:元号をまたぐ期間の日数計算比較は、必ず西暦(DATE型)ベースで行いましょう。和暦文字列同士の比較は正しくソートできません。和暦はあくまで表示用として使い、内部処理は西暦で行うのが鉄則です。

VIEWでの和暦活用

頻繁に和暦表示が必要なテーブルには、VIEWを作成しておくと便利です。

SQL
-- 和暦付きの社員VIEW
CREATE OR REPLACE VIEW v_employees_wareki AS
SELECT
  emp_id,
  emp_name,
  hire_date,
  TO_CHAR(hire_date,
    'EEYY"年"MM"月"DD"日"',
    'NLS_CALENDAR=Japanese Imperial'
  ) AS hire_date_wareki,
  birth_date,
  TO_CHAR(birth_date,
    'EEYY"年"MM"月"DD"日"',
    'NLS_CALENDAR=Japanese Imperial'
  ) AS birth_date_wareki
FROM employees;

-- VIEWを使って和暦で検索
SELECT emp_name, hire_date_wareki
FROM v_employees_wareki
WHERE hire_date >= TO_DATE('2019-05-01', 'YYYY-MM-DD');

実行結果

EMP_NAME    HIRE_DATE_WAREKI
----------  -----------------
鈴木花子    令和02年04月01日
佐藤一郎    令和05年10月15日

まとめ

Oracleで日付を和暦で取得する方法を体系的に解説しました。最後に重要なポイントを整理します。

方法 用途 特徴
TO_CHAR + NLS_CALENDAR 標準的な和暦変換 最も簡潔、Oracle標準
ALTER SESSION セッション全体で和暦を使用 毎回NLSパラメータ指定不要
CASE文による手動変換 カスタムフォーマット・元年対応 柔軟性が高い
PL/SQL関数 再利用可能な和暦変換 保守性が高い
VIEW 和暦列の定常的な利用 アプリ側の修正不要

実務で押さえておくべきポイント

  • TO_CHAR + NLS_CALENDARが最も簡潔な和暦変換方法
  • 元号を日本語で表示するにはNLS_DATE_LANGUAGE=JAPANESEを指定する
  • 元年対応が必要な場合はCASE文またはPL/SQL関数を使う
  • 日付の比較・計算は必ず西暦(DATE型)で行い、和暦は表示用に限定する
  • 頻繁に使うテーブルはVIEWで和暦列を用意すると便利
  • 他RDBMSへの移行時は和暦変換方法の違いに注意する