最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java8中日期時間API使用的完全指南

 更新時間:2025年12月15日 08:49:08   作者:吃西紅柿長大的番茄  
如果你曾經(jīng)使用過Java的java.util.Date和java.util.Calendar,一定體會過那種混亂和痛苦,例如線程不安全,時區(qū)處理復(fù)雜等,Java?8引入的全新日期時間API徹底解決了這些問題,下面小編就和大家詳細介紹一下吧

引言:為什么需要新的日期時間API?

如果你曾經(jīng)使用過Java的java.util.Datejava.util.Calendar,一定體會過那種混亂和痛苦:月份從0開始、Date既包含日期又包含時間、SimpleDateFormat線程不安全、時區(qū)處理復(fù)雜... Java 8引入的全新日期時間API徹底解決了這些問題,帶來了現(xiàn)代化、易于使用且線程安全的時間處理方式。

新舊API對比:一場革命

傳統(tǒng)API的問題

import java.util.*;
import java.text.SimpleDateFormat;

public class LegacyDateTimeProblems {
    public static void main(String[] args) throws Exception {
        // 問題1: Date的月份從0開始(0=一月,11=十二月)
        Date date = new Date(2023, 10, 15); // 這實際上是2023年11月15日!
        System.out.println("令人困惑的月份: " + date);
        
        // 問題2: SimpleDateFormat線程不安全
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date parsedDate = sdf.parse("2023-11-15");
        System.out.println("解析后的日期: " + parsedDate);
        
        // 問題3: Calendar操作繁瑣且容易出錯
        Calendar calendar = Calendar.getInstance();
        calendar.set(2023, Calendar.NOVEMBER, 15); // 注意:這里月份是實際的11月
        calendar.add(Calendar.DAY_OF_MONTH, 7);
        System.out.println("7天后: " + calendar.getTime());
        
        // 問題4: Date同時包含日期和時間,但經(jīng)常被誤用
        Date now = new Date();
        System.out.println("Date包含時間: " + now);
        
        // 問題5: 時區(qū)處理復(fù)雜
        TimeZone tz = TimeZone.getTimeZone("America/New_York");
        calendar.setTimeZone(tz);
        System.out.println("紐約時間: " + calendar.getTime());
    }
}

Java 8日期時間API的核心優(yōu)勢

  • 不可變性:所有日期時間對象都是不可變的,線程安全
  • 清晰的設(shè)計:分離了日期、時間、日期時間等概念
  • 流暢的API:鏈式調(diào)用,代碼更易讀
  • 強大的時區(qū)支持:內(nèi)置完善的時區(qū)處理
  • 更好的擴展性:支持自定義日歷系統(tǒng)

核心類概覽

Java 8日期時間API主要類:
├── 基本日期時間類
│   ├── LocalDate       (日期:年-月-日)
│   ├── LocalTime       (時間:時-分-秒-納秒)
│   ├── LocalDateTime   (日期時間)
│   ├── ZonedDateTime   (帶時區(qū)的日期時間)
│   └── OffsetDateTime  (帶偏移量的日期時間)

├── 時間點與持續(xù)時間
│   ├── Instant         (時間戳,基于Unix時間)
│   ├── Duration        (時間段,基于時間)
│   └── Period          (時間段,基于日期)

├── 輔助類
│   ├── DateTimeFormatter (日期時間格式化)
│   ├── ZoneId          (時區(qū)ID)
│   ├── ZoneOffset      (時區(qū)偏移量)
│   └── Chronology      (年表,支持不同日歷系統(tǒng))

└── 時間調(diào)整器
    ├── TemporalAdjuster (時間調(diào)整器)
    └── TemporalAdjusters (預(yù)定義調(diào)整器)

LocalDate:處理日期

LocalDate基礎(chǔ)操作

import java.time.*;
import java.time.format.*;
import java.time.temporal.*;

public class LocalDateExample {
    
    public static void main(String[] args) {
        System.out.println("=== LocalDate 基礎(chǔ)操作 ===");
        
        // 1. 創(chuàng)建LocalDate的多種方式
        LocalDate today = LocalDate.now();
        LocalDate specificDate = LocalDate.of(2023, 11, 15);
        LocalDate parsedDate = LocalDate.parse("2023-11-15");
        
        System.out.println("今天: " + today);
        System.out.println("指定日期: " + specificDate);
        System.out.println("解析日期: " + parsedDate);
        
        // 2. 獲取日期各部分
        System.out.println("\n日期分解:");
        System.out.println("年: " + today.getYear());
        System.out.println("月: " + today.getMonth() + " (數(shù)值: " + today.getMonthValue() + ")");
        System.out.println("日: " + today.getDayOfMonth());
        System.out.println("星期: " + today.getDayOfWeek());
        System.out.println("一年中的第幾天: " + today.getDayOfYear());
        
        // 3. 日期運算
        System.out.println("\n日期運算:");
        System.out.println("明天: " + today.plusDays(1));
        System.out.println("一周后: " + today.plusWeeks(1));
        System.out.println("一月后: " + today.plusMonths(1));
        System.out.println("一年后: " + today.plusYears(1));
        
        System.out.println("昨天: " + today.minusDays(1));
        System.out.println("一周前: " + today.minusWeeks(1));
        System.out.println("一月前: " + today.minusMonths(1));
        System.out.println("一年前: " + today.minusYears(1));
        
        // 4. 日期比較
        LocalDate otherDate = LocalDate.of(2023, 12, 25);
        System.out.println("\n日期比較:");
        System.out.println(today + " 在 " + otherDate + " 之前? " + today.isBefore(otherDate));
        System.out.println(today + " 在 " + otherDate + " 之后? " + today.isAfter(otherDate));
        System.out.println(today + " 等于 " + otherDate + "? " + today.isEqual(otherDate));
        
        // 5. 特殊日期
        System.out.println("\n特殊日期:");
        System.out.println("是否是閏年? " + today.isLeapYear());
        System.out.println("當(dāng)月天數(shù): " + today.lengthOfMonth());
        System.out.println("當(dāng)年天數(shù): " + today.lengthOfYear());
        
        // 6. 日期調(diào)整
        System.out.println("\n日期調(diào)整:");
        System.out.println("當(dāng)月第一天: " + today.with(TemporalAdjusters.firstDayOfMonth()));
        System.out.println("當(dāng)月最后一天: " + today.with(TemporalAdjusters.lastDayOfMonth()));
        System.out.println("下個月第一天: " + today.with(TemporalAdjusters.firstDayOfNextMonth()));
        System.out.println("下個周一: " + today.with(TemporalAdjusters.next(DayOfWeek.MONDAY)));
        System.out.println("當(dāng)月最后一個周五: " + today.with(TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY)));
        
        // 7. 自定義調(diào)整器
        TemporalAdjuster nextWorkingDay = TemporalAdjusters.ofDateAdjuster(date -> {
            DayOfWeek dayOfWeek = date.getDayOfWeek();
            if (dayOfWeek == DayOfWeek.FRIDAY) {
                return date.plusDays(3); // 周五到下周一
            } else if (dayOfWeek == DayOfWeek.SATURDAY) {
                return date.plusDays(2); // 周六到下周一
            } else {
                return date.plusDays(1); // 其他日子到明天
            }
        });
        System.out.println("下一個工作日: " + today.with(nextWorkingDay));
    }
    
    // 實際應(yīng)用:計算年齡
    public static int calculateAge(LocalDate birthDate) {
        return Period.between(birthDate, LocalDate.now()).getYears();
    }
    
    // 實際應(yīng)用:計算工作日
    public static long calculateWorkingDays(LocalDate start, LocalDate end) {
        return start.datesUntil(end.plusDays(1))
                   .filter(date -> date.getDayOfWeek() != DayOfWeek.SATURDAY &&
                                  date.getDayOfWeek() != DayOfWeek.SUNDAY)
                   .count();
    }
    
    // 實際應(yīng)用:生成日期范圍
    public static List<LocalDate> generateDateRange(LocalDate start, LocalDate end, int stepDays) {
        List<LocalDate> dates = new ArrayList<>();
        LocalDate current = start;
        while (!current.isAfter(end)) {
            dates.add(current);
            current = current.plusDays(stepDays);
        }
        return dates;
    }
}

LocalTime:處理時間

LocalTime基礎(chǔ)操作

import java.time.*;
import java.time.temporal.ChronoUnit;

public class LocalTimeExample {
    
    public static void main(String[] args) {
        System.out.println("=== LocalTime 基礎(chǔ)操作 ===");
        
        // 1. 創(chuàng)建LocalTime的多種方式
        LocalTime now = LocalTime.now();
        LocalTime specificTime = LocalTime.of(14, 30, 45); // 14:30:45
        LocalTime parsedTime = LocalTime.parse("09:15:30");
        
        System.out.println("現(xiàn)在時間: " + now);
        System.out.println("指定時間: " + specificTime);
        System.out.println("解析時間: " + parsedTime);
        
        // 2. 獲取時間各部分
        System.out.println("\n時間分解:");
        System.out.println("小時: " + now.getHour());
        System.out.println("分鐘: " + now.getMinute());
        System.out.println("秒: " + now.getSecond());
        System.out.println("納秒: " + now.getNano());
        
        // 3. 時間運算
        System.out.println("\n時間運算:");
        System.out.println("1小時后: " + now.plusHours(1));
        System.out.println("30分鐘后: " + now.plusMinutes(30));
        System.out.println("15秒后: " + now.plusSeconds(15));
        System.out.println("100納秒后: " + now.plusNanos(100));
        
        System.out.println("2小時前: " + now.minusHours(2));
        System.out.println("45分鐘前: " + now.minusMinutes(45));
        System.out.println("30秒前: " + now.minusSeconds(30));
        
        // 使用ChronoUnit進行更靈活的時間運算
        System.out.println("半小時后: " + now.plus(30, ChronoUnit.MINUTES));
        System.out.println("三刻鐘后: " + now.plus(3, ChronoUnit.HALF_HOURS));
        
        // 4. 時間比較
        LocalTime otherTime = LocalTime.of(18, 0, 0);
        System.out.println("\n時間比較:");
        System.out.println(now + " 在 " + otherTime + " 之前? " + now.isBefore(otherTime));
        System.out.println(now + " 在 " + otherTime + " 之后? " + now.isAfter(otherTime));
        
        // 5. 時間調(diào)整
        System.out.println("\n時間調(diào)整:");
        System.out.println("調(diào)整到整點: " + now.withMinute(0).withSecond(0).withNano(0));
        System.out.println("調(diào)整到下一小時: " + now.withHour((now.getHour() + 1) % 24));
        
        // 6. 獲取最大/最小時間
        System.out.println("\n特殊時間:");
        System.out.println("最小時間: " + LocalTime.MIN);
        System.out.println("最大時間: " + LocalTime.MAX);
        System.out.println("午夜: " + LocalTime.MIDNIGHT);
        System.out.println("中午: " + LocalTime.NOON);
        
        // 7. 時間范圍檢查
        System.out.println("\n時間范圍檢查:");
        LocalTime startWork = LocalTime.of(9, 0);
        LocalTime endWork = LocalTime.of(18, 0);
        System.out.println(now + " 是否在工作時間內(nèi)? " + 
                          (now.isAfter(startWork) && now.isBefore(endWork)));
        
        // 8. 時間差計算
        LocalTime start = LocalTime.of(9, 0);
        LocalTime end = LocalTime.of(17, 30);
        System.out.println("\n時間差計算:");
        long hoursBetween = ChronoUnit.HOURS.between(start, end);
        long minutesBetween = ChronoUnit.MINUTES.between(start, end);
        System.out.println(start + " 到 " + end + " 相差 " + hoursBetween + " 小時");
        System.out.println(start + " 到 " + end + " 相差 " + minutesBetween + " 分鐘");
    }
    
