首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 日期時間獲取與格式化完全指南:從 Date 到現代 Time API

     編輯:Java 相關知識

傳統 Date/Calendar 方案(維護項目常見)

常用格式化模式

需求代碼示例輸出示例
標準日期時間DateFormat.getDateTimeInstance(2, 2, Locale.CHINESE).format(new Date())2024-01-15 14:30:45
中文長格式DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.CHINESE).format(new Date())2024年1月15日 下午2時30分45秒
毫秒精度new Timestamp(System.currentTimeMillis()).toString()2024-01-15 14:30:45.123

SimpleDateFormat 模式字符對照表

字母含義示例
y年2024
M月01
d日15
H時(24制)14
m分30
s秒45
S毫秒123
E星期週一
a上午/下午下午

字符串↔日期互轉


SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

// String → Date
Date date = sdf.parse("2024-01-15 14:30:45");

// Date → String
String str = sdf.format(date);

Calendar 日期運算實戰

常用操作封裝工具類


public class DateUtils {
    
    // 獲取指定格式當前時間
    public static String getNow(String pattern) {
        return new SimpleDateFormat(pattern).format(new Date());
    }
    
    // 獲取 N 月後日期
    public static String getAfterMonth(int months) {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, months);
        return new SimpleDateFormat("yyyy-MM-dd").format(c.getTime());
    }
    
    // 本周一日期
    public static String getMondayOfWeek() {
        Calendar c = Calendar.getInstance();
        int dayOfWeek = c.get(Calendar.DAY_OF_WEEK) - 1; // 周日=1
        if (dayOfWeek == 0) dayOfWeek = 7; // 將周日調為7
        c.add(Calendar.DATE, 1 - dayOfWeek);
        return new SimpleDateFormat("yyyy-MM-dd").format(c.getTime());
    }
    
    // 本月第一天/最後一天
    public static String getFirstDayOfMonth() {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.DAY_OF_MONTH, 1);
        return new SimpleDateFormat("yyyy-MM-dd").format(c.getTime());
    }
    
    public static String getLastDayOfMonth() {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.DAY_OF_MONTH, 1);
        c.add(Calendar.MONTH, 1);
        c.add(Calendar.DATE, -1);
        return new SimpleDateFormat("yyyy-MM-dd").format(c.getTime());
    }
    
    // 兩日期天數差
    public static long daysBetween(String d1, String d2) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            long diff = sdf.parse(d1).getTime() - sdf.parse(d2).getTime();
            return diff / (24 * 60 * 60 * 1000);
        } catch (ParseException e) {
            return 0;
        }
    }
}

現代 Java 8+ Time API(新項目首選)

核心類對照

舊 API新 API說明
DateInstant時間戳
CalendarZonedDateTime帶時區日期時間
無LocalDateTime本地日期時間(無時區)
無LocalDate本地日期
無LocalTime本地時間
SimpleDateFormatDateTimeFormatter線程安全格式化

現代 API 實戰示例


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

// 當前時間
LocalDateTime now = LocalDateTime.now();
LocalDate today = LocalDate.now();

// 格式化
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String str = now.format(fmt);

// 解析
LocalDateTime parsed = LocalDateTime.parse("2024-01-15T14:30:45", fmt);

// 日期運算
LocalDate nextMonth = today.plusMonths(1);
LocalDate firstDay = today.with(TemporalAdjusters.firstDayOfMonth());
LocalDate lastDay = today.with(TemporalAdjusters.lastDayOfMonth());
LocalDate monday = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));

// 期間計算
Period period = Period.between(LocalDate.of(2024,1,1), today);
long days = ChronoUnit.DAYS.between(LocalDate.of(2024,1,1), today);

// 時區轉換
ZonedDateTime beijing = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
ZonedDateTime utc = beijing.withZoneSameInstant(ZoneOffset.UTC);

線程安全陷阱與最佳實踐

SimpleDateFormat 非線程安全


// ❌ 危險:靜態共享會導致解析錯誤
private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd");

// ✅ 方案1:ThreadLocal
private static final ThreadLocal TL_SDF = 
    ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));

// ✅ 方案2:局部變量(推薦簡單場景)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

// ✅ 方案3:Java 8 DateTimeFormatter(天然線程安全)
private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd");

時區處理避坑指南

  • 存儲統一用 UTC(數據庫 TIMESTAMP/TIMESTAMPTZ)
  • 展示時按用戶時區轉換
  • 避免在業務邏輯中依賴默認時區
  • 跨時區計算使用 ZonedDateTime 或 Instant

總結選型建議

場景推薦方案
維護舊系統SimpleDateFormat + Calendar + ThreadLocal
新項目開發java.time 全家桶
高併發解析/格式化DateTimeFormatter (線程安全)
複雜日期運算TemporalAdjusters / Period / Duration
序列化/數據庫交互Instant (UTC 毫秒/納秒)

日期時間處理看似簡單,實則坑深。拥抱 Java 8 Time API,告別線程安全噩夢,享受不可變、流式、領域驅動的優雅體驗。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved