「時間丸め」とは何をするものか
「10:03 を 5 分単位に丸めて 10:05 にしたい」「ログの時刻を“分単位”にそろえたい」「勤務時間を 15 分単位で計算したい」
こういうときに出てくるのが「時間丸め」です。
時間丸めは、“ある時刻を、指定した単位(5 分・15 分・1 時間など)の“きりのいいところ”に揃える処理” です。
切り捨て(floor)、切り上げ(ceil)、四捨五入(round)の 3 パターンを意識しておくと整理しやすくなります。
情報セキュリティの観点では、
「ログの時刻をあえて丸めて保存して、個人の行動を“秒単位”で追えないようにする」
といった“匿名化・マスキング”のテクニックとしても使われます。
基本方針:秒や分を「数値」として扱って丸める
なぜ「LocalDateTime のまま」丸めようとしない方がよいか
LocalDateTime は「年月日+時分秒」をまとめて持つクラスです。
これをそのまま丸めようとすると、
「分を丸めた結果 60 分になったらどうする?」「日付をまたいだら?」といった細かい処理が増えます。
そこで、一度“分”や“秒”を数値として取り出して丸め、最後に時刻に戻すという方針を取ると、
ロジックがかなりスッキリします。
分単位の丸め(5 分単位・15 分単位など)
分を切り捨てる(floor)
例:10:07 を 5 分単位で切り捨て → 10:05
10:14 を 15 分単位で切り捨て → 10:00
import java.time.LocalDateTime;
public class RoundDownMinutes {
public static LocalDateTime floorToMinutes(LocalDateTime dt, int unitMinutes) {
int minute = dt.getMinute();
int floored = (minute / unitMinutes) * unitMinutes;
return dt.withMinute(floored)
.withSecond(0)
.withNano(0);
}
public static void main(String[] args) {
LocalDateTime dt = LocalDateTime.of(2025, 3, 26, 10, 7, 30);
LocalDateTime floor5 = floorToMinutes(dt, 5);
LocalDateTime floor15 = floorToMinutes(dt, 15);
System.out.println("元 : " + dt); // 2025-03-26T10:07:30
System.out.println("5分切捨て : " + floor5); // 2025-03-26T10:05
System.out.println("15分切捨て: " + floor15); // 2025-03-26T10:00
}
}
Javaここで重要なのは、(minute / unitMinutes) * unitMinutes で「丸め後の分」を計算し、
秒・ナノ秒は 0 にリセットしていることです。
「丸めた結果の時刻は、“その単位の先頭”に揃える」という感覚を持ってください。
分を切り上げる(ceil)
例:10:07 を 5 分単位で切り上げ → 10:10
10:00 ちょうどはそのまま → 10:00
import java.time.LocalDateTime;
public class RoundUpMinutes {
public static LocalDateTime ceilToMinutes(LocalDateTime dt, int unitMinutes) {
int minute = dt.getMinute();
int mod = minute % unitMinutes;
if (mod == 0 && dt.getSecond() == 0 && dt.getNano() == 0) {
// すでにきりのいい時間ならそのまま
return dt.withSecond(0).withNano(0);
}
int up = minute + (unitMinutes - mod);
if (up >= 60) {
// 60分を超えたら、1時間進めて分を0に
dt = dt.plusHours(1);
up = 0;
}
return dt.withMinute(up)
.withSecond(0)
.withNano(0);
}
public static void main(String[] args) {
LocalDateTime dt = LocalDateTime.of(2025, 3, 26, 10, 7, 30);
LocalDateTime ceil5 = ceilToMinutes(dt, 5);
System.out.println("元 : " + dt); // 2025-03-26T10:07:30
System.out.println("5分切上げ: " + ceil5); // 2025-03-26T10:10
}
}
Javaここで深掘りしたいポイントは、
「切り上げは“次のきりのいい時間”に進める処理であり、60 分を超えたら時間も進める必要がある」ことです。
日付をまたぐケース(23:58 を 5 分切り上げ → 翌日 0:00)も同じ考え方で処理できます。
分を四捨五入する(round)
例:10:07 を 5 分単位で四捨五入 → 10:05(7 分は 5 に近い)
10:08 を 5 分単位で四捨五入 → 10:10(8 分は 10 に近い)
import java.time.LocalDateTime;
public class RoundNearestMinutes {
public static LocalDateTime roundToMinutes(LocalDateTime dt, int unitMinutes) {
int minute = dt.getMinute();
int second = dt.getSecond();
int nano = dt.getNano();
// 秒・ナノ秒も「分の小数部分」として考慮したい場合はここを工夫する
double totalMinutes = minute + (second / 60.0) + (nano / 1_000_000_000.0 / 60.0);
int rounded = (int) Math.round(totalMinutes / unitMinutes) * unitMinutes;
if (rounded >= 60) {
dt = dt.plusHours(1);
rounded = 0;
}
return dt.withMinute(rounded)
.withSecond(0)
.withNano(0);
}
public static void main(String[] args) {
LocalDateTime dt1 = LocalDateTime.of(2025, 3, 26, 10, 7, 0);
LocalDateTime dt2 = LocalDateTime.of(2025, 3, 26, 10, 8, 0);
System.out.println("10:07 → " + roundToMinutes(dt1, 5)); // 10:05
System.out.println("10:08 → " + roundToMinutes(dt2, 5)); // 10:10
}
}
Javaここでのキモは、
「分+秒+ナノ秒を“分の小数”として扱い、Math.round で丸めている」ことです。
業務によっては「秒は無視して分だけで四捨五入する」などのルールもあるので、
「何を丸めの対象にするか(秒を含めるかどうか)」を仕様として決めることが大事です。
時間単位(1 時間・2 時間単位など)の丸め
時を切り捨てる(floor)
例:10:30 を 1 時間単位で切り捨て → 10:00
10:30 を 2 時間単位で切り捨て → 10:00
23:30 を 2 時間単位で切り捨て → 22:00
import java.time.LocalDateTime;
public class RoundDownHours {
public static LocalDateTime floorToHours(LocalDateTime dt, int unitHours) {
int hour = dt.getHour();
int floored = (hour / unitHours) * unitHours;
return dt.withHour(floored)
.withMinute(0)
.withSecond(0)
.withNano(0);
}
public static void main(String[] args) {
LocalDateTime dt = LocalDateTime.of(2025, 3, 26, 10, 30);
System.out.println("1時間切捨て: " + floorToHours(dt, 1)); // 10:00
System.out.println("2時間切捨て: " + floorToHours(dt, 2)); // 10:00
}
}
Java考え方は分単位と同じで、
「時を数値として扱い、単位で割って掛け直す」だけです。
切り上げ・四捨五入も同じパターンで書けます。
セキュリティ観点での「時間丸め」
ログの時刻を丸めて“追跡精度”を落とす
情報セキュリティの世界では、
「ログを分析すると、ユーザーの行動パターンが秒単位で丸見えになる」という問題があります。
例えば、
「毎日 23:58:12 にアクセスしているユーザー」
という情報は、個人を特定する手がかりになり得ます。
そこで、ログ保存時に時刻を丸めてしまうというテクニックがあります。
例:
・秒以下を 0 にする(分単位まで)
・5 分単位に切り捨てる
・1 時間単位に切り捨てる
import java.time.LocalDateTime;
public class LogTimeMasking {
public static LocalDateTime maskToMinutes(LocalDateTime dt) {
// 秒・ナノ秒を0にして「分単位」までにする
return dt.withSecond(0).withNano(0);
}
public static LocalDateTime maskTo5Minutes(LocalDateTime dt) {
// 5分単位に切り捨て
int minute = dt.getMinute();
int floored = (minute / 5) * 5;
return dt.withMinute(floored).withSecond(0).withNano(0);
}
public static void main(String[] args) {
LocalDateTime dt = LocalDateTime.of(2025, 3, 26, 10, 7, 42);
System.out.println("元 : " + dt); // 10:07:42
System.out.println("分単位 : " + maskToMinutes(dt)); // 10:07:00
System.out.println("5分単位 : " + maskTo5Minutes(dt)); // 10:05:00
}
}
Javaここでのポイントは、
「分析に必要な精度」と「プライバシー保護」のバランスを、丸めの単位で調整できることです。
・セキュリティインシデント調査には秒単位が必要か?
・業務分析には分単位で十分か?
こういった問いに答えながら、
「どこまで丸めるか」を設計するのが“情報セキュリティのプロ”の視点です。
時間丸めユーティリティとしてまとめる
「丸め方」と「単位」をパラメータにする
時間丸めは、あちこちで似たようなコードを書きがちなので、
ユーティリティクラスにまとめておくと再利用しやすくなります。
import java.time.LocalDateTime;
public class TimeRoundingUtils {
public enum Mode {
FLOOR, CEIL, ROUND
}
public static LocalDateTime roundMinutes(LocalDateTime dt, int unitMinutes, Mode mode) {
return switch (mode) {
case FLOOR -> floorToMinutes(dt, unitMinutes);
case CEIL -> ceilToMinutes(dt, unitMinutes);
case ROUND -> roundToMinutes(dt, unitMinutes);
};
}
private static LocalDateTime floorToMinutes(LocalDateTime dt, int unitMinutes) {
int minute = dt.getMinute();
int floored = (minute / unitMinutes) * unitMinutes;
return dt.withMinute(floored).withSecond(0).withNano(0);
}
private static LocalDateTime ceilToMinutes(LocalDateTime dt, int unitMinutes) {
int minute = dt.getMinute();
int mod = minute % unitMinutes;
if (mod == 0 && dt.getSecond() == 0 && dt.getNano() == 0) {
return dt.withSecond(0).withNano(0);
}
int up = minute + (unitMinutes - mod);
if (up >= 60) {
dt = dt.plusHours(1);
up = 0;
}
return dt.withMinute(up).withSecond(0).withNano(0);
}
private static LocalDateTime roundToMinutes(LocalDateTime dt, int unitMinutes) {
int minute = dt.getMinute();
int second = dt.getSecond();
int nano = dt.getNano();
double totalMinutes = minute + (second / 60.0) + (nano / 1_000_000_000.0 / 60.0);
int rounded = (int) Math.round(totalMinutes / unitMinutes) * unitMinutes;
if (rounded >= 60) {
dt = dt.plusHours(1);
rounded = 0;
}
return dt.withMinute(rounded).withSecond(0).withNano(0);
}
}
Javaこうしておけば、呼び出し側は
LocalDateTime rounded =
TimeRoundingUtils.roundMinutes(now, 5, TimeRoundingUtils.Mode.FLOOR);
Javaのように、
「何分単位で」「どの丸め方で」という意図を、コードでそのまま表現できます。
まとめ:時間丸めで身につけてほしい感覚
時間丸めは、「時刻を“きりのいい単位”に揃える」処理です。
分単位・時間単位など、まず「どの単位で丸めるか」を決める。
切り捨て・切り上げ・四捨五入の 3 パターンを意識し、
分や秒を“数値”として扱ってから丸め、最後に時刻に戻す。
ログや監査情報では、丸めを使って“必要以上に細かい時刻情報を持たない”というセキュリティ設計もあり得る。
共通ユーティリティにして、「単位」と「丸め方」をパラメータ化すると、実務コードがかなりきれいになる。
もしあなたのコードのどこかに、
「if 文で 0〜4 分は切り捨て、5〜9 分は切り上げ…」のようなゴリゴリの分岐があれば、
そこを一度「数値として丸める」スタイルに置き換えられないか眺めてみてください。
その小さな整理が、
“時間にもセキュリティにも強いエンジニア”への、確かな一歩になります。
