【Java】createdAtの「At」とは?日時を表す変数名の命名慣習を解説

Java

はじめに

さて今回は、Javaにおける時刻関連の変数名に関する慣習についてまとめたいと思います。

仕事の関連でJavaのソースコードを読んでいた際、慣習的に使われる変数名があることを知ったので、忘れないようにまとめておこうと思った背景です。

例えば、次のような変数名を見かけることがあります。

private Instant createdAt;
private Instant updatedAt;
private Instant deletedAt;

これらはいずれも、末尾に「At」が付いています。しかも、見ていたソースだけでなく、色々なところで使われていたので、これは何やら暗黙の慣習があるのかと思い調べてみると、やはりその通りといったところでした。

また、日時を表す名前には、「At」以外にも「Date」、「Time」、「From」、「Until」、「Duration」、「Timeout」など、よく使われる単語があります。

それぞれの意味を理解せずに使用すると、

  • 日付だけを保持するのか、時刻まで保持するのか分からない
  • タイムゾーンを含む値なのか分からない
  • 開始時刻と終了時刻の範囲が曖昧になる
  • 予定時刻と、実際に処理された時刻を区別できない
  • 開発者間で誤解を招く原因となる

など後々困ったことになりかねないので、正しく理解し、扱えるようになりましょう。

慣習として使われているだけですので、基本的には各々が参画している開発プロジェクトの命名規則に従うことを第一に考えましょう。

その命名規則におさまる範囲でどうするか?といったイメージを持っていただければと思います。

Javaにおける基本的な変数の命名規則

日時の命名を確認する前に、Javaの基本的な命名規則を押さえておきましょう。

Javaのフィールド名や変数名では、先頭を小文字にし、単語の区切りから大文字にするローワーキャメルケースが一般的です。

createdAt
lastLoginAt
paymentDueDate
requestTimeout

OracleのJava命名規則でも、フィールドは小文字から始まる複合語形式とし、内容を推測できる名詞または名詞句を使用することが示されています。

そのため、「created_at」や「CREATED_AT」ではなく、Javaの変数としては「createdAt」と書くのが一般的です。

「At」が表す意味

「At」は、基本的に「ある出来事が発生した特定の時点」を表します。

例えば、「createdAt」は英語の「created at 10:00」のような表現から、作成された時点を意味します。

private Instant createdAt;   // 作成された日時
private Instant updatedAt;   // 更新された日時
private Instant approvedAt;  // 承認された日時

通常、「At」を付けた変数は日付だけではなく、年月日と時刻を含む日時を保持します。そのため、「Instant」、「OffsetDateTime」、「ZonedDateTime」、「LocalDateTime」などと組み合わせて使われます。

「At」を使った代表的な変数名

登録・更新・削除に関する日時

変数名意味
createdAtデータが作成された日時
updatedAtデータが最後に更新された日時
modifiedAtデータが最後に変更された日時
deletedAtデータが削除された日時
restoredAt削除済みデータなどが復元された日時

「updatedAt」と「modifiedAt」は、どちらも「変更された日時」として使われます。同じシステム内で両方を使うと違いが分かりにくいため、どちらか一方へ統一するのがおすすめです。

また、「lastUpdatedAt」という名前も使われますが、「updatedAt」だけでも「最後に更新された日時」を表すことが一般的です。複数種類の更新日時があり、最後の更新であることを強調したい場合に「lastUpdatedAt」を使うとよいでしょう。

認証・アクセスに関する日時

変数名意味
loginAtログインした日時
lastLoginAt最後にログインした日時
logoutAtログアウトした日時
lastAccessedAt最後にアクセスした日時
passwordChangedAtパスワードを変更した日時
verifiedAtメールアドレスや本人確認などが完了した日時
lockedAtアカウントがロックされた日時

履歴を1件ずつ保存するログイン履歴であれば「loginAt」、ユーザー情報に最後のログイン日時だけを保持するのであれば「lastLoginAt」が分かりやすい名前です。

処理・通信に関する日時

変数名意味
requestedAtリクエストを受け付けた日時
receivedAtデータやメッセージを受信した日時
sentAtデータやメッセージを送信した日時
processedAt処理した日時
completedAt処理が完了した日時
failedAt処理が失敗した日時
retriedAt再試行した日時
cancelledAtキャンセルされた日時

イベント駆動システムでは、次の2つを分けることも重要です。

private Instant occurredAt;  // 業務上の出来事が実際に発生した日時
private Instant recordedAt;  // システムへ記録された日時

例えば、店舗で15時に売上が発生し、通信障害のため15時10分にサーバーへ登録された場合、「occurredAt」は15時、「recordedAt」は15時10分になります。

公開・有効期限に関する日時

変数名意味
publishedAt実際に公開された日時
unpublishedAt公開が終了した日時
expiresAt有効期限が切れる予定日時
expiredAt実際に期限切れとして処理された日時
activatedAt有効化された日時
deactivatedAt無効化された日時

