Skip to content

ClickHouse で Date と DateTime をパースする 5 つの方法

mark needham
2026年3月12日 · 8分で読む

日付データには、イベントストリームの Unix タイムスタンプ、レガシーデータベースのエクスポートに見られる独特な数値形式の日付、API から返される ISO 8601 文字列など、実にさまざまな形式が存在します。幸いなことに、ClickHouse にはこれらすべてを処理できる豊富な関数が用意されています。本ブログ記事では、それらの関数の使い方を詳しく見ていきます。

まずは、最も明示的なアプローチから始めます。fromUnixTimestamp による Unix タイムスタンプの変換、YYYYMMDDToDate によるパックされた数値日付のパース、そして parseDateTime による既知のフォーマット文字列のパースです。次に、フォーマットが不明な場合や混在している場合に役立つ parseDateTimeBestEffort ファミリーを紹介します。

最後に、ユースケースによっては明示的な関数呼び出しよりも、cast_string_to_date_time_mode 設定と組み合わせた日付のキャストが適している理由を解説します。

Unix タイムスタンプ

まずは Unix タイムスタンプです。Unix タイムスタンプは 1970年1月1日 からの経過秒数を表します。変換には fromUnixTimestamp 関数を使用します:

SELECT
    fromUnixTimestamp(1704067295) AS val1, toTypeName(val1);

これは DateTime 型を返します。1970年1月1日 からのミリ秒単位の値がある場合は別の関数 fromUnixTimestamp64Milli があり、戻り値の型はミリ秒までの精度を表す 3 を指定した DateTime64(3) になります。

SELECT
    fromUnixTimestamp64Milli(1704067295123) AS val2, toTypeName(val2);

マイクロ秒の場合は、fromUnixTimestamp64Micro が DateTime64(6) を返します:

SELECT
    fromUnixTimestamp64Micro(1704067295123456) AS val3, toTypeName(val3);

数値形式の日付フォーマット

日付が区切り文字やフォーマットなしで、年・月・日をエンコードした単純な数値として表されることがあります。これはレガシーデータベースのエクスポートやメインフレームのフラットファイルでよく見られます。この処理には YYYYMMDDToDate 関数を使います:

SELECT
    YYYYMMDDToDate(20240115) AS val1, toTypeName(val1);

数値に時刻情報も含まれている場合は、YYYYMMDDhhmmssToDateTime で処理できます:

SELECT
    YYYYMMDDhhmmssToDateTime(20240115143022) AS val2, toTypeName(val2);

既知のフォーマット文字列

API は多くの場合、日付を文字列として返します。フォーマットがわかっている場合は、MySQL 形式の日付フォーマット文字列を指定して parseDateTime を使用できます:

SELECT
    parseDateTime('15/01/2024 14:30:22', '%d/%m/%Y %H:%i:%s') AS val1,
    toTypeName(val1);

これはタイムゾーンを含む DateTime を返します。

Joda 形式の日付フォーマット文字列を使いたい場合は parseDateTimeInJodaSyntax も用意されており、同じ出力が得られます:

SELECT
    parseDateTimeInJodaSyntax('15/01/2024 14:30:22', 'dd/MM/yyyy HH:mm:ss') AS val2,
    toTypeName(val2);

DateTime のベストエフォートパース

ここまでの 3 つのアプローチは、すべて正確な日付フォーマットが判明していることを前提としていました。しかし、不明な場合はどうすればよいでしょうか。そこで役立つのが parseDateTimeBestEffort ファミリーの関数です。さまざまなフォーマットが混在する日付を想定してみましょう:

WITH dates AS (
    SELECT '2024-01-15T14:30:22.000Z' AS raw
    UNION ALL
    SELECT '2024-01-15' AS raw
    UNION ALL
    SELECT '1704067295' AS raw
)
SELECT raw, parseDateTimeBestEffort(raw) AS val, toTypeName(val)
FROM dates;

前述の関数と同様に、parseDateTimeBestEffort64 を使用して DateTime64 に変換することもできます:

WITH dates AS (
    SELECT '2024-01-15T14:30:22.000Z' AS raw
    UNION ALL
    SELECT '2024-01-15' AS raw
    UNION ALL
    SELECT '1704067295' AS raw
)
SELECT raw, parseDateTime64BestEffort(raw) AS val, toTypeName(val)
FROM dates;

まったく無効な日付が含まれている場合はどうなるでしょうか。