    // 實際應(yīng)用:計算會議持續(xù)時間
    public static Duration calculateMeetingDuration(LocalTime startTime, LocalTime endTime) {
        return Duration.between(startTime, endTime);
    }
    
    // 實際應(yīng)用:檢查是否在營業(yè)時間
    public static boolean isBusinessHour(LocalTime time, LocalTime open, LocalTime close) {
        return !time.isBefore(open) && !time.isAfter(close);
    }
    
    // 實際應(yīng)用:生成時間表
    public static List<LocalTime> generateTimeSchedule(LocalTime start, int intervalMinutes, int count) {
        List<LocalTime> schedule = new ArrayList<>();
        LocalTime current = start;
        for (int i = 0; i < count; i++) {
            schedule.add(current);
            current = current.plusMinutes(intervalMinutes);
        }
        return schedule;
    }
}

LocalDateTime:日期時間組合

LocalDateTime基礎(chǔ)操作

import java.time.*;
import java.time.format.*;
import java.time.temporal.*;

public class LocalDateTimeExample {
    
    public static void main(String[] args) {
        System.out.println("=== LocalDateTime 基礎(chǔ)操作 ===");
        
        // 1. 創(chuàng)建LocalDateTime的多種方式
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime specificDateTime = LocalDateTime.of(2023, 11, 15, 14, 30, 45);
        LocalDateTime parsedDateTime = LocalDateTime.parse("2023-11-15T14:30:45");
        LocalDateTime fromDateAndTime = LocalDateTime.of(LocalDate.now(), LocalTime.now());
        
        System.out.println("現(xiàn)在: " + now);
        System.out.println("指定日期時間: " + specificDateTime);
        System.out.println("解析日期時間: " + parsedDateTime);
        System.out.println("從日期和時間組合: " + fromDateAndTime);
        
        // 2. 轉(zhuǎn)換操作
        System.out.println("\n轉(zhuǎn)換操作:");
        LocalDate datePart = now.toLocalDate();
        LocalTime timePart = now.toLocalTime();
        System.out.println("日期部分: " + datePart);
        System.out.println("時間部分: " + timePart);
        
        // 3. 日期時間運算
        System.out.println("\n日期時間運算:");
        System.out.println("3天后: " + now.plusDays(3));
        System.out.println("2周后: " + now.plusWeeks(2));
        System.out.println("6個月后: " + now.plusMonths(6));
        System.out.println("1年2個月3天后: " + now.plusYears(1).plusMonths(2).plusDays(3));
        
        System.out.println("5小時前: " + now.minusHours(5));
        System.out.println("30分鐘前: " + now.minusMinutes(30));
        
        // 4. 日期時間比較
        LocalDateTime futureDateTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0);
        System.out.println("\n日期時間比較:");
        System.out.println(now + " 在 " + futureDateTime + " 之前? " + now.isBefore(futureDateTime));
        System.out.println(now + " 在 " + futureDateTime + " 之后? " + now.isAfter(futureDateTime));
        
        // 5. 日期時間調(diào)整
        System.out.println("\n日期時間調(diào)整:");
        System.out.println("調(diào)整到當(dāng)月第一天: " + now.with(TemporalAdjusters.firstDayOfMonth()));
        System.out.println("調(diào)整到下個周一上午9點: " + 
            now.with(TemporalAdjusters.next(DayOfWeek.MONDAY)).withHour(9).withMinute(0));
        
        // 6. 格式化與解析
        System.out.println("\n格式化與解析:");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
        String formatted = now.format(formatter);
        System.out.println("格式化后: " + formatted);
        
        LocalDateTime parsed = LocalDateTime.parse("2023年11月15日 14:30:00", formatter);
        System.out.println("解析后: " + parsed);
        
        // 7. 自定義格式化器
        System.out.println("\n自定義格式化:");
        DateTimeFormatter customFormatter = new DateTimeFormatterBuilder()
            .appendPattern("yyyy/MM/dd")
            .appendLiteral(" ")
            .appendPattern("HH:mm")
            .toFormatter();
        
        System.out.println("自定義格式: " + now.format(customFormatter));
        
        // 8. 與時間戳的轉(zhuǎn)換
        System.out.println("\n與時間戳轉(zhuǎn)換:");
        Instant instant = now.atZone(ZoneId.systemDefault()).toInstant();
        long epochMilli = instant.toEpochMilli();
        System.out.println("時間戳: " + epochMilli);
        
        LocalDateTime fromTimestamp = LocalDateTime.ofInstant(
            Instant.ofEpochMilli(epochMilli), 
            ZoneId.systemDefault()
        );
        System.out.println("從時間戳恢復(fù): " + fromTimestamp);
    }
    
    // 實際應(yīng)用:計算項目截止日期
    public static LocalDateTime calculateDeadline(LocalDateTime startDate, int workingDays) {
        LocalDateTime deadline = startDate;
        int daysAdded = 0;
        
        while (daysAdded < workingDays) {
            deadline = deadline.plusDays(1);
            DayOfWeek dayOfWeek = deadline.getDayOfWeek();
            if (dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY) {
                daysAdded++;
            }
        }
        return deadline;
    }
    
    // 實際應(yīng)用:檢查是否在維護窗口
    public static boolean isInMaintenanceWindow(LocalDateTime dateTime) {
        LocalTime start = LocalTime.of(2, 0); // 凌晨2點
        LocalTime end = LocalTime.of(4, 0);   // 凌晨4點
        DayOfWeek day = dateTime.getDayOfWeek();
        
        // 假設(shè)每周日2-4點維護
        return day == DayOfWeek.SUNDAY && 
               !dateTime.toLocalTime().isBefore(start) && 
               dateTime.toLocalTime().isBefore(end);
    }
    
    // 實際應(yīng)用:生成時間軸
    public static Map<LocalDateTime, String> generateTimeline(LocalDateTime start, int intervalHours, int count) {
        Map<LocalDateTime, String> timeline = new LinkedHashMap<>();
        LocalDateTime current = start;
        
        for (int i = 0; i < count; i++) {
            timeline.put(current, "事件 " + (i + 1));
            current = current.plusHours(intervalHours);
        }
        
        return timeline;
    }
}

時區(qū)處理:ZonedDateTime和OffsetDateTime

時區(qū)處理實戰(zhàn)

import java.time.*;
import java.time.format.*;
import java.util.*;

public class TimeZoneExample {
    
    public static void main(String[] args) {
        System.out.println("=== 時區(qū)處理實戰(zhàn) ===");
        
        // 1. 時區(qū)基礎(chǔ)
        System.out.println("\n1. 時區(qū)基礎(chǔ):");
        Set<String> allZoneIds = ZoneId.getAvailableZoneIds();
        System.out.println("可用時區(qū)數(shù)量: " + allZoneIds.size());
        System.out.println("前10個時區(qū):");
        allZoneIds.stream().sorted().limit(10).forEach(System.out::println);
        
        // 2. 創(chuàng)建帶時區(qū)的時間
        System.out.println("\n2. 創(chuàng)建帶時區(qū)的時間:");
        ZonedDateTime nowInTokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
        ZonedDateTime nowInNewYork = ZonedDateTime.now(ZoneId.of("America/New_York"));
        ZonedDateTime nowInLondon = ZonedDateTime.now(ZoneId.of("Europe/London"));
        
        System.out.println("東京時間: " + nowInTokyo);
        System.out.println("紐約時間: " + nowInNewYork);
        System.out.println("倫敦時間: " + nowInLondon);
        
        // 3. 時區(qū)轉(zhuǎn)換
        System.out.println("\n3. 時區(qū)轉(zhuǎn)換:");
        ZonedDateTime tokyoTime = ZonedDateTime.of(
            LocalDateTime.of(2023, 11, 15, 14, 30),
            ZoneId.of("Asia/Tokyo")
        );
        
        ZonedDateTime newYorkTime = tokyoTime.withZoneSameInstant(ZoneId.of("America/New_York"));
        ZonedDateTime londonTime = tokyoTime.withZoneSameInstant(ZoneId.of("Europe/London"));
        
        System.out.println("東京 14:30 相當(dāng)于:");
        System.out.println("  紐約: " + newYorkTime.toLocalDateTime() + " (" + newYorkTime.getZone() + ")");
        System.out.println("  倫敦: " + londonTime.toLocalDateTime() + " (" + londonTime.getZone() + ")");
        
        // 4. 夏令時處理
        System.out.println("\n4. 夏令時測試:");
        testDaylightSavingTime();
        
        // 5. OffsetDateTime(固定時區(qū)偏移)
        System.out.println("\n5. OffsetDateTime:");
        OffsetDateTime offsetDateTime = OffsetDateTime.now(ZoneOffset.ofHours(8));
        System.out.println("UTC+8時間: " + offsetDateTime);
        
        // 6. 時區(qū)偏移計算
        System.out.println("\n6. 時區(qū)偏移計算:");
        ZoneId tokyoZone = ZoneId.of("Asia/Tokyo");
        ZoneId newYorkZone = ZoneId.of("America/New_York");
        
        Instant instant = Instant.now();
        ZoneOffset tokyoOffset = tokyoZone.getRules().getOffset(instant);
        ZoneOffset newYorkOffset = newYorkZone.getRules().getOffset(instant);
        
        System.out.println("東京時區(qū)偏移: " + tokyoOffset);
        System.out.println("紐約時區(qū)偏移: " + newYorkOffset);
        System.out.println("時差: " + 
            Duration.between(
                instant.atOffset(tokyoOffset).toLocalTime(),
                instant.atOffset(newYorkOffset).toLocalTime()
            ).toHours() + " 小時"
        );
        
        // 7. 實際應(yīng)用:全球會議時間
        System.out.println("\n7. 實際應(yīng)用:全球會議時間安排:");
        scheduleGlobalMeeting();
    }
    
    // 測試夏令時
    public static void testDaylightSavingTime() {
        ZoneId nyZone = ZoneId.of("America/New_York");
        
        // 紐約2023年夏令時開始于3月12日
        LocalDateTime beforeDST = LocalDateTime.of(2023, 3, 12, 1, 30);
        LocalDateTime afterDST = LocalDateTime.of(2023, 3, 12, 3, 30);
        
        ZonedDateTime zonedBefore = ZonedDateTime.of(beforeDST, nyZone);
        ZonedDateTime zonedAfter = ZonedDateTime.of(afterDST, nyZone);
        
        System.out.println("夏令時變化前: " + zonedBefore);
        System.out.println("夏令時變化后: " + zonedAfter);
        System.out.println("是否在夏令時中: " + zonedAfter.getZone().getRules().isDaylightSavings(zonedAfter.toInstant()));
        
        // 檢查轉(zhuǎn)換
        System.out.println("\n驗證轉(zhuǎn)換:");
        System.out.println("轉(zhuǎn)換到倫敦時間:");
        System.out.println("  前: " + zonedBefore.withZoneSameInstant(ZoneId.of("Europe/London")));
        System.out.println("  后: " + zonedAfter.withZoneSameInstant(ZoneId.of("Europe/London")));
    }
    
    // 安排全球會議
    public static void scheduleGlobalMeeting() {
        System.out.println("=== 全球會議安排 ===");
        
        // 假設(shè)會議在舊金山時間上午9點
        LocalDateTime meetingTime = LocalDateTime.of(2023, 11, 15, 9, 0);
        ZonedDateTime meetingSF = ZonedDateTime.of(meetingTime, ZoneId.of("America/Los_Angeles"));
        
        System.out.println("會議時間(舊金山): " + meetingSF);
        
        // 轉(zhuǎn)換到其他城市
        String[] cities = {
            "Asia/Shanghai",      // 上海
            "Asia/Tokyo",         // 東京
            "Europe/London",      // 倫敦
            "Europe/Paris",       // 巴黎
            "America/New_York",   // 紐約
            "Australia/Sydney"    // 悉尼
        };
        
        System.out.println("\n各城市會議時間:");
        for (String city : cities) {
            ZonedDateTime cityTime = meetingSF.withZoneSameInstant(ZoneId.of(city));
            System.out.printf("%-20s: %s%n", 
                city.split("/")[1], 
                cityTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm (zzz)"))
            );
        }
    }
    
    // 計算飛行時間(考慮時區(qū))
    public static Duration calculateFlightDuration(ZonedDateTime departure, ZonedDateTime arrival) {
        return Duration.between(departure, arrival);
    }
    
    // 檢查是否在營業(yè)時間內(nèi)(考慮時區(qū))
    public static boolean isBusinessHourGlobal(ZonedDateTime time, ZoneId businessZone, 
                                              LocalTime open, LocalTime close) {
        ZonedDateTime businessZoneTime = time.withZoneSameInstant(businessZone);
        LocalTime localTime = businessZoneTime.toLocalTime();
        
        return !localTime.isBefore(open) && !localTime.isAfter(close);
    }
}

Instant和Duration:時間點與時間段

Instant和Duration實戰(zhàn)

import java.time.*;
import java.time.temporal.*;
import java.util.concurrent.TimeUnit;

public class InstantDurationExample {
    
    public static void main(String[] args) throws Exception {
        System.out.println("=== Instant 和 Duration 實戰(zhàn) ===");
        
        // 1. Instant:時間點(時間戳)
        System.out.println("\n1. Instant - 時間點:");
        
        Instant now = Instant.now();
        Instant specificInstant = Instant.ofEpochMilli(1699999999999L);
        Instant parsedInstant = Instant.parse("2023-11-15T14:30:45.123Z");
        
        System.out.println("當(dāng)前時刻: " + now);
        System.out.println("指定時間戳: " + specificInstant);
        System.out.println("解析的ISO格式: " + parsedInstant);
        
        // 獲取時間戳
        System.out.println("\n時間戳獲取:");
        System.out.println("毫秒時間戳: " + now.toEpochMilli());
        System.out.println("秒時間戳: " + now.getEpochSecond());
        System.out.println("納秒部分: " + now.getNano());
        
        // 2. Instant運算
        System.out.println("\n2. Instant運算:");
        System.out.println("1小時后: " + now.plus(1, ChronoUnit.HOURS));
        System.out.println("30分鐘后: " + now.plus(30, ChronoUnit.MINUTES));
        System.out.println("1天前: " + now.minus(1, ChronoUnit.DAYS));
        System.out.println("500毫秒前: " + now.minus(500, ChronoUnit.MILLIS));
        
        // 3. Duration:時間段(基于時間)
        System.out.println("\n3. Duration - 時間段:");
        
        Duration oneHour = Duration.ofHours(1);
        Duration thirtyMinutes = Duration.ofMinutes(30);
        Duration customDuration = Duration.of(90, ChronoUnit.SECONDS);
        Duration parsedDuration = Duration.parse("PT1H30M"); // ISO-8601格式
        
        System.out.println("1小時: " + oneHour);
        System.out.println("30分鐘: " + thirtyMinutes);
        System.out.println("90秒: " + customDuration);
        System.out.println("解析1小時30分鐘: " + parsedDuration);
        
        // 4. Duration運算
        System.out.println("\n4. Duration運算:");
        System.out.println("1小時 + 30分鐘 = " + oneHour.plus(thirtyMinutes));
        System.out.println("2小時 - 30分鐘 = " + Duration.ofHours(2).minus(thirtyMinutes));
        System.out.println("30分鐘 × 2 = " + thirtyMinutes.multipliedBy(2));
        System.out.println("1小時 ÷ 2 = " + oneHour.dividedBy(2));
        
        // 5. 獲取Duration各部分
        System.out.println("\n5. Duration分解:");
        Duration complexDuration = Duration.ofHours(25).plusMinutes(90);
        System.out.println("25小時90分鐘分解:");
        System.out.println("  總天數(shù): " + complexDuration.toDays());
        System.out.println("  總小時數(shù): " + complexDuration.toHours());
        System.out.println("  總分鐘數(shù): " + complexDuration.toMinutes());
        System.out.println("  總秒數(shù): " + complexDuration.toSeconds());
        System.out.println("  總毫秒數(shù): " + complexDuration.toMillis());
        System.out.println("  總納秒數(shù): " + complexDuration.toNanos());
        
        System.out.println("\n各部分:");
        System.out.println("  小時部分: " + complexDuration.toHoursPart());
        System.out.println("  分鐘部分: " + complexDuration.toMinutesPart());
        System.out.println("  秒部分: " + complexDuration.toSecondsPart());
        
        // 6. Period:時間段(基于日期)
        System.out.println("\n6. Period - 基于日期的時間段:");
        
        Period oneYear = Period.ofYears(1);
        Period sixMonths = Period.ofMonths(6);
        Period complexPeriod = Period.of(1, 6, 15); // 1年6個月15天
        Period parsedPeriod = Period.parse("P1Y6M15D"); // ISO-8601格式
        
        System.out.println("1年: " + oneYear);
        System.out.println("6個月: " + sixMonths);
        System.out.println("1年6個月15天: " + complexPeriod);
        System.out.println("解析的Period: " + parsedPeriod);
        
        // 7. 實際應(yīng)用:計算兩個日期之間的時間段
        System.out.println("\n7. 實際應(yīng)用:計算時間段:");
        
        LocalDate birthDate = LocalDate.of(1990, 5, 15);
        LocalDate today = LocalDate.now();
        
        Period age = Period.between(birthDate, today);
        System.out.println("年齡: " + age.getYears() + "年 " + 
                         age.getMonths() + "個月 " + 
                         age.getDays() + "天");
        
        // 8. 實際應(yīng)用:性能測量
        System.out.println("\n8. 性能測量示例:");
        measurePerformance();
        
        // 9. 實際應(yīng)用:超時控制
        System.out.println("\n9. 超時控制示例:");
        timeoutControl();
    }
    
