ゲーム開発備忘録

ゲームプログラマー UE4・5向けの記事を書いておりますので見ていただけるとありがたいです。

【UE5】〈Tips〉時間同士の足し算、引き算

目次

 

はじめに

UEで「現在時刻に60秒を足したい」と思ったとき、どの型を使えばいいか迷ったことはありませんか?

UEには時間を扱う構造体として FDateTime と FTimespan が用意されています。

どちらも内部的には int64 のTick値を保持していますが、意味が全く異なります。

 

この記事では、これらの型の演算子を網羅的に検証し、どの組み合わせが有効で、どれがベストなのかを明らかにします。

 

個人の備忘録としてまとめています。誤った情報がある場合があります。

もっと良い方法などもあるかもしれません!
コメントにてご指摘のほどお願いいたします。

 

UE5.6で解説します。

 

解説

①時間を表す構造体

FDateTime — 「時刻」を表す型

FDateTime は 特定の一点の時刻(いつ)を表します。

// 現在のUTC時刻を取得
FDateTime UtcNow = FDateTime::UtcNow();

// 現在のローカル時刻を取得
FDateTime LocalNow = FDateTime::Now();

// 特定の日時を指定して生成
FDateTime SpecificDate(2026, 3, 23, 15, 0, 0, 0); // 2026323 15:00:00.00
FTimespan — 「時間の長さ」を表す型

FTimespan は 時間の長さ(どれだけ)を表します。特定の日付に紐づかない「期間」です。

// ファクトリメソッドで生成
FTimespan OneMinute = FTimespan::FromSeconds(60.0);
FTimespan ThreeHours = FTimespan::FromHours(3.0);
FTimespan HalfDay = FTimespan::FromDays(0.5);

// コンストラクタで生成(時, , 秒)
FTimespan Duration(2, 30, 0); // 2時間300

// 値の取得
double TotalSec = OneMinute.GetTotalSeconds(); // 60.0
double TotalMin = OneMinute.GetTotalMinutes(); // 1.0

 

Blueprint での注意点

C++ の FromDays 等は float / double を受け取るため 0.5(半日)のような小数値を渡せます。

しかし、Blueprint の Make Timespan ノードは全引数が int32 のため、小数値を直接指定できません。

半日を表現したい場合は Days=0, Hours=12 のように分解するか、From Days ノードを使ってください。

 

Make Timespan と Make Timespan2 の違い

Make Timespan と Make Timespan2 の違いは最後の引数だけです。

Make Timespan はミリ秒(Milliseconds)、Make Timespan2 はナノ秒の端数(FractionNano)で精度を指定します。

 

②演算子の検証

FDateTime - FDateTime = FTimespan

2つの時刻の差を求めると、経過時間(FTimespan) が得られます。

FDateTime Start(2026, 3, 23, 10, 0, 0);
FDateTime End(2026, 3, 23, 13, 30, 0);

FTimespan Elapsed = End - Start;

UE_LOG(LogTemp, Log, TEXT("経過時間: %.1f "), Elapsed.GetTotalSeconds());
// 経過時間: 12600.0

UE_LOG(LogTemp, Log, TEXT("経過時間: %.1f 時間"), Elapsed.GetTotalHours());
// 経過時間: 3.5 時間

「15:00 から 12:00 を引くと?」→ 答えは「3時間」という長さになります。直感通りですね。

FDateTime + FTimespan = FDateTime

時刻に時間の長さを足すと、新しい時刻 が得られます。

FDateTime Now = FDateTime::UtcNow();
FTimespan OneHour = FTimespan::FromHours(1.0);

FDateTime OneHourLater = Now + OneHour;

UE_LOG(LogTemp, Log, TEXT("現在: %s"), *Now.ToString());
UE_LOG(LogTemp, Log, TEXT("1時間後: %s"), *OneHourLater.ToString());

「今日の15:00」+「1時間」=「今日の16:00」。これも自然です。

 

FDateTime - FTimespan = FDateTime

時刻から時間の長さを引くことも可能です。

FDateTime Now = FDateTime::UtcNow();
FTimespan ThirtyMinutes = FTimespan::FromMinutes(30.0);

FDateTime ThirtyMinutesAgo = Now - ThirtyMinutes;

UE_LOG(LogTemp, Log, TEXT("30分前: %s"), *ThirtyMinutesAgo.ToString());

 

FDateTime + FDateTime = コンパイルエラー

FDateTime A(2026, 3, 23, 10, 0, 0);
FDateTime B(2026, 3, 23, 15, 0, 0);

FDateTime Result = A + B; // コンパイルエラー!
// error: binary 'operator+': no operator found

「3月23日 10:00」+「3月23日 15:00」= ???

これは意味のない演算です。
地理に例えるなら「東京 + 大阪 = ???」のようなもの。2つの絶対位置を足し算することに意味はありません。

一方、引き算は「東京から大阪までの距離」のように相対的な差を求めるので意味があります。

内部的には FDateTime も FTimespan も同じ int64 のTick値を持っているため、Epicが operator+ を実装すること自体は簡単です。しかし、あえて提供していません。

これは型システムによって意味のない操作をコンパイル時に防ぐという、意図的な設計判断のように見えます。

 

Blueprint での注意点

C++ では FDateTime + FDateTime はコンパイルエラーになりますが、

Blueprint の + ノードではコンパイルが通ってしまいます。

内部のTick値がそのまま加算されるため、結果は意味のない日時になります。

 

例: 2026/3/23 13:30 + 2026/3/23 10:00 → 4051/6/12 23:30(ゴミ値)

Blueprint では型チェックが緩いため、C++ のような保護が働きません。

FDateTime 同士の加算は意味がないので、Blueprint でも使わないようにしましょう。



FTimespan 同士の演算

時間の長さ同士は自由に演算できます。

FTimespan A = FTimespan::FromHours(2.0);
FTimespan B = FTimespan::FromMinutes(30.0);

FTimespan Sum = A + B; // 2時間30
FTimespan Diff = A - B; // 1時間30
FTimespan Doubled = A * 2.0; // 4時間
FTimespan Halved = A / 2.0; // 1時間

UE_LOG(LogTemp, Log, TEXT("合計: %.1f "), Sum.GetTotalMinutes()); // 150.0
UE_LOG(LogTemp, Log, TEXT("差分: %.1f "), Diff.GetTotalMinutes()); // 90.0
UE_LOG(LogTemp, Log, TEXT("2: %.1f 時間"), Doubled.GetTotalHours()); // 4.0
UE_LOG(LogTemp, Log, TEXT("半分: %.1f 時間"), Halved.GetTotalHours()); // 1.0

「2時間 + 30分 = 2時間30分」。長さ同士の足し算は自然ですね。

 

最後に


UE4やUE5向けの記事を書いています。

皆様の応援が投稿のモチベーションになりますので

コメントやX(Twitter)のフォローなどしていただけるとありがたいです。

それではよきゲーム開発を。

投げ銭を投げる