「日付丸め」とは何をするものか
「2025-03-26 を“月初”にそろえたい」「日付を“週単位”にまとめたい」「分析用に“日単位”までに丸めたい」
こういうときに出てくるのが「日付丸め」です。
日付丸めは、“ある日付を、指定した単位(1日・1週間・1ヶ月・1年など)の“きりのいいところ”に揃える処理” です。
時間丸めと同じく、切り捨て(floor)、切り上げ(ceil)、四捨五入(round)を意識すると整理しやすくなります。
情報セキュリティの観点では、
「ログの日時を“日単位”や“月単位”に丸めて保存し、個人の行動を細かく追えないようにする」
といった“匿名化・マスキング”のテクニックとしても使われます。
日単位の丸め(LocalDateTime → LocalDate)
時刻を落として「日付だけ」にする
まず一番基本の「日単位への丸め」です。LocalDateTime から「日付だけ」を取り出すと、それは「その日の 0:00 に丸めた」と同じ意味になります。
import java.time.LocalDate;
import java.time.LocalDateTime;
public class DateFloorToDay {
public static void main(String[] args) {
LocalDateTime dt = LocalDateTime.of(2025, 3, 26, 15, 30, 45);
LocalDate dateOnly = dt.toLocalDate(); // 2025-03-26
LocalDateTime startOfDay = dt.toLocalDate().atStartOfDay(); // 2025-03-26T00:00
System.out.println("元日時 : " + dt);
System.out.println("日付だけ : " + dateOnly);
System.out.println("その日の0時 : " + startOfDay);
}
}
Javaここで重要なのは、
「日単位で扱うと決めたら、時刻は切り捨ててしまう」という割り切りです。
ログ分析や集計では、「何日のデータか」だけが重要で、
「何時何分か」は不要なことも多いので、LocalDate にしてしまうだけで、データの扱いがかなりシンプルになります。
月単位の丸め(“月初”と“月末”)
月初に丸める(firstDayOfMonth)
例:2025-03-26 → 2025-03-01(3 月の月初)
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
public class DateFloorToMonth {
public static void main(String[] args) {
LocalDate any = LocalDate.of(2025, 3, 26);
LocalDate monthStart = any.with(TemporalAdjusters.firstDayOfMonth());
System.out.println("元日付 : " + any); // 2025-03-26
System.out.println("月初 : " + monthStart); // 2025-03-01
}
}
Javaこれは「月単位で切り捨てた」と考えられます。
「どの日でも、その月の代表として“月初”に揃える」イメージです。
月末に丸める(lastDayOfMonth)
例:2025-03-26 → 2025-03-31(3 月の月末)
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
public class DateCeilToMonth {
public static void main(String[] args) {
LocalDate any = LocalDate.of(2025, 3, 26);
LocalDate monthEnd = any.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("元日付 : " + any); // 2025-03-26
System.out.println("月末 : " + monthEnd); // 2025-03-31
}
}
Javaこれは「月単位で切り上げた」と見ることもできます。
「この月の最後の日」を代表として使いたいときに便利です。
月単位の四捨五入(“月初か月末か”を決める)
例えば「月の前半なら月初、後半なら月末に丸める」というルールも作れます。
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
public class DateRoundToMonth {
public static LocalDate roundToMonth(LocalDate date) {
LocalDate start = date.with(TemporalAdjusters.firstDayOfMonth());
LocalDate end = date.with(TemporalAdjusters.lastDayOfMonth());
long daysFromStart = java.time.temporal.ChronoUnit.DAYS.between(start, date);
long daysToEnd = java.time.temporal.ChronoUnit.DAYS.between(date, end);
if (daysFromStart <= daysToEnd) {
return start; // 前半寄り → 月初
} else {
return end; // 後半寄り → 月末
}
}
public static void main(String[] args) {
System.out.println("2025-03-10 → " + roundToMonth(LocalDate.of(2025, 3, 10)));
System.out.println("2025-03-25 → " + roundToMonth(LocalDate.of(2025, 3, 25)));
}
}
Javaここで深掘りしたいのは、
「丸めは“距離が近い方に寄せる”という発想で書ける」ということです。
月初と月末のどちらに近いかを日数で比べて、近い方に寄せています。
週単位の丸め(週の開始日・終了日)
週の開始日に丸める(例:月曜始まり)
例:2025-03-26(水) → 2025-03-24(月)
import java.time.DayOfWeek;
import java.time.LocalDate;
public class DateFloorToWeek {
public static LocalDate floorToWeek(LocalDate date, DayOfWeek weekStart) {
DayOfWeek dow = date.getDayOfWeek();
int diff = dow.getValue() - weekStart.getValue();
if (diff < 0) {
diff += 7;
}
return date.minusDays(diff);
}
public static void main(String[] args) {
LocalDate any = LocalDate.of(2025, 3, 26); // 水
LocalDate weekStart = floorToWeek(any, DayOfWeek.MONDAY);
System.out.println("元日付 : " + any); // 2025-03-26
System.out.println("週の開始: " + weekStart); // 2025-03-24
}
}
Javaここでのポイントは、
「“週の開始曜日”をパラメータにしておく」ことです。
日本だと月曜始まり・日曜始まりの両方があり得るので、
固定せずに引数で受け取る設計にしておくと柔軟です。
週の終了日に丸める(例:日曜終わり)
終了日は「開始日+6日」で表現できます。
import java.time.DayOfWeek;
import java.time.LocalDate;
public class DateCeilToWeek {
public static LocalDate ceilToWeek(LocalDate date, DayOfWeek weekStart) {
LocalDate start = DateFloorToWeek.floorToWeek(date, weekStart);
return start.plusDays(6);
}
public static void main(String[] args) {
LocalDate any = LocalDate.of(2025, 3, 26); // 水
LocalDate weekEnd = ceilToWeek(any, DayOfWeek.MONDAY);
System.out.println("元日付 : " + any); // 2025-03-26
System.out.println("週の終了: " + weekEnd); // 2025-03-30
}
}
Java週単位の集計(週次レポートなど)では、
「どの週に属するか」を決めるために、
このような“週の開始日”への丸めがよく使われます。
年単位の丸め(年初・年末)
年初に丸める(firstDayOfYear)
例:2025-03-26 → 2025-01-01
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
public class DateFloorToYear {
public static void main(String[] args) {
LocalDate any = LocalDate.of(2025, 3, 26);
LocalDate yearStart = any.with(TemporalAdjusters.firstDayOfYear());
System.out.println("元日付 : " + any); // 2025-03-26
System.out.println("年初 : " + yearStart); // 2025-01-01
}
}
Java年末に丸める(lastDayOfYear)
例:2025-03-26 → 2025-12-31
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
public class DateCeilToYear {
public static void main(String[] args) {
LocalDate any = LocalDate.of(2025, 3, 26);
LocalDate yearEnd = any.with(TemporalAdjusters.lastDayOfYear());
System.out.println("元日付 : " + any); // 2025-03-26
System.out.println("年末 : " + yearEnd); // 2025-12-31
}
}
Java年次集計・年度処理などでは、
「どの年に属するか」を決めるために、
年初・年末への丸めがよく使われます。
会計年度(4 月〜翌年 3 月など)の場合は、
「年度初日」「年度末日」を自前のユーティリティで定義して、
そこに丸めるイメージになります。
セキュリティ観点での「日付丸め」
ログ・分析データの“粒度”を落としてプライバシーを守る
情報セキュリティの観点では、
「日時が細かすぎると、個人の行動パターンが特定されやすくなる」という問題があります。
例えば、
「毎日 23:58 にアクセスしている」「毎週火曜の 7:05 にログインしている」
といった情報は、個人を推測する手がかりになり得ます。
そこで、保存時に日付を丸めてしまうという設計があり得ます。
例:
・日時を「日単位」に丸める(時刻は 0:00 にする)
・「月単位」に丸めて、日付は 1 日にする
・「週単位」に丸めて、週の開始日に揃える
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
public class DateMasking {
public static LocalDate maskToDate(LocalDateTime dt) {
return dt.toLocalDate();
}
public static LocalDate maskToMonth(LocalDateTime dt) {
return dt.toLocalDate().withDayOfMonth(1);
}
public static LocalDate maskToWeek(LocalDateTime dt) {
LocalDate d = dt.toLocalDate();
return DateFloorToWeek.floorToWeek(d, DayOfWeek.MONDAY);
}
public static void main(String[] args) {
LocalDateTime dt = LocalDateTime.of(2025, 3, 26, 23, 58);
System.out.println("元日時 : " + dt);
System.out.println("日単位 : " + maskToDate(dt)); // 2025-03-26
System.out.println("月単位 : " + maskToMonth(dt)); // 2025-03-01
System.out.println("週単位 : " + maskToWeek(dt)); // 2025-03-24 (月曜始まり)
}
}
Javaここで大事なのは、
「分析に本当に必要な粒度はどこまでか?」を考えたうえで丸めることです。
・セキュリティインシデント調査には“日時”が必要か
・マーケティング分析には“日単位”で十分か
・長期統計には“月単位”で十分か
こうした問いに答えながら、
「どの単位に丸めるか」を決めるのが、セキュリティ設計としての“日付丸め”です。
日付丸めユーティリティとしてまとめる
「単位」と「丸め方」を名前で表現する
日付丸めも、あちこちで同じようなコードを書きがちなので、
ユーティリティクラスにまとめておくと再利用しやすくなります。
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
public class DateRoundingUtils {
public static LocalDate floorToDay(LocalDateTime dt) {
return dt.toLocalDate();
}
public static LocalDate floorToMonth(LocalDate date) {
return date.with(TemporalAdjusters.firstDayOfMonth());
}
public static LocalDate ceilToMonth(LocalDate date) {
return date.with(TemporalAdjusters.lastDayOfMonth());
}
public static LocalDate floorToYear(LocalDate date) {
return date.with(TemporalAdjusters.firstDayOfYear());
}
public static LocalDate ceilToYear(LocalDate date) {
return date.with(TemporalAdjusters.lastDayOfYear());
}
public static LocalDate floorToWeek(LocalDate date, DayOfWeek weekStart) {
return DateFloorToWeek.floorToWeek(date, weekStart);
}
}
Javaこうしておけば、呼び出し側は
LocalDate monthKey = DateRoundingUtils.floorToMonth(date);
Javaのように、
「何単位で」「どの方向に」丸めているかが、コードから一目で分かるようになります。
まとめ:日付丸めで身につけてほしい感覚
日付丸めは、「日付を“きりのいい単位”に揃える」処理です。
まず「どの単位で扱うか」(日・週・月・年)を決める。
次に「どの方向に丸めるか」(切り捨て・切り上げ・四捨五入)を決める。TemporalAdjusters や ChronoUnit を使うと、月初・月末・年初・年末・日数差などを安全に扱える。
セキュリティ・プライバシーの観点では、「必要以上に細かい日付情報を持たない」ための丸めとしても使える。
共通ユーティリティにして、「単位」と「丸め方」を名前で表現すると、業務コードが読みやすくなる。
もしあなたのコードのどこかに、
「月初を 1 日と決め打ち」「月末を 30 日や 31 日と決め打ち」しているような箇所があれば、
そこを一度 TemporalAdjusters や日付丸めユーティリティに置き換えられないか眺めてみてください。
その小さな置き換えが、
“時間にもセキュリティにも強いエンジニア”への、確かな一歩になります。
