できない.dev

2つの日付の差を求めるには

2つの日付・日時の差を取って日数や時間に直す基本形を各言語で示す。
差が「期間を表す専用の型」で返る言語と、ミリ秒の数値で返る言語の違いと、日数へ丸めるときに切り捨てが起きる位置までを扱う。

公開:

各言語見出しの横のバッジは検証状態を表す。実行確認済みはコードを実際に実行して確認したもの、静的確認は構文と公式 API ドキュメントで確認したものである。

Python 実行確認済み

from datetime import date, datetime
 
d1 = date(2026, 3, 1)
d2 = date(2026, 8, 28)
print((d2 - d1).days)          # -> 180(date 同士なら timedelta.days がそのまま日数)
 
t1 = datetime(2026, 8, 28, 9, 0)
t2 = datetime(2026, 8, 29, 21, 30)
diff = t2 - t1
print(diff.days, diff.seconds)      # -> 1 45000(days は切り捨て、端数は seconds 側)
print(diff.total_seconds() / 3600)  # -> 36.5(時間で見るなら total_seconds を割る)

date 同士・datetime 同士を引くと timedelta が返る。
date 同士なら days がそのまま日数になるが、datetime 同士の場合 days は切り捨てた日数で、24 時間未満の端数は seconds 側に入る。
時間や分の単位でまとめて見たいときは total_seconds() を割るのが確実である。

うまくいかない時: Python で datetime の naive と aware を比較できず TypeError になる

JavaScript 実行確認済み

const d1 = new Date("2026-03-01T00:00:00Z");
const d2 = new Date("2026-08-28T00:00:00Z");
 
const ms = d2 - d1;                 // Date は数値に変換され、差はミリ秒で出る
console.log(ms / 86400000);         // -> 180
 
const a = new Date("2026-08-28T09:00:00Z");
const b = new Date("2026-08-29T21:30:00Z");
console.log((b - a) / 3600000);        // -> 36.5
console.log(Math.floor((b - a) / 86400000)); // -> 1(日数に丸めるなら自分で切り捨てる)

Date 同士を引くと数値に変換され、差はミリ秒で返る。
日数にするには 86400000 で割る。
専用の期間型が無いぶん単位を自分で決められるが、割った結果は小数のままなので、日数として使うなら Math.floor などで丸める向きを明示する。

うまくいかない時: React のハイドレーションエラー(Hydration mismatch)が解消できない

TypeScript 実行確認済み

const d1: Date = new Date("2026-03-01T00:00:00Z");
const d2: Date = new Date("2026-08-28T00:00:00Z");
 
// const ms = d2 - d1;  // TS2362 / TS2363: 算術演算の両辺は number でなければならない
const ms: number = d2.getTime() - d1.getTime();
 
console.log(ms / 86_400_000);            // -> 180
console.log(Math.trunc(ms / 86_400_000)); // -> 180(端数を落とすなら trunc / floor)

JavaScript と計算内容は同じだが、Date 同士の引き算は TS2362 / TS2363 で弾かれる。
算術演算の両辺は number 型でなければならないため、getTime() で明示的にミリ秒へ変換してから引く。
valueOf() や単項プラスでも通るが、意図が読み取りやすい getTime() を選ぶ。

Go 静的確認

package main
 
import (
	"fmt"
	"time"
)
 
func main() {
	d1 := time.Date(2026, time.March, 1, 0, 0, 0, 0, time.UTC)
	d2 := time.Date(2026, time.August, 28, 0, 0, 0, 0, time.UTC)
 
	diff := d2.Sub(d1)                  // time.Duration
	fmt.Println(int(diff.Hours() / 24)) // -> 180(Duration に Days() は無い)
 
	t1 := time.Date(2026, time.August, 28, 9, 0, 0, 0, time.UTC)
	t2 := time.Date(2026, time.August, 29, 21, 30, 0, 0, time.UTC)
	fmt.Println(t2.Sub(t1).Hours()) // -> 36.5
}

Sub は time.Duration を返す。
Duration が持つのは Hours / Minutes / Seconds までで Days は無いため、日数が欲しければ Hours() を 24 で割る。
日付だけを比べたい場合も time.Time を使うので、時刻部分をゼロで揃えてから引く必要がある。

