Java LocalDateTime
LocalDateTime 是 Java 8 引入的日期時間類別,結合了日期和時間,但不包含時區資訊,位於 java.time 套件中。
引入套件
import java.time.LocalDateTime;
建立 LocalDateTime
取得當前日期時間
LocalDateTime now = LocalDateTime.now();
System.out.println(now); // 2024-12-10T14:30:45.123456789
指定日期時間
// of(年, 月, 日, 時, 分)
LocalDateTime dt1 = LocalDateTime.of(2024, 12, 25, 14, 30);
System.out.println(dt1); // 2024-12-25T14:30
// of(年, 月, 日, 時, 分, 秒)
LocalDateTime dt2 = LocalDateTime.of(2024, 12, 25, 14, 30, 45);
System.out.println(dt2); // 2024-12-25T14:30:45
// of(年, 月, 日, 時, 分, 秒, 奈秒)
LocalDateTime dt3 = LocalDateTime.of(2024, 12, 25, 14, 30, 45, 123456789);
// 使用 Month 列舉
LocalDateTime dt4 = LocalDateTime.of(2024, Month.DECEMBER, 25, 14, 30);
結合 LocalDate 和 LocalTime
LocalDate date = LocalDate.of(2024, 12, 25);
LocalTime time = LocalTime.of(14, 30, 45);
LocalDateTime dt1 = LocalDateTime.of(date, time);
LocalDateTime dt2 = date.atTime(time);
LocalDateTime dt3 = date.atTime(14, 30);
LocalDateTime dt4 = time.atDate(date);
System.out.println(dt1); // 2024-12-25T14:30:45
從字串解析
LocalDateTime dt = LocalDateTime.parse("2024-12-25T14:30:45");
System.out.println(dt); // 2024-12-25T14:30:45
// 自訂格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
LocalDateTime dt2 = LocalDateTime.parse("2024/12/25 14:30:45", formatter);
取得日期時間資訊
LocalDateTime dt = LocalDateTime.of(2024, 12, 25, 14, 30, 45);
// 日期部分
int year = dt.getYear(); // 2024
int month = dt.getMonthValue(); // 12
Month monthEnum = dt.getMonth(); // DECEMBER
int day = dt.getDayOfMonth(); // 25
DayOfWeek dayOfWeek = dt.getDayOfWeek(); // WEDNESDAY
int dayOfYear = dt.getDayOfYear(); // 360
// 時間部分
int hour = dt.getHour(); // 14
int minute = dt.getMinute(); // 30
int second = dt.getSecond(); // 45
int nano = dt.getNano(); // 0
// 取得 LocalDate 和 LocalTime
LocalDate date = dt.toLocalDate(); // 2024-12-25
LocalTime time = dt.toLocalTime(); // 14:30:45
日期時間運算
加減運算
LocalDateTime dt = LocalDateTime.of(2024, 12, 25, 14, 30, 0);
// 加上時間
LocalDateTime plus1Year = dt.plusYears(1); // 2025-12-25T14:30
LocalDateTime plus2Months = dt.plusMonths(2); // 2025-02-25T14:30
LocalDateTime plus7Days = dt.plusDays(7); // 2025-01-01T14:30
LocalDateTime plus3Hours = dt.plusHours(3); // 2024-12-25T17:30
LocalDateTime plus30Mins = dt.plusMinutes(30); // 2024-12-25T15:00
LocalDateTime plus45Secs = dt.plusSeconds(45); // 2024-12-25T14:30:45
// 減去時間
LocalDateTime minus1Month = dt.minusMonths(1); // 2024-11-25T14:30
LocalDateTime minus2Hours = dt.minusHours(2); // 2024-12-25T12:30
使用 Period 和 Duration
LocalDateTime dt = LocalDateTime.of(2024, 12, 25, 14, 30, 0);
// Period(日期間隔)
Period period = Period.ofMonths(2);
LocalDateTime newDt1 = dt.plus(period); // 2025-02-25T14:30
// Duration(時間間隔)
Duration duration = Duration.ofHours(5);
LocalDateTime newDt2 = dt.plus(duration); // 2024-12-25T19:30
修改日期時間
LocalDateTime dt = LocalDateTime.of(2024, 12, 25, 14, 30, 45);
// 修改日期部分
LocalDateTime newYear = dt.withYear(2025); // 2025-12-25T14:30:45
LocalDateTime newMonth = dt.withMonth(6); // 2024-06-25T14:30:45
LocalDateTime newDay = dt.withDayOfMonth(1); // 2024-12-01T14:30:45
// 修改時間部分
LocalDateTime newHour = dt.withHour(10); // 2024-12-25T10:30:45
LocalDateTime newMinute = dt.withMinute(0); // 2024-12-25T14:00:45
LocalDateTime newSecond = dt.withSecond(0); // 2024-12-25T14:30:00
日期時間比較
LocalDateTime dt1 = LocalDateTime.of(2024, 12, 25, 14, 30);
LocalDateTime dt2 = LocalDateTime.of(2024, 12, 31, 18, 0);
boolean isBefore = dt1.isBefore(dt2); // true
boolean isAfter = dt1.isAfter(dt2); // false
boolean isEqual = dt1.isEqual(dt2); // false
int result = dt1.compareTo(dt2); // 負數(dt1 較早)
計算間隔
LocalDateTime start = LocalDateTime.of(2024, 1, 1, 9, 0);
LocalDateTime end = LocalDateTime.of(2024, 12, 31, 18, 0);
// 使用 Duration(適合時間間隔)
Duration duration = Duration.between(start, end);
long hours = duration.toHours(); // 8769
long minutes = duration.toMinutes(); // 526140
// 使用 ChronoUnit
long days = ChronoUnit.DAYS.between(start, end); // 365
long hours2 = ChronoUnit.HOURS.between(start, end); // 8769
long months = ChronoUnit.MONTHS.between(start, end); // 11
時間調節器
import java.time.temporal.TemporalAdjusters;
LocalDateTime dt = LocalDateTime.of(2024, 12, 15, 14, 30);
// 該月第一天
LocalDateTime firstDay = dt.with(TemporalAdjusters.firstDayOfMonth()); // 2024-12-01T14:30
// 該月最後一天
LocalDateTime lastDay = dt.with(TemporalAdjusters.lastDayOfMonth()); // 2024-12-31T14:30
// 下一個星期一
LocalDateTime nextMonday = dt.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
// 設定時間為當天開始
LocalDateTime startOfDay = dt.toLocalDate().atStartOfDay(); // 2024-12-15T00:00
格式化輸出
LocalDateTime dt = LocalDateTime.of(2024, 12, 25, 14, 30, 45);
// 預設格式
System.out.println(dt.toString()); // 2024-12-25T14:30:45
// 自訂格式
DateTimeFormatter f1 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
System.out.println(dt.format(f1)); // 2024/12/25 14:30:45
DateTimeFormatter f2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH時mm分ss秒");
System.out.println(dt.format(f2)); // 2024年12月25日 14時30分45秒
DateTimeFormatter f3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm a");
System.out.println(dt.format(f3)); // 2024-12-25 02:30 PM
轉換為其他類型
LocalDateTime dt = LocalDateTime.of(2024, 12, 25, 14, 30, 45);
// 轉換為 ZonedDateTime(加上時區)
ZonedDateTime zdt = dt.atZone(ZoneId.of("Asia/Taipei"));
// 轉換為 OffsetDateTime
OffsetDateTime odt = dt.atOffset(ZoneOffset.ofHours(8));
// 轉換為 Instant(需要時區)
Instant instant = dt.atZone(ZoneId.systemDefault()).toInstant();
// 轉換為 Epoch 秒數
long epochSecond = dt.atZone(ZoneId.systemDefault()).toEpochSecond();
// 從 Epoch 毫秒數建立
LocalDateTime fromEpoch = LocalDateTime.ofInstant(
Instant.ofEpochMilli(System.currentTimeMillis()),
ZoneId.systemDefault()
);
實用範例
計算會議結束時間
public static LocalDateTime calculateEndTime(LocalDateTime start, int durationMinutes) {
return start.plusMinutes(durationMinutes);
}
LocalDateTime meetingStart = LocalDateTime.of(2024, 12, 25, 14, 0);
LocalDateTime meetingEnd = calculateEndTime(meetingStart, 90);
System.out.println("會議結束時間: " + meetingEnd); // 2024-12-25T15:30
判斷是否在特定時間範圍內
public static boolean isWithinRange(LocalDateTime target,
LocalDateTime start,
LocalDateTime end) {
return !target.isBefore(start) && !target.isAfter(end);
}
LocalDateTime event = LocalDateTime.of(2024, 12, 25, 15, 0);
LocalDateTime rangeStart = LocalDateTime.of(2024, 12, 25, 14, 0);
LocalDateTime rangeEnd = LocalDateTime.of(2024, 12, 25, 16, 0);
System.out.println(isWithinRange(event, rangeStart, rangeEnd)); // true
格式化為相對時間
public static String formatRelativeTime(LocalDateTime dateTime) {
LocalDateTime now = LocalDateTime.now();
Duration duration = Duration.between(dateTime, now);
if (duration.isNegative()) {
return "未來";
}
long seconds = duration.getSeconds();
if (seconds < 60) return "剛剛";
if (seconds < 3600) return (seconds / 60) + " 分鐘前";
if (seconds < 86400) return (seconds / 3600) + " 小時前";
if (seconds < 604800) return (seconds / 86400) + " 天前";
return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}
取得本週的開始和結束
public static LocalDateTime getStartOfWeek(LocalDateTime dt) {
return dt.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
.toLocalDate()
.atStartOfDay();
}
public static LocalDateTime getEndOfWeek(LocalDateTime dt) {
return dt.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY))
.toLocalDate()
.atTime(23, 59, 59);
}
LocalDateTime now = LocalDateTime.now();
System.out.println("本週開始: " + getStartOfWeek(now));
System.out.println("本週結束: " + getEndOfWeek(now));
重點整理
LocalDateTime結合日期和時間,但不含時區- 是不可變(immutable)類別
- 使用
now()取得當前日期時間 - 可由
LocalDate+LocalTime組合而成 - 使用
plus/minus方法進行日期時間運算 - 需要時區資訊時,轉換為
ZonedDateTime - 搭配
DateTimeFormatter格式化輸出