WITH dates AS (
    SELECT '2024-01-15T14:30:22.000Z' AS raw
    UNION ALL
    SELECT '2024-01-15' AS raw
    UNION ALL
    SELECT '1704067295' AS raw
    UNION ALL
    SELECT 'not a date' AS raw
)
SELECT raw, parseDateTime64BestEffort(raw) AS val, toTypeName(val)
FROM dates;

ClickHouse は例外をスローします。

これは、エラーの代わりに NULL を返すバリアントの parseDateTimeBestEffort64OrNull で回避できます:

WITH dates AS (
    SELECT '2024-01-15T14:30:22.000Z' AS raw
    UNION ALL
    SELECT '2024-01-15' AS raw
    UNION ALL
    SELECT '1704067295' AS raw
    UNION ALL
    SELECT 'not a date' AS raw
)
SELECT raw, parseDateTime64BestEffortOrNull(raw) AS val, toTypeName(val)
FROM dates;

あるいは実際の日時値を取得したい場合は、parseDateTimeBestEffort64OrZero を使用すると 1970年1月1日 午前 0 時にフォールバックします:

WITH dates AS (
    SELECT '2024-01-15T14:30:22.000Z' AS raw
    UNION ALL
    SELECT '2024-01-15' AS raw
    UNION ALL
    SELECT '1704067295' AS raw
    UNION ALL
    SELECT 'not a date' AS raw
)
SELECT raw, parseDateTime64BestEffortOrZero(raw) AS val, toTypeName(val)
FROM dates;

キャスト

クエリ全体で明示的なパース関数を毎回呼び出さずに済ませたい場合は、::DateTime を使用して文字列値を日付型に直接キャストできます。ただし、注意すべき重要な設定として cast_string_to_date_time_mode があります。

デフォルトでは basic に設定されており、YYYY-MM-DD や YYYY-MM-DD HH:MM:SS などの標準的なフォーマットを処理できますが、それ以外の形式は失敗します。より幅広いフォーマットに対応させるには、これを best_effort に変更します。なお、この設定でも完全に無効な日付に対しては例外がスローされます。

この設定は、クエリごとに行内で渡すことができます:

WITH dates AS (
    SELECT '2024-01-15T14:30:22.000Z' AS raw
    UNION ALL
    SELECT '2024-01-15' AS raw
    UNION ALL
    SELECT '1704067295' AS raw
)
SELECT raw, raw::DateTime AS val, toTypeName(val)
FROM dates
SETTINGS cast_string_to_date_time_mode = 'best_effort';

またはセッションレベルで設定しておけば、クエリごとに指定する必要がなくなります:

SET cast_string_to_date_time_mode = 'best_effort';

そうすれば、SETTINGS 句なしでも同じクエリが動作します:

WITH dates AS (
    SELECT '2024-01-15T14:30:22.000Z' AS raw
    UNION ALL
    SELECT '2024-01-15' AS raw
    UNION ALL
    SELECT '1704067295' AS raw
)
SELECT raw, raw::DateTime AS val, toTypeName(val)
FROM dates;

最後に、さまざまな日付が含まれる次のようなファイルを想定してみましょう:

dates.csv

raw
2024-01-15T14:30:22.000Z
2024-01-15
1704067295

同じアプローチを使って、そのファイル内の日付をパースできます:

SELECT raw, raw::DateTime AS val, toTypeName(val)
FROM file('dates.csv', CSVWithNames);
┌─raw──────────────────────┬─────────────────val─┬─toTypeName(val)─┐
│ 2024-01-15T14:30:22.000Z │ 2024-01-15 14:30:22 │ DateTime        │
│ 2024-01-15               │ 2024-01-15 00:00:00 │ DateTime        │
│ 1704067295               │ 2024-01-01 00:01:35 │ DateTime        │
└──────────────────────────┴─────────────────────┴─────────────────┘

今すぐ始める

自社のデータで ClickHouse を試してみませんか?ClickHouse Cloud は数分で使い始めることができ、300 ドル分の無料クレジットも進呈しています。

サインアップ

この記事をシェア

  • Y Combinator icon
  • X icon
  • Bluesky icon
  • Facebook icon
  • LinkedIn icon

Subscribe to our newsletter

Stay informed on feature releases, product roadmap, support, and cloud offerings!

Follow us

XBlueskySlackGithubTelegramMeetupRSS