Rust 静的確認

use chrono::NaiveDate;
 
fn main() {
    let d1 = NaiveDate::from_ymd_opt(2026, 3, 1).unwrap();
    let d2 = NaiveDate::from_ymd_opt(2026, 8, 28).unwrap();
 
    let diff = d2 - d1;              // chrono::TimeDelta
    println!("{}", diff.num_days()); // -> 180
}

標準ライブラリにはカレンダー上の日付型が無いため、日付の差を取るには chrono を使う。
NaiveDate 同士の引き算は TimeDelta を返し、num_days() で日数を取り出す。
タイムゾーンを持たせたい場合は NaiveDate ではなく DateTime<Tz> 側を使う。

Java 実行確認済み

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
 
public class Main {
    public static void main(String[] args) {
        LocalDate d1 = LocalDate.of(2026, 3, 1);
        LocalDate d2 = LocalDate.of(2026, 8, 28);
        System.out.println(ChronoUnit.DAYS.between(d1, d2)); // -> 180
 
        LocalDateTime t1 = LocalDateTime.of(2026, 8, 28, 9, 0);
        LocalDateTime t2 = LocalDateTime.of(2026, 8, 29, 21, 30);
        Duration d = Duration.between(t1, t2);
        System.out.println(d.toHours());   // -> 36(切り捨て。36.5 にはならない)
        System.out.println(d.toMinutes()); // -> 2190
    }
}

日付単位の差は ChronoUnit.DAYS.between が読みやすい。
時刻を含む差は Duration.between で取るが、toHours / toDays は切り捨てて整数を返すため、36 時間 30 分は 36 と表示される。
端数まで見たいときは toMinutes のように細かい単位へ落としてから割る。

C# 実行確認済み

var d1 = new DateTime(2026, 3, 1);
var d2 = new DateTime(2026, 8, 28);
 
TimeSpan span = d2 - d1;
Console.WriteLine(span.Days); // -> 180
 
var t1 = new DateTime(2026, 8, 28, 9, 0, 0);
var t2 = new DateTime(2026, 8, 29, 21, 30, 0);
TimeSpan d = t2 - t1;
Console.WriteLine(d.Days);       // -> 1(日数部分だけ)
Console.WriteLine(d.TotalHours); // -> 36.5(全体を時間で見る)

DateTime 同士を引くと TimeSpan が返る。
Days は日数部分だけを整数で返すのに対し、TotalHours や TotalDays は端数を含む小数を返す。
Days と TotalDays は名前が似ていて意味が違うため、丸めたいのか総量が欲しいのかで選び分ける。

つまずき

TypeScript では JavaScript と同じつもりで Date 同士を引くとコンパイルが通らない。
tsc --strict で確認すると TS2362 と TS2363 の 2 件が出て、算術演算の両辺は number でなければならないと言われる。
getTime() でミリ秒に変換してから引けば解決する。
Python では tzinfo の有無が揃っていない datetime 同士を引くと TypeError になる。
両方を naive にするか、両方を aware に揃えてから引く。

日数に丸める位置に注意する

差を日数へ直すとき、どこで切り捨てが起きるかは言語ごとに違う。
同じ 36 時間 30 分の差でも、Java の Duration.toHours() は 36 を返し、C# の TimeSpan.TotalHours は 36.5 を返す。
Python の timedelta は days が 1、端数の 12 時間 30 分が seconds に 45000 として分かれて入る。
JavaScript はミリ秒の数値しか返さないので、丸めるかどうかは呼び出し側の判断になる。
「日数」と一口に言っても切り捨てた整数なのか端数込みの小数なのかで結果が変わるため、必要な方を明示的に選ぶ。

1日が24時間とは限らない

夏時間を採用している地域のローカル時刻で日付を作ると、切り替え日の 1 日は 23 時間または 25 時間になる。
ミリ秒や秒の差を 86400 で割って日数にする方法は、この日をまたぐと 1 日ずれることがある。
カレンダー上の日数が欲しい場合は、Java の ChronoUnit.DAYS.between や Python の date のように時刻を持たない型で引くか、UTC に揃えてから計算する。
上のコードで UTC を明示しているのはこのためである。

この記事は役立ちましたか?