特に注意したいのが、「expiresAt」と「expiredAt」の違いです。

private Instant expiresAt;  // この日時になると期限切れになる
private Instant expiredAt;  // 期限切れ処理が実際に行われた

「expiresAt」は将来を含む期限、「expiredAt」は実際に起きた結果を表す名前として使い分けられます。バッチ処理が遅れた場合などは、この2つの値が一致しないことがあります。

システム開発では、「予定している時刻」と「実際に起きた時刻」を区別することが重要です。

予定・設定実績意味
startsAtstartedAt開始予定日時/実際の開始日時
endsAtendedAt終了予定日時/実際の終了日時
expiresAtexpiredAt期限日時/実際に期限切れとなった日時
scheduledForprocessedAt実行予定日時/実際に処理した日時

例えば、バッチ処理を午前2時に開始する予定でも、実際には混雑によって午前2時5分に始まる可能性があります。

なお、「scheduledAt」は「実行予定日時」と「予定を登録した日時」のどちらにも読めるため、注意が必要です。以下のように分けると意味が明確になります。

private Instant scheduledFor; // 処理を実行する予定日時
private Instant scheduledAt;  // 予定を登録した日時

「Date」、「Time」、「DateTime」の使い分け

Date:日付だけを表す

年月日だけが必要で、時刻を持たない値には「Date」を使います。

private LocalDate birthDate;     // 生年月日
private LocalDate deliveryDate;  // 配送日
private LocalDate dueDate;       // 期限日
private LocalDate closingDate;   // 締め日

例えば誕生日は、通常「2026年8月11日」のような日付に意味があり、「2026年8月11日0時0分」という時点を表すものではありません。そのため、「birthAt」や「LocalDateTime birthDate」ではなく、「LocalDate birthDate」が自然です。

Time:時刻だけを表す

日付を含まず、時刻だけを表す場合は「Time」を使います。

private LocalTime openingTime; // 開店時刻
private LocalTime closingTime; // 閉店時刻
private LocalTime cutoffTime;  // 締切時刻

ただし、「createdTime」のような名前は、日時全体なのか時刻だけなのか分かりにくくなる場合があります。特定の時点を表すのであれば「createdAt」、時刻だけであれば「creationTimeOfDay」など、意味が明確な名前を選びます。

DateTime:日付と時刻を明示する

「orderDateTime」のように「DateTime」を付ける名前もあります。ただし、型が「LocalDateTime」であれば、変数名にまで「DateTime」を含めると冗長になることがあります。

private LocalDateTime scheduledDateTime;

この名前自体は間違いではありませんが、予定された時点を表したいのであれば、次の方が業務上の意味を読み取りやすくなります。

private LocalDateTime scheduledFor;

型が表す技術的な情報をそのまま名前にするよりも、「何の日時なのか」を名前で示すことが大切です。

その他よく使われる変数名

期間の開始と終了を表す名前

期間を表す場合は、「start」と「end」、または「from」と「to」などが使われます。

命名例意味
startAt / endAt処理やイベントの開始日時と終了日時
validFrom / validUntil有効期間の開始日時と終了日時
fromDate / toDate検索条件などの日付範囲

ここで注意したいのが、境界を範囲へ含めるかどうかです。

例えば「validFrom」を範囲に含み、「validUntil」を含まないルールであれば、次のような半開区間になります。

validFrom <= target < validUntil

経過時間や時間量を表す名前

「At」は特定の時点を表します。一方、「30分間」「5秒経過」のような時間量には、「Duration」、「Timeout」、「Interval」などを使います。

変数名意味
processingDuration処理にかかった時間
retryInterval再試行の間隔
retentionPeriod保存期間
requestTimeoutリクエストを待つ上限時間
private Duration requestTimeout;
private Duration retryInterval;
private Duration processingDuration;
private Period warrantyPeriod;

「Duration」は秒やナノ秒を基準とする時間量、「Period」は年・月・日を基準とする期間です。

例えば「処理を30秒待つ」は「Duration」が適しています。一方、「保証期間2年」のように暦に基づく期間は「Period」が適しています。

数値で時間を保持するときは単位を名前に含める

時間を「int」や「long」で保持すると、値の単位が分からなくなることがあります。

long timeout = 30;

この「30」が30秒なのか、30ミリ秒なのかは、変数名だけでは判断できません。

なので、数値を使う必要がある場合は、単位を変数名へ含めます。

long timeoutMillis = 30_000;
long elapsedSeconds = 15;
long createdAtEpochMillis = 1_786_377_600_000L;

ただし、Javaでは可能な限り「Duration」や「Instant」を使用した方が、単位の取り違えを防げます。

Duration timeout = Duration.ofSeconds(30);
Instant createdAt = Instant.now();

Tips:変数名とJava型を対応させる

適切な変数名を付けても、型の選択を誤ると日時の意味が曖昧になります

表したいもの主なJava型変数名の例
世界共通の時間軸上の一点InstantcreatedAt、occurredAt
UTCからのオフセットを含む日時OffsetDateTimereceivedAt
地域のタイムゾーンを含む日時ZonedDateTimemeetingStartsAt
タイムゾーンを持たない日付と時刻LocalDateTimeappointmentStartsAt
日付だけLocalDatebirthDate、dueDate
時刻だけLocalTimeopeningTime
秒・ナノ秒ベースの時間量Durationtimeout、elapsedTime
年・月・日ベースの期間PeriodwarrantyPeriod
タイムゾーン識別子ZoneIduserZoneId

Instant

「Instant」は、世界共通の時間軸上の特定の時点を表しますタイムゾーンそのものは保持しません

private Instant createdAt;

作成日時、更新日時、ログ、メッセージの発生日時など、システム内部で一意の時点を記録したい場合の有力な選択肢です。画面へ表示するときに、利用者の`ZoneId`を使って日本時間などへ変換します。

OffsetDateTime

「OffsetDateTime」は、「+09:00」のようなUTCからのオフセットを含む日時です。

private OffsetDateTime receivedAt;

APIでオフセット付きの日時を受け渡す場合や、受信したオフセットも保持したい場合に利用できます。

ZonedDateTime

「ZonedDateTime」は、「Asia/Tokyo」や「America/New_York」のような地域のタイムゾーンを含む日時です。

private ZonedDateTime meetingStartsAt;

地域ごとのタイムゾーンルールを考慮する必要がある会議、交通機関、国際的な予約などに向いています。

LocalDateTime

「LocalDateTime」は日付と時刻を保持しますが、タイムゾーンもUTCオフセットも持ちません

private LocalDateTime appointmentStartsAt;

予約を扱う施設のタイムゾーンが別の項目やシステムの前提によって明確な場合などには利用できます。一方、「LocalDateTime createdAt」だけでは、東京の10時なのかロンドンの10時なのかを判別できません。複数地域で利用するシステムの監査日時やイベント日時では注意が必要です。

命名を決めるときのチェックポイント

日時に関する変数名を決めるときは、次の順番で考えると整理しやすくなります。

あくまでも日時に関連した変数名だけなのでご認識を

また、基本的にはプロジェクトルールを最優先に考えましょう

  1. 特定の時点か、日付だけか、時刻だけか、時間量か
    • 時点:At
    • 日付:Date
    • 時刻:Time
    • 時間量:Duration、Period、Timeoutなど
  2. 何に関する日時なのか
    • 作成:createdAt
    • 支払い完了:paymentCompletedAt
    • 配送予定日:deliveryDate
  3. 予定か実績か
    • 開始予定:startsAt
    • 実際の開始:startedAt
  4. タイムゾーンやオフセットが必要か
    • 世界共通の時点:Instant
    • 地域ルールが必要:ZonedDateTime
    • 日付だけ:LocalDate
  5. 数値なら単位が明確か
    • ミリ秒:timeoutMillis
    • 秒:elapsedSeconds
  6. 期間の境界条件が決まっているか
    • 開始・終了を範囲に含むか、仕様に明記する
  7. プロジェクト内で表現が統一されているか
    • updatedAtとmodifiedAtを混在させない
    • endAtとendsAtを理由なく混在させない

よく使われる変数名の例

表したい内容変数名の例
作成日時createdAt
最終更新日時updatedAt
論理削除日時deletedAt
最終ログイン日時lastLoginAt
実際の開始日時startedAt
実際の完了日時completedAt
開始予定日時startsAt
終了予定日時endsAt
有効期限expiresAt
実際の期限切れ処理日時expiredAt
イベント発生日時occurredAt
システム記録日時recordedAt
生年月日birthDate
配送予定日deliveryDate
開店時刻openingTime
処理時間processingDuration
タイムアウト時間requestTimeout
再試行間隔retryInterval
タイムゾーンzoneId

最後に

さて今回は、Javaにおける時刻関連の変数名に関する慣習についてまとめました。

Javaでよく見かける「createdAt」や「updatedAt」の「At」は、特定の出来事が発生した「時点」を表すための実務上の命名慣習です。Javaの言語仕様で強制されるルールではありませんが、多くのシステムで利用されているため、意味を知っておくとコードやデータベースの構造を理解しやすくなりますし、開発者間で不要な認識齟齬が無くなります。

最も大切なのは、変数名を見た開発者が「何を表す値なのか」を迷わず判断できることです。日時の種類、業務上の意味、予定と実績、単位、タイムゾーンを整理し、誰が読んでも誤解しにくい名前を付けましょう。

繰り返しにはなりますが、まずはプロジェクトルールに従うようにしてくださいね。

今回まとめたのはあくまでも「慣習」なのでお忘れなく

以上!

前回まとめたJava関連の記事も読んでもらえると嬉しいです!

Java以外の勉強記事も是非!

コメント

タイトルとURLをコピーしました