    // 性能測量
    public static void measurePerformance() {
        Instant start = Instant.now();
        
        // 模擬耗時操作
        try {
            TimeUnit.MILLISECONDS.sleep(1500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        Instant end = Instant.now();
        Duration elapsed = Duration.between(start, end);
        
        System.out.println("操作耗時: " + elapsed.toMillis() + " 毫秒");
        System.out.println("操作耗時: " + elapsed.getSeconds() + " 秒 " + 
                         elapsed.toMillisPart() + " 毫秒");
        
        // 格式化輸出
        if (elapsed.toMinutes() > 0) {
            System.out.printf("格式化: %d分 %d秒 %d毫秒%n",
                elapsed.toMinutes(),
                elapsed.toSecondsPart(),
                elapsed.toMillisPart());
        } else {
            System.out.printf("格式化: %d秒 %d毫秒%n",
                elapsed.toSeconds(),
                elapsed.toMillisPart());
        }
    }
    
    // 超時控制
    public static void timeoutControl() {
        Duration timeout = Duration.ofSeconds(3);
        Instant startTime = Instant.now();
        
        System.out.println("開始執(zhí)行,超時時間: " + timeout.getSeconds() + "秒");
        
        try {
            // 模擬長時間操作
            for (int i = 1; i <= 10; i++) {
                // 檢查是否超時
                Duration elapsed = Duration.between(startTime, Instant.now());
                if (elapsed.compareTo(timeout) > 0) {
                    System.out.println("操作超時!");
                    break;
                }
                
                System.out.println("第 " + i + " 步");
                TimeUnit.MILLISECONDS.sleep(500);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        Duration totalTime = Duration.between(startTime, Instant.now());
        System.out.println("總耗時: " + totalTime.toMillis() + "毫秒");
    }
    
    // 計算兩個時刻之間的精確時間段
    public static String formatDurationBetween(Instant start, Instant end) {
        Duration duration = Duration.between(start, end);
        
        long days = duration.toDays();
        long hours = duration.toHoursPart();
        long minutes = duration.toMinutesPart();
        long seconds = duration.toSecondsPart();
        long millis = duration.toMillisPart();
        
        StringBuilder sb = new StringBuilder();
        if (days > 0) sb.append(days).append("天 ");
        if (hours > 0 || days > 0) sb.append(hours).append("小時 ");
        if (minutes > 0 || hours > 0 || days > 0) sb.append(minutes).append("分 ");
        sb.append(seconds).append("秒 ");
        sb.append(millis).append("毫秒");
        
        return sb.toString();
    }
    
    // 計算工作日的持續(xù)時間
    public static Duration calculateWorkingDuration(LocalDateTime start, LocalDateTime end) {
        Duration totalDuration = Duration.between(start, end);
        
        // 計算包含的周末天數(shù)
        long weekendDays = 0;
        LocalDate currentDate = start.toLocalDate();
        LocalDate endDate = end.toLocalDate();
        
        while (!currentDate.isAfter(endDate)) {
            DayOfWeek dayOfWeek = currentDate.getDayOfWeek();
            if (dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY) {
                weekendDays++;
            }
            currentDate = currentDate.plusDays(1);
        }
        
        // 減去周末的時間
        Duration weekendDuration = Duration.ofDays(weekendDays);
        return totalDuration.minus(weekendDuration);
    }
}

格式化與解析

高級格式化與解析

import java.time.*;
import java.time.format.*;
import java.time.temporal.*;
import java.util.Locale;

public class DateTimeFormatting {
    
    public static void main(String[] args) {
        System.out.println("=== 日期時間格式化與解析 ===");
        
        LocalDateTime now = LocalDateTime.now();
        
        // 1. 預(yù)定義的格式化器
        System.out.println("\n1. 預(yù)定義的格式化器:");
        
        System.out.println("ISO格式: " + now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        System.out.println("ISO日期: " + now.format(DateTimeFormatter.ISO_LOCAL_DATE));
        System.out.println("ISO時間: " + now.format(DateTimeFormatter.ISO_LOCAL_TIME));
        
        // 2. 自定義模式
        System.out.println("\n2. 自定義模式:");
        
        DateTimeFormatter[] formatters = {
            DateTimeFormatter.ofPattern("yyyy-MM-dd"),
            DateTimeFormatter.ofPattern("dd/MM/yyyy"),
            DateTimeFormatter.ofPattern("yyyy年MM月dd日"),
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"),
            DateTimeFormatter.ofPattern("EEEE, MMMM dd, yyyy"), // 星期,月份,日,年
            DateTimeFormatter.ofPattern("hh:mm a"),            // 12小時制
            DateTimeFormatter.ofPattern("yyyy年 第Q季度"),       // 季度
            DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX") // 帶時區(qū)偏移
        };
        
        for (DateTimeFormatter formatter : formatters) {
            System.out.println(formatter.format(now) + "  <- " + 
                             formatter.toString().replaceAll(".*\[", "["));
        }
        
        // 3. 本地化格式化
        System.out.println("\n3. 本地化格式化:");
        
        Locale[] locales = {Locale.US, Locale.UK, Locale.GERMANY, Locale.JAPAN, Locale.CHINA};
        DateTimeFormatter localizedFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
        
        for (Locale locale : locales) {
            DateTimeFormatter localeSpecific = localizedFormatter.withLocale(locale);
            System.out.println(locale.getDisplayName() + ": " + localeSpecific.format(now));
        }
        
        // 4. 格式化器構(gòu)建器(復(fù)雜格式化)
        System.out.println("\n4. 格式化器構(gòu)建器:");
        
        DateTimeFormatter complexFormatter = new DateTimeFormatterBuilder()
            .appendLiteral("日期: ")
            .appendValue(ChronoField.YEAR, 4)
            .appendLiteral("年")
            .appendValue(ChronoField.MONTH_OF_YEAR, 2)
            .appendLiteral("月")
            .appendValue(ChronoField.DAY_OF_MONTH, 2)
            .appendLiteral("日")
            .appendLiteral(" 時間: ")
            .appendValue(ChronoField.HOUR_OF_DAY, 2)
            .appendLiteral(":")
            .appendValue(ChronoField.MINUTE_OF_HOUR, 2)
            .appendLiteral(":")
            .appendValue(ChronoField.SECOND_OF_MINUTE, 2)
            .optionalStart() // 可選部分
            .appendLiteral(".")
            .appendValue(ChronoField.MILLI_OF_SECOND, 3)
            .optionalEnd()
            .toFormatter();
        
        System.out.println("復(fù)雜格式化: " + complexFormatter.format(now));
        
        // 5. 解析日期時間
        System.out.println("\n5. 解析日期時間:");
        
        String[] dateStrings = {
            "2023-11-15",
            "15/11/2023",
            "2023年11月15日",
            "2023-11-15 14:30:45",
            "November 15, 2023"
        };
        
        DateTimeFormatter[] parsers = {
            DateTimeFormatter.ofPattern("yyyy-MM-dd"),
            DateTimeFormatter.ofPattern("dd/MM/yyyy"),
            DateTimeFormatter.ofPattern("yyyy年MM月dd日"),
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),
            DateTimeFormatter.ofPattern("MMMM dd, yyyy", Locale.US)
        };
        
        for (int i = 0; i < dateStrings.length; i++) {
            try {
                TemporalAccessor parsed = parsers[i].parse(dateStrings[i]);
                System.out.println(dateStrings[i] + " -> 解析成功");
            } catch (DateTimeParseException e) {
                System.out.println(dateStrings[i] + " -> 解析失敗: " + e.getMessage());
            }
        }
        
        // 6. 寬松解析與嚴格解析
        System.out.println("\n6. 寬松解析與嚴格解析:");
        
        String looseDate = "2023-2-31"; // 2月31日不存在
        DateTimeFormatter lenientFormatter = DateTimeFormatter.ofPattern("yyyy-M-d")
            .withResolverStyle(ResolverStyle.LENIENT);
        DateTimeFormatter strictFormatter = DateTimeFormatter.ofPattern("yyyy-M-d")
            .withResolverStyle(ResolverStyle.STRICT);
        
        try {
            LocalDate parsedLenient = LocalDate.parse(looseDate, lenientFormatter);
            System.out.println("寬松解析成功: " + parsedLenient); // 會自動調(diào)整到3月3日
        } catch (DateTimeParseException e) {
            System.out.println("寬松解析失敗: " + e.getMessage());
        }
        
        try {
            LocalDate parsedStrict = LocalDate.parse(looseDate, strictFormatter);
            System.out.println("嚴格解析成功: " + parsedStrict);
        } catch (DateTimeParseException e) {
            System.out.println("嚴格解析失敗: " + e.getMessage());
        }
        
        // 7. 實際應(yīng)用:多格式解析器
        System.out.println("\n7. 多格式解析器:");
        
        String[] possibleFormats = {
            "yyyy-MM-dd",
            "yyyy/MM/dd",
            "dd-MM-yyyy",
            "dd/MM/yyyy",
            "yyyy.MM.dd",
            "MMM dd, yyyy",
            "dd MMM yyyy"
        };
        
        String testDate = "15/11/2023";
        LocalDate result = parseWithMultipleFormats(testDate, possibleFormats);
        System.out.println("多格式解析結(jié)果: " + result);
        
        // 8. 自定義格式化擴展
        System.out.println("\n8. 自定義格式化擴展:");
        
        DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
            .withZone(ZoneId.of("Asia/Shanghai"))
            .withDecimalStyle(DecimalStyle.STANDARD)
            .withChronology(IsoChronology.INSTANCE);
        
        ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
        System.out.println("帶時區(qū)格式化: " + customFormatter.format(zonedDateTime));
    }
    
    // 多格式解析器實現(xiàn)
    public static LocalDate parseWithMultipleFormats(String dateString, String[] formats) {
        for (String format : formats) {
            try {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
                return LocalDate.parse(dateString, formatter);
            } catch (DateTimeParseException e) {
                // 繼續(xù)嘗試下一個格式
                continue;
            }
        }
        throw new IllegalArgumentException("無法解析日期: " + dateString);
    }
    
    // 智能日期解析
    public static LocalDate smartDateParse(String input) {
        // 移除常見的分隔符,統(tǒng)一處理
        String normalized = input.replaceAll("[/.-]", "-");
        
        // 嘗試常見格式
        String[] patterns = {
            "yyyy-MM-dd",
            "yyyy-M-d",
            "yy-MM-dd",
            "yy-M-d",
            "MM-dd-yyyy",
            "M-d-yyyy",
            "dd-MM-yyyy",
            "d-M-yyyy"
        };
        
        for (String pattern : patterns) {
            try {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
                return LocalDate.parse(normalized, formatter);
            } catch (DateTimeParseException e) {
                continue;
            }
        }
        
        // 嘗試文本月份
        patterns = new String[]{
            "MMM dd, yyyy",
            "MMM d, yyyy",
            "MMMM dd, yyyy",
            "MMMM d, yyyy",
            "dd MMM yyyy",
            "d MMM yyyy"
        };
        
        for (String pattern : patterns) {
            try {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern, Locale.ENGLISH);
                return LocalDate.parse(input, formatter);
            } catch (DateTimeParseException e) {
                continue;
            }
        }
        
        throw new IllegalArgumentException("無法識別的日期格式: " + input);
    }
    
    // 生成可讀的時間間隔描述
    public static String formatTimeAgo(LocalDateTime pastTime) {
        Duration duration = Duration.between(pastTime, LocalDateTime.now());
        
        if (duration.toDays() > 365) {
            long years = duration.toDays() / 365;
            return years + "年前";
        } else if (duration.toDays() > 30) {
            long months = duration.toDays() / 30;
            return months + "個月前";
        } else if (duration.toDays() > 0) {
            return duration.toDays() + "天前";
        } else if (duration.toHours() > 0) {
            return duration.toHours() + "小時前";
        } else if (duration.toMinutes() > 0) {
            return duration.toMinutes() + "分鐘前";
        } else {
            return "剛剛";
        }
    }
    
    // 生成日歷視圖
    public static void printCalendar(int year, int month) {
        LocalDate firstDay = LocalDate.of(year, month, 1);
        DayOfWeek firstDayOfWeek = firstDay.getDayOfWeek();
        int daysInMonth = firstDay.lengthOfMonth();
        
        System.out.printf("\n     %d年 %d月\n", year, month);
        System.out.println("日 一 二 三 四 五 六");
        
        // 打印前面的空白
        for (int i = 0; i < firstDayOfWeek.getValue() % 7; i++) {
            System.out.print("   ");
        }
        
        // 打印日期
        for (int day = 1; day <= daysInMonth; day++) {
            System.out.printf("%2d ", day);
            
            // 換行
            if ((firstDayOfWeek.getValue() % 7 + day) % 7 == 0) {
                System.out.println();
            }
        }
        System.out.println();
    }
}

實戰(zhàn):完整的企業(yè)級應(yīng)用

import java.time.*;
import java.time.format.*;
import java.time.temporal.*;
import java.util.*;
import java.util.concurrent.*;

public class EnterpriseDateTimeApplication {
    
    // 1. 航班預(yù)訂系統(tǒng)
    static class FlightBookingSystem {
        
        static class Flight {
            String flightNumber;
            String airline;
            String departureAirport;
            String arrivalAirport;
            ZonedDateTime departureTime;
            ZonedDateTime arrivalTime;
            Duration flightDuration;
            
            public Flight(String flightNumber, String airline, String departureAirport, 
                         String arrivalAirport, ZonedDateTime departureTime, 
                         ZonedDateTime arrivalTime) {
                this.flightNumber = flightNumber;
                this.airline = airline;
                this.departureAirport = departureAirport;
                this.arrivalAirport = arrivalAirport;
                this.departureTime = departureTime;
                this.arrivalTime = arrivalTime;
                this.flightDuration = Duration.between(departureTime, arrivalTime);
            }
            
            public boolean isOverlapping(Flight other) {
                return !(this.arrivalTime.isBefore(other.departureTime) || 
                        this.departureTime.isAfter(other.arrivalTime));
            }
            
            public Duration getLayoverTime(Flight connectingFlight) {
                if (!this.arrivalAirport.equals(connectingFlight.departureAirport)) {
                    throw new IllegalArgumentException("不是連續(xù)的航班");
                }
                return Duration.between(this.arrivalTime, connectingFlight.departureTime);
            }
            
            @Override
            public String toString() {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm (zzz)");
                return String.format("%s %s: %s [%s] -> %s [%s] 時長: %s",
                    airline, flightNumber,
                    departureTime.format(formatter),
                    departureAirport,
                    arrivalTime.format(formatter),
                    arrivalAirport,
                    formatDuration(flightDuration));
            }
            
            private String formatDuration(Duration duration) {
                long hours = duration.toHours();
                long minutes = duration.toMinutesPart();
                return String.format("%d小時%d分鐘", hours, minutes);
            }
        }
        
        public static void bookFlight() {
            System.out.println("=== 航班預(yù)訂系統(tǒng) ===");
            
            // 定義航班
            Flight flight1 = new Flight(
                "CA123",
                "中國航空",
                "北京首都國際機場 (PEK)",
                "上海浦東國際機場 (PVG)",
                ZonedDateTime.of(2023, 12, 1, 8, 0, 0, 0, ZoneId.of("Asia/Shanghai")),
                ZonedDateTime.of(2023, 12, 1, 10, 30, 0, 0, ZoneId.of("Asia/Shanghai"))
            );
            
            Flight flight2 = new Flight(
                "AA789",
                "美國航空",
                "上海浦東國際機場 (PVG)",
                "紐約肯尼迪機場 (JFK)",
                ZonedDateTime.of(2023, 12, 1, 13, 30, 0, 0, ZoneId.of("Asia/Shanghai")),
                ZonedDateTime.of(2023, 12, 1, 16, 0, 0, 0, ZoneId.of("America/New_York"))
            );
            
            System.out.println("航班1: " + flight1);
            System.out.println("航班2: " + flight2);
            
            // 檢查轉(zhuǎn)機時間
            Duration layover = flight1.getLayoverTime(flight2);
            System.out.println("\n轉(zhuǎn)機時間: " + 
                layover.toHours() + "小時" + layover.toMinutesPart() + "分鐘");
            
            if (layover.toHours() < 1) {
                System.out.println("?? 警告:轉(zhuǎn)機時間太短!");
            } else if (layover.toHours() > 4) {
                System.out.println("?? 警告:轉(zhuǎn)機時間太長!");
            } else {
                System.out.println("? 轉(zhuǎn)機時間合適");
            }
            
            // 顯示到達目的地的時間(按目的地時區(qū))
            ZonedDateTime arrivalInLocalTime = flight2.arrivalTime
                .withZoneSameInstant(ZoneId.of("America/New_York"));
            System.out.println("\n到達紐約時間: " + 
                arrivalInLocalTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm (zzz)")));
        }
    }
    
    // 2. 會議調(diào)度系統(tǒng)
    static class MeetingScheduler {
        
        static class Meeting {
            String title;
            String organizer;
            ZonedDateTime startTime;
            Duration duration;
            Set<String> participants;
            String location;
            
            public Meeting(String title, String organizer, ZonedDateTime startTime, 
                          Duration duration, Set<String> participants, String location) {
                this.title = title;
                this.organizer = organizer;
                this.startTime = startTime;
                this.duration = duration;
                this.participants = participants;
                this.location = location;
            }
            
            public ZonedDateTime getEndTime() {
                return startTime.plus(duration);
            }
            
            public boolean conflictsWith(Meeting other) {
                return !(this.getEndTime().isBefore(other.startTime) || 
                        this.startTime.isAfter(other.getEndTime()));
            }
            
            public Map<String, ZonedDateTime> getLocalTimesForParticipants() {
                Map<String, ZonedDateTime> localTimes = new HashMap<>();
                
                // 模擬從數(shù)據(jù)庫獲取參與者時區(qū)
                Map<String, String> participantTimezones = Map.of(
                    "張三", "Asia/Shanghai",
                    "李四", "America/New_York",
                    "王五", "Europe/London",
                    "山田", "Asia/Tokyo"
                );
                
                for (String participant : participants) {
                    String timezone = participantTimezones.getOrDefault(participant, "UTC");
                    localTimes.put(participant, 
                        startTime.withZoneSameInstant(ZoneId.of(timezone)));
                }
                
                return localTimes;
            }
            
            @Override
            public String toString() {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm (zzz)");
                return String.format("會議: %s\n組織者: %s\n時間: %s - %s\n地點: %s\n參與者: %s",
                    title, organizer,
                    startTime.format(formatter),
                    getEndTime().format(formatter),
                    location,
                    String.join(", ", participants));
            }
        }
        
        public static void scheduleMeeting() {
            System.out.println("\n=== 會議調(diào)度系統(tǒng) ===");
            
            Set<String> participants = new HashSet<>(Arrays.asList(
                "張三", "李四", "王五", "山田"
            ));
            
            Meeting meeting = new Meeting(
                "季度項目評審",
                "張三",
                ZonedDateTime.of(2023, 12, 15, 14, 0, 0, 0, ZoneId.of("Asia/Shanghai")),
                Duration.ofHours(2),
                participants,
                "會議室A"
            );
            
            System.out.println(meeting);
            
            // 顯示各參與者的本地時間
            System.out.println("\n各參與者的本地時間:");
            Map<String, ZonedDateTime> localTimes = meeting.getLocalTimesForParticipants();
            
            DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
            DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MM月dd日");
            
            for (Map.Entry<String, ZonedDateTime> entry : localTimes.entrySet()) {
                ZonedDateTime localTime = entry.getValue();
                System.out.printf("%-8s: %s %s%n",
                    entry.getKey(),
                    localTime.format(dateFormatter),
                    localTime.format(timeFormatter));
            }
            
            // 檢查時間是否合適
            System.out.println("\n時間合適性檢查:");
            for (Map.Entry<String, ZonedDateTime> entry : localTimes.entrySet()) {
                ZonedDateTime localTime = entry.getValue();
                LocalTime meetingLocalTime = localTime.toLocalTime();
                
                boolean isWorkingHour = meetingLocalTime.isAfter(LocalTime.of(9, 0)) &&
                                       meetingLocalTime.isBefore(LocalTime.of(18, 0));
                
                System.out.printf("%-8s: %s (%s)%n",
                    entry.getKey(),
                    isWorkingHour ? "? 工作時間" : "?? 非工作時間",
                    meetingLocalTime.format(DateTimeFormatter.ofPattern("HH:mm")));
            }
        }
    }
    
    // 3. 任務(wù)管理系統(tǒng)
    static class TaskManagementSystem {
        
        static class Task {
            String id;
            String title;
            String description;
            TaskPriority priority;
            LocalDateTime dueDate;
            Duration estimatedEffort;
            LocalDateTime actualStart;
            LocalDateTime actualEnd;
            TaskStatus status;
            
            enum TaskPriority { LOW, MEDIUM, HIGH, CRITICAL }
            enum TaskStatus { PENDING, IN_PROGRESS, BLOCKED, COMPLETED, CANCELLED }
            
            public Task(String id, String title, String description, TaskPriority priority,
                       LocalDateTime dueDate, Duration estimatedEffort) {
                this.id = id;
                this.title = title;
                this.description = description;
                this.priority = priority;
                this.dueDate = dueDate;
                this.estimatedEffort = estimatedEffort;
                this.status = TaskStatus.PENDING;
            }
            
            public void startTask() {
                this.actualStart = LocalDateTime.now();
                this.status = TaskStatus.IN_PROGRESS;
            }
            
            public void completeTask() {
                this.actualEnd = LocalDateTime.now();
                this.status = TaskStatus.COMPLETED;
            }
            
            public Duration getTimeSpent() {
                if (actualStart == null) return Duration.ZERO;
                if (actualEnd == null) return Duration.between(actualStart, LocalDateTime.now());
                return Duration.between(actualStart, actualEnd);
            }
            
            public Duration getTimeRemaining() {
                if (status == TaskStatus.COMPLETED) return Duration.ZERO;
                
                Duration timeSpent = getTimeSpent();
                if (timeSpent.compareTo(estimatedEffort) >= 0) {
                    return Duration.ZERO;
                }
                return estimatedEffort.minus(timeSpent);
            }
            
            public boolean isOverdue() {
                return status != TaskStatus.COMPLETED && 
                       LocalDateTime.now().isAfter(dueDate);
            }
            
            public Duration getOverdueDuration() {
                if (!isOverdue()) return Duration.ZERO;
                return Duration.between(dueDate, LocalDateTime.now());
            }
            
            public String getProgress() {
                if (status == TaskStatus.PENDING) return "0%";
                if (status == TaskStatus.COMPLETED) return "100%";
                
                if (estimatedEffort.isZero()) return "N/A";
                
                long spentMillis = getTimeSpent().toMillis();
                long totalMillis = estimatedEffort.toMillis();
                
                double progress = (double) spentMillis / totalMillis * 100;
                return String.format("%.1f%%", Math.min(100, progress));
            }
            
            @Override
            public String toString() {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
                return String.format("任務(wù): %s [%s]\n優(yōu)先級: %s\n截止時間: %s\n預(yù)估工作量: %s\n狀態(tài): %s\n進度: %s\n%s",
                    title, id,
                    priority,
                    dueDate.format(formatter),
                    formatDuration(estimatedEffort),
                    status,
                    getProgress(),
                    isOverdue() ? "?? 已超期 " + formatDuration(getOverdueDuration()) : "? 按時"
                );
            }
            
            private String formatDuration(Duration duration) {
                if (duration.toDays() > 0) {
                    return String.format("%d天%d小時", duration.toDays(), duration.toHoursPart());
                } else if (duration.toHours() > 0) {
                    return String.format("%d小時%d分鐘", duration.toHours(), duration.toMinutesPart());
                } else {
                    return String.format("%d分鐘", duration.toMinutes());
                }
            }
        }
        
        public static void manageTasks() {
            System.out.println("\n=== 任務(wù)管理系統(tǒng) ===");
            
            Task task1 = new Task(
                "TASK-001",
                "實現(xiàn)用戶登錄功能",
                "實現(xiàn)用戶登錄、注冊、忘記密碼功能",
                Task.TaskPriority.HIGH,
                LocalDateTime.of(2023, 11, 30, 18, 0),
                Duration.ofHours(16)
            );
            
            Task task2 = new Task(
                "TASK-002",
                "編寫單元測試",
                "為核心模塊編寫單元測試",
                Task.TaskPriority.MEDIUM,
                LocalDateTime.of(2023, 12, 5, 18, 0),
                Duration.ofHours(8)
            );
            
            task1.startTask();
            task1.completeTask();
            
            task2.startTask();
            // task2 正在進行中
            
            System.out.println(task1);
            System.out.println("\n---\n");
            System.out.println(task2);
            
            // 生成任務(wù)報告
            System.out.println("\n=== 任務(wù)報告 ===");
            List<Task> tasks = Arrays.asList(task1, task2);
            
            long totalEstimated = tasks.stream()
                .mapToLong(t -> t.estimatedEffort.toHours())
                .sum();
            
            long totalActual = tasks.stream()
                .mapToLong(t -> t.getTimeSpent().toHours())
                .sum();
            
            long overdueCount = tasks.stream()
                .filter(Task::isOverdue)
                .count();
            
            System.out.printf("總?cè)蝿?wù)數(shù): %d\n", tasks.size());
            System.out.printf("預(yù)估總工時: %d 小時\n", totalEstimated);
            System.out.printf("實際總工時: %d 小時\n", totalActual);
            System.out.printf("超期任務(wù)數(shù): %d\n", overdueCount);
            System.out.printf("完成率: %.1f%%\n", 
                tasks.stream().filter(t -> t.status == Task.TaskStatus.COMPLETED).count() * 100.0 / tasks.size());
        }
    }
    
    // 4. 緩存過期系統(tǒng)
    static class CacheExpirySystem<K, V> {
        private final ConcurrentHashMap<K, CacheEntry<V>> cache = new ConcurrentHashMap<>();
        private final ScheduledExecutorService cleaner = Executors.newScheduledThreadPool(1);
        
        static class CacheEntry<V> {
            V value;
            Instant expiryTime;
            
            CacheEntry(V value, Duration ttl) {
                this.value = value;
                this.expiryTime = Instant.now().plus(ttl);
            }
            
            boolean isExpired() {
                return Instant.now().isAfter(expiryTime);
            }
            
            Duration getTimeUntilExpiry() {
                return Duration.between(Instant.now(), expiryTime);
            }
        }
        
        public CacheExpirySystem() {
            // 每5秒清理一次過期緩存
            cleaner.scheduleAtFixedRate(this::cleanExpiredEntries, 5, 5, TimeUnit.SECONDS);
        }
        
        public void put(K key, V value, Duration ttl) {
            cache.put(key, new CacheEntry<>(value, ttl));
        }
        
        public V get(K key) {
            CacheEntry<V> entry = cache.get(key);
            if (entry == null || entry.isExpired()) {
                cache.remove(key);
                return null;
            }
            return entry.value;
        }
        
        public void remove(K key) {
            cache.remove(key);
        }
        
        public Set<K> getKeysAboutToExpire(Duration threshold) {
            Instant warningTime = Instant.now().plus(threshold);
            Set<K> result = new HashSet<>();
            
            for (Map.Entry<K, CacheEntry<V>> entry : cache.entrySet()) {
                if (entry.getValue().expiryTime.isBefore(warningTime)) {
                    result.add(entry.getKey());
                }
            }
            
            return result;
        }
        
        public Map<K, Duration> getExpiryTimes() {
            Map<K, Duration> result = new HashMap<>();
            
            for (Map.Entry<K, CacheEntry<V>> entry : cache.entrySet()) {
                result.put(entry.getKey(), entry.getValue().getTimeUntilExpiry());
            }
            
            return result;
        }
        
        private void cleanExpiredEntries() {
            cache.entrySet().removeIf(entry -> entry.getValue().isExpired());
        }
        
        public void shutdown() {
            cleaner.shutdown();
        }
        
        public void demonstrate() {
            System.out.println("\n=== 緩存過期系統(tǒng) ===");
            
            put("user:1001", "用戶數(shù)據(jù)A", Duration.ofSeconds(30));
            put("product:2001", "產(chǎn)品數(shù)據(jù)B", Duration.ofMinutes(1));
            put("config:3001", "配置數(shù)據(jù)C", Duration.ofHours(1));
            
            System.out.println("初始緩存狀態(tài):");
            getExpiryTimes().forEach((key, duration) -> 
                System.out.printf("  %s: %d秒后過期%n", key, duration.getSeconds())
            );
            
            System.out.println("\n30秒內(nèi)將過期的緩存:");
            getKeysAboutToExpire(Duration.ofSeconds(30)).forEach(key ->
                System.out.println("  " + key)
            );
            
            System.out.println("\n等待35秒后...");
            try {
                Thread.sleep(35000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            System.out.println("\n當(dāng)前緩存狀態(tài):");
            getExpiryTimes().forEach((key, duration) -> 
                System.out.printf("  %s: %d秒后過期%n", key, duration.getSeconds())
            );
            
            System.out.println("\n獲取user:1001: " + get("user:1001"));
        }
    }
    
    public static void main(String[] args) {
        // 運行各個系統(tǒng)
        FlightBookingSystem.bookFlight();
        MeetingScheduler.scheduleMeeting();
        TaskManagementSystem.manageTasks();
        
        CacheExpirySystem<String, String> cacheSystem = new CacheExpirySystem<>();
        cacheSystem.demonstrate();
        cacheSystem.shutdown();
    }
}

最佳實踐與性能優(yōu)化

import java.time.*;
import java.time.format.*;
import java.time.temporal.*;
import java.util.concurrent.*;

public class DateTimeBestPractices {
    
    // 1. 線程安全的日期時間格式化
    static class ThreadSafeFormatter {
        // ? 錯誤做法:SimpleDateFormat不是線程安全的
        // private static final SimpleDateFormat unsafeFormatter = new SimpleDateFormat("yyyy-MM-dd");
        
        // ? 正確做法:DateTimeFormatter是線程安全的
        private static final DateTimeFormatter safeFormatter = 
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        
        private static final Map<String, DateTimeFormatter> formatterCache = 
            new ConcurrentHashMap<>();
        
        public static DateTimeFormatter getFormatter(String pattern) {
            return formatterCache.computeIfAbsent(pattern, 
                p -> DateTimeFormatter.ofPattern(p));
        }
        
        public static String format(LocalDateTime dateTime, String pattern) {
            return dateTime.format(getFormatter(pattern));
        }
    }
    
    // 2. 日期時間對象池(針對高頻率創(chuàng)建場景)
    static class DateTimePool {
        private final ConcurrentLinkedQueue<LocalDateTime> pool = 
            new ConcurrentLinkedQueue<>();
        private final int maxSize;
        
        public DateTimePool(int maxSize) {
            this.maxSize = maxSize;
        }
        
        public LocalDateTime borrow() {
            LocalDateTime dt = pool.poll();
            return dt != null ? dt : LocalDateTime.now();
        }
        
        public void release(LocalDateTime dateTime) {
            if (pool.size() < maxSize) {
                pool.offer(dateTime);
            }
        }
    }
    
    // 3. 高效的時間比較
    static class EfficientDateTimeComparison {
        // 比較兩個時間段是否重疊
        public static boolean isOverlap(LocalDateTime start1, LocalDateTime end1,
                                       LocalDateTime start2, LocalDateTime end2) {
            // 使用時間戳比較,避免多次方法調(diào)用
            long s1 = start1.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
            long e1 = end1.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
            long s2 = start2.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
            long e2 = end2.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
            
            return !(e1 <= s2 || s1 >= e2);
        }
        
        // 批量檢查日期是否在范圍內(nèi)
        public static List<LocalDate> filterDatesInRange(List<LocalDate> dates,
                                                        LocalDate start, 
                                                        LocalDate end) {
            long startEpochDay = start.toEpochDay();
            long endEpochDay = end.toEpochDay();
            
            return dates.stream()
                .filter(date -> {
                    long epochDay = date.toEpochDay();
                    return epochDay >= startEpochDay && epochDay <= endEpochDay;
                })
                .collect(Collectors.toList());
        }
    }
    
    // 4. 避免常見的性能陷阱
    static class PerformancePitfalls {
        
        // ? 錯誤做法:在循環(huán)中重復(fù)創(chuàng)建格式化器
        public static void badPractice(List<LocalDateTime> dateTimes) {
            for (LocalDateTime dt : dateTimes) {
                // 每次循環(huán)都創(chuàng)建新的格式化器
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                String formatted = dt.format(formatter);
                // 使用 formatted...
            }
        }
        
        // ? 正確做法:重用格式化器
        public static void goodPractice(List<LocalDateTime> dateTimes) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            for (LocalDateTime dt : dateTimes) {
                String formatted = dt.format(formatter);
                // 使用 formatted...
            }
        }
        
        // ? 錯誤做法:不必要的時區(qū)轉(zhuǎn)換
        public static void badTimeZoneConversion() {
            LocalDateTime localDateTime = LocalDateTime.now();
            // 不必要的雙重轉(zhuǎn)換
            ZonedDateTime zoned = localDateTime.atZone(ZoneId.systemDefault());
            Instant instant = zoned.toInstant();
            // ...
        }
        
        // ? 正確做法:直接轉(zhuǎn)換
        public static void goodTimeZoneConversion() {
            LocalDateTime localDateTime = LocalDateTime.now();
            // 直接轉(zhuǎn)換為Instant
            Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
            // ...
        }
    }
    
    // 5. 內(nèi)存優(yōu)化:使用原始類型處理時間戳
    static class MemoryOptimizedTimeSeries {
        private final long[] timestamps;
        private final double[] values;
        private int size;
        
        public MemoryOptimizedTimeSeries(int capacity) {
            this.timestamps = new long[capacity];
            this.values = new double[capacity];
            this.size = 0;
        }
        
        public void addDataPoint(LocalDateTime timestamp, double value) {
            if (size >= timestamps.length) {
                throw new IllegalStateException("容量已滿");
            }
            
            // 存儲時間戳(毫秒)
            timestamps[size] = timestamp.atZone(ZoneId.systemDefault())
                                        .toInstant()
                                        .toEpochMilli();
            values[size] = value;
            size++;
        }
        
        public LocalDateTime getTimestamp(int index) {
            return LocalDateTime.ofInstant(
                Instant.ofEpochMilli(timestamps[index]),
                ZoneId.systemDefault()
            );
        }
        
        public double getValue(int index) {
            return values[index];
        }
        
        // 高效的時間范圍查詢
        public List<Integer> queryByTimeRange(LocalDateTime start, LocalDateTime end) {
            long startMillis = start.atZone(ZoneId.systemDefault())
                                   .toInstant()
                                   .toEpochMilli();
            long endMillis = end.atZone(ZoneId.systemDefault())
                               .toInstant()
                               .toEpochMilli();
            
            List<Integer> result = new ArrayList<>();
            for (int i = 0; i < size; i++) {
                if (timestamps[i] >= startMillis && timestamps[i] <= endMillis) {
                    result.add(i);
                }
            }
            return result;
        }
    }
    
    // 6. 基準測試:對比不同實現(xiàn)方式的性能
    static class DateTimeBenchmark {
        
        public static void benchmarkFormatting() {
            int iterations = 100000;
            LocalDateTime now = LocalDateTime.now();
            
            // 測試1:重復(fù)創(chuàng)建格式化器
            long start1 = System.nanoTime();
            for (int i = 0; i < iterations; i++) {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                String formatted = now.format(formatter);
            }
            long time1 = System.nanoTime() - start1;
            
            // 測試2:重用格式化器
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            long start2 = System.nanoTime();
            for (int i = 0; i < iterations; i++) {
                String formatted = now.format(formatter);
            }
            long time2 = System.nanoTime() - start2;
            
            System.out.println("=== 格式化性能測試 ===");
            System.out.printf("重復(fù)創(chuàng)建格式化器: %,d ns%n", time1);
            System.out.printf("重用格式化器: %,d ns%n", time2);
            System.out.printf("性能提升: %.1f%%%n", (time1 - time2) * 100.0 / time1);
        }
        
        public static void benchmarkComparison() {
            int iterations = 1000000;
            List<LocalDate> dates = new ArrayList<>();
            Random random = new Random();
            
            // 生成測試數(shù)據(jù)
            for (int i = 0; i < 1000; i++) {
                dates.add(LocalDate.now().plusDays(random.nextInt(365)));
            }
            
            LocalDate start = LocalDate.now().minusDays(180);
            LocalDate end = LocalDate.now().plusDays(180);
            
            // 測試不同的比較方法
            long startTime = System.nanoTime();
            long count1 = dates.stream()
                .filter(date -> date.isAfter(start) && date.isBefore(end))
                .count();
            long time1 = System.nanoTime() - startTime;
            
            startTime = System.nanoTime();
            long startEpochDay = start.toEpochDay();
            long endEpochDay = end.toEpochDay();
            long count2 = dates.stream()
                .filter(date -> {
                    long epochDay = date.toEpochDay();
                    return epochDay > startEpochDay && epochDay < endEpochDay;
                })
                .count();
            long time2 = System.nanoTime() - startTime;
            
            System.out.println("\n=== 日期比較性能測試 ===");
            System.out.printf("使用isAfter/isBefore: %,d ns%n", time1);
            System.out.printf("使用epochDay直接比較: %,d ns%n", time2);
            System.out.printf("性能提升: %.1f%%%n", (time1 - time2) * 100.0 / time1);
        }
    }
    
    // 7. 實用的工具方法
    static class DateTimeUtils {
        
        // 安全解析日期,支持多種格式
        public static Optional<LocalDate> safeParseDate(String dateStr) {
            String[] patterns = {
                "yyyy-MM-dd",
                "yyyy/MM/dd",
                "dd/MM/yyyy",
                "dd-MM-yyyy",
                "yyyy.MM.dd",
                "MM/dd/yyyy"
            };
            
            for (String pattern : patterns) {
                try {
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
                    return Optional.of(LocalDate.parse(dateStr, formatter));
                } catch (DateTimeParseException e) {
                    continue;
                }
            }
            
            return Optional.empty();
        }
        
        // 計算兩個日期之間的工作日
        public static long calculateWorkingDays(LocalDate start, LocalDate end) {
            return start.datesUntil(end.plusDays(1))
                .filter(date -> date.getDayOfWeek() != DayOfWeek.SATURDAY &&
                              date.getDayOfWeek() != DayOfWeek.SUNDAY)
                .count();
        }
        
        // 獲取下一個工作日
        public static LocalDate getNextWorkingDay(LocalDate date) {
            LocalDate nextDay = date.plusDays(1);
            while (nextDay.getDayOfWeek() == DayOfWeek.SATURDAY || 
                   nextDay.getDayOfWeek() == DayOfWeek.SUNDAY) {
                nextDay = nextDay.plusDays(1);
            }
            return nextDay;
        }
        
        // 格式化時間差為可讀字符串
        public static String formatDurationReadable(Duration duration) {
            if (duration.isNegative()) {
                return "已過期";
            }
            
            if (duration.toDays() > 0) {
                return String.format("%d天%d小時", duration.toDays(), duration.toHoursPart());
            } else if (duration.toHours() > 0) {
                return String.format("%d小時%d分鐘", duration.toHours(), duration.toMinutesPart());
            } else if (duration.toMinutes() > 0) {
                return String.format("%d分鐘", duration.toMinutes());
            } else {
                return String.format("%d秒", duration.toSeconds());
            }
        }
        
        // 檢查是否是營業(yè)時間(考慮周末和節(jié)假日)
        public static boolean isBusinessTime(LocalDateTime dateTime, 
                                            Set<LocalDate> holidays) {
            // 檢查是否是周末
            DayOfWeek dayOfWeek = dateTime.getDayOfWeek();
            if (dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY) {
                return false;
            }
            
            // 檢查是否是節(jié)假日
            if (holidays.contains(dateTime.toLocalDate())) {
                return false;
            }
            
            // 檢查時間是否在營業(yè)時間內(nèi)(假設(shè)9:00-18:00)
            LocalTime time = dateTime.toLocalTime();
            return !time.isBefore(LocalTime.of(9, 0)) && 
                   !time.isAfter(LocalTime.of(18, 0));
        }
    }
    
    public static void main(String[] args) {
        System.out.println("=== 日期時間API最佳實踐 ===");
        
        // 運行性能測試
        DateTimeBenchmark.benchmarkFormatting();
        DateTimeBenchmark.benchmarkComparison();
        
        // 演示實用工具方法
        System.out.println("\n=== 實用工具方法演示 ===");
        
        LocalDate today = LocalDate.now();
        System.out.println("今天: " + today);
        System.out.println("下一個工作日: " + DateTimeUtils.getNextWorkingDay(today));
        
        LocalDate start = today.minusDays(30);
        LocalDate end = today.plusDays(30);
        System.out.printf("%s 到 %s 之間的工作日: %d天%n", 
            start, end, DateTimeUtils.calculateWorkingDays(start, end));
        
        // 測試安全解析
        String[] testDates = {"2023-11-15", "15/11/2023", "2023.11.15", "無效日期"};
        for (String testDate : testDates) {
            Optional<LocalDate> parsed = DateTimeUtils.safeParseDate(testDate);
            System.out.printf("解析 '%s': %s%n", 
                testDate, 
                parsed.map(LocalDate::toString).orElse("解析失敗"));
        }
        
        // 演示緩存系統(tǒng)
        System.out.println("\n=== 線程安全格式化演示 ===");
        ExecutorService executor = Executors.newFixedThreadPool(10);
        List<Future<String>> futures = new ArrayList<>();
        
        for (int i = 0; i < 100; i++) {
            final int index = i;
            futures.add(executor.submit(() -> 
                ThreadSafeFormatter.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss") + 
                " - 線程" + index
            ));
        }
        
        for (Future<String> future : futures) {
            try {
                System.out.println(future.get());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        executor.shutdown();
    }
}

總結(jié):Java 8日期時間API的核心要點

主要優(yōu)勢

  • 不可變性:所有核心類都是不可變的,線程安全
  • 清晰的API設(shè)計:分離了日期、時間、時區(qū)等概念
  • 強大的時區(qū)支持:內(nèi)置完善的時區(qū)處理機制
  • 流暢的鏈式調(diào)用:代碼更易讀、更易寫
  • ISO標(biāo)準兼容:默認使用ISO-8601標(biāo)準

常見使用場景

場景推薦使用的類說明
只處理日期LocalDate生日、紀念日、截止日期
只處理時間LocalTime營業(yè)時間、會議時間
日期+時間LocalDateTime日志時間、創(chuàng)建時間
跨時區(qū)應(yīng)用ZonedDateTime國際會議、航班時間
時間點/時間戳Instant性能測量、緩存過期
時間段(時間)Duration電影時長、任務(wù)耗時
時間段(日期)Period年齡、訂閱期限

遷移指南(從傳統(tǒng)API遷移)

public class MigrationGuide {
    
    // 傳統(tǒng)API -> Java 8 API的遷移
    public static void migrateFromLegacy() {
        System.out.println("=== 從傳統(tǒng)API遷移到Java 8 API ===");
        
        // 1. Date -> Instant/LocalDateTime
        java.util.Date oldDate = new java.util.Date();
        Instant instant = oldDate.toInstant();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        System.out.println("Date -> LocalDateTime: " + localDateTime);
        
        // 2. Calendar -> ZonedDateTime
        Calendar calendar = Calendar.getInstance();
        ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(
            calendar.toInstant(),
            calendar.getTimeZone().toZoneId()
        );
        System.out.println("Calendar -> ZonedDateTime: " + zonedDateTime);
        
        // 3. SimpleDateFormat -> DateTimeFormatter
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        System.out.println("格式化: " + formatter.format(LocalDate.now()));
        
        // 4. 時間運算的遷移
        calendar.add(Calendar.DAY_OF_MONTH, 7);
        ZonedDateTime sevenDaysLater = zonedDateTime.plusDays(7);
        System.out.println("7天后: " + sevenDaysLater);
        
        // 5. 時間比較的遷移
        boolean isBefore = calendar.before(Calendar.getInstance());
        boolean isBefore8 = zonedDateTime.isBefore(ZonedDateTime.now());
        System.out.println("時間比較: " + isBefore8);
    }
    
    // 常見陷阱和解決方案
    public static void commonPitfalls() {
        System.out.println("\n=== 常見陷阱和解決方案 ===");
        
        // 陷阱1:時區(qū)處理不當(dāng)
        System.out.println("\n陷阱1:時區(qū)處理");
        System.out.println("? LocalDateTime.now() 不包含時區(qū)信息");
        System.out.println("? 使用 ZonedDateTime.now() 或指定時區(qū)");
        
        // 陷阱2:忽略不可變性
        System.out.println("\n陷阱2:忽略不可變性");
        LocalDate date = LocalDate.of(2023, 11, 15);
        date.plusDays(1); // 這個方法返回新對象,不修改原對象
        System.out.println("date.plusDays(1) 后,原date未改變: " + date);
        LocalDate newDate = date.plusDays(1);
        System.out.println("需要接收返回值: " + newDate);
        
        // 陷阱3:格式化模式錯誤
        System.out.println("\n陷阱3:格式化模式");
        System.out.println("? yyyy-MM-dd HH:mm:ss - 24小時制");
        System.out.println("? yyyy-MM-dd hh:mm:ss - 12小時制(需要a表示上午/下午)");
        System.out.println("? yyyy-MM-dd HH:mm:ss - 24小時制");
        System.out.println("? yyyy-MM-dd hh:mm:ss a - 12小時制");
        
        // 陷阱4:解析嚴格性
        System.out.println("\n陷阱4:解析嚴格性");
        String dateStr = "2023-02-31"; // 2月31日不存在
        try {
            LocalDate date2 = LocalDate.parse(dateStr);
            System.out.println("寬松解析: " + date2);
        } catch (Exception e) {
            System.out.println("默認嚴格解析失敗: " + e.getMessage());
        }
    }
    
    // 性能最佳實踐總結(jié)
    public static void performanceBestPractices() {
        System.out.println("\n=== 性能最佳實踐 ===");
        
        System.out.println("1. 重用DateTimeFormatter");
        System.out.println("   ? 將格式化器聲明為靜態(tài)常量");
        System.out.println("   ? 避免在循環(huán)中創(chuàng)建新的格式化器");
        
        System.out.println("\n2. 使用正確的數(shù)據(jù)結(jié)構(gòu)");
        System.out.println("   ? 對于時間序列數(shù)據(jù),考慮使用long數(shù)組存儲時間戳");
        System.out.println("   ? 避免存儲大量LocalDateTime對象");
        
        System.out.println("\n3. 高效的時間比較");
        System.out.println("   ? 對于批量比較,轉(zhuǎn)換為epochDay或時間戳進行比較");
        System.out.println("   ? 避免在循環(huán)中多次調(diào)用isBefore/isAfter");
        
        System.out.println("\n4. 時區(qū)處理優(yōu)化");
        System.out.println("   ? 如果不需要時區(qū)信息,使用LocalDateTime而不是ZonedDateTime");
        System.out.println("   ? 避免不必要的時區(qū)轉(zhuǎn)換");
        System.out.println("   ? 不要在性能關(guān)鍵路徑中頻繁轉(zhuǎn)換時區(qū)");
    }
    
    public static void main(String[] args) {
        migrateFromLegacy();
        commonPitfalls();
        performanceBestPractices();
        
        System.out.println("\n=== 學(xué)習(xí)資源推薦 ===");
        System.out.println("1. Oracle官方教程: Java Date Time");
        System.out.println("2. 書籍: 《Java 8 in Action》");
        System.out.println("3. 在線練習(xí): codingbat.com/java/Date-Time");
        System.out.println("4. 開源項目: Joda-Time (Java 8日期時間API的前身)");
        
        System.out.println("\n記?。菏炀氄莆認ava 8日期時間API是現(xiàn)代Java開發(fā)的必備技能!");
    }
}

以上就是Java8中日期時間API使用的完全指南的詳細內(nèi)容,更多關(guān)于Java8 日期時間API的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • spring boot 自定義參數(shù)過濾器,把傳入的空字符轉(zhuǎn)換成null方式

    spring boot 自定義參數(shù)過濾器,把傳入的空字符轉(zhuǎn)換成null方式

    這篇文章主要介紹了spring boot 自定義參數(shù)過濾器,把傳入的空字符轉(zhuǎn)換成null方式。具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java中volatile防止指令重排

    Java中volatile防止指令重排

    volatile可以防止指令重排,在多線程環(huán)境下有時候我們需要使用volatile來防止指令重排,來保證代碼運行后數(shù)據(jù)的準確性,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Springboot整合zookeeper實現(xiàn)對節(jié)點的創(chuàng)建、監(jiān)聽與判斷的案例詳解

    Springboot整合zookeeper實現(xiàn)對節(jié)點的創(chuàng)建、監(jiān)聽與判斷的案例詳解

    這篇文章主要介紹了基于Springboot整合zookeeper實現(xiàn)對節(jié)點的創(chuàng)建、監(jiān)聽與判斷,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • Java連接Oracle數(shù)據(jù)庫并查詢

    Java連接Oracle數(shù)據(jù)庫并查詢

    這篇文章主要介紹了Java連接Oracle數(shù)據(jù)庫并查詢的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • SpringBoot整合RabbitMQ實現(xiàn)RPC遠程調(diào)用功能

    SpringBoot整合RabbitMQ實現(xiàn)RPC遠程調(diào)用功能

    在分布式系統(tǒng)中,RPC(Remote?Procedure?Call)是一種常用的通信機制,它可以讓不同的節(jié)點之間像調(diào)用本地函數(shù)一樣進行函數(shù)調(diào)用,隱藏了底層的網(wǎng)絡(luò)通信細節(jié),通過本教程,你可以了解RPC的基本原理以及如何使用Java實現(xiàn)一個簡單的RPC客戶端和服務(wù)端
    2023-06-06
  • RabbitMq 常用命令和REST API詳解

    RabbitMq 常用命令和REST API詳解

    RabbitMQ管理命令涵蓋服務(wù)啟停、用戶權(quán)限、虛擬主機、隊列操作、消息管理及集群配置,包含創(chuàng)建/刪除用戶、設(shè)置角色、綁定交換機與隊列、REST API數(shù)據(jù)查詢等關(guān)鍵操作,需注意參數(shù)格式和角色唯一性限制,本文給大家介紹RabbitMq常用命令和REST API,感興趣的朋友一起看看吧
    2025-07-07
  • 如何將Spring Session存儲到Redis中實現(xiàn)持久化

    如何將Spring Session存儲到Redis中實現(xiàn)持久化

    這篇文章主要介紹了如何將Spring Session存儲到Redis中實現(xiàn)持久化,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • mybatis解決<foreach>標(biāo)簽不能超過1000的問題

    mybatis解決<foreach>標(biāo)簽不能超過1000的問題

    MyBatis是一個開源的持久層框架,它可以幫助開發(fā)者簡化數(shù)據(jù)庫操作的編寫,而foreach是MyBatis中的一個重要標(biāo)簽,用于在SQL語句中進行循環(huán)操作,本文主要給大家介紹了mybatis解決<foreach>標(biāo)簽不能超過1000的問題,需要的朋友可以參考下
    2024-05-05
  • java如何讀取yaml配置文件

    java如何讀取yaml配置文件

    這篇文章主要介紹了java如何讀取yaml配置文件問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Maven倉庫分類的優(yōu)先級

    Maven倉庫分類的優(yōu)先級

    本文主要介紹了Maven倉庫分類的優(yōu)先級,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04

最新評論

阜平县| 罗平县| 韩城市| 洛川县| 肇源县| 齐河县| 昭平县| 台江县| 文山县| 铁力市| 广平县| 汝南县| 安阳市| 安阳市| 油尖旺区| 新平| 修文县| 高密市| 哈尔滨市| 麻阳| 景洪市| 手机| 潮安县| 泰兴市| 曲周县| 泸州市| 兴文县| 武安市| 葵青区| 深水埗区| 嵊泗县| 如东县| 镇远县| 固镇县| 平遥县| 景德镇市| 达拉特旗| 桐乡市| 台州市| 海南省| 保山市|