一、SimpleDateFormat(传统方式)

1. 基本用法
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateFormatExample {
    public static void main(String[] args) {
        // 创建 SimpleDateFormat 实例
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        
        // 格式化当前日期
        String formattedDate = sdf.format(new Date());
        System.out.println("当前时间: " + formattedDate); // 2023-12-15 14:30:25
    }
}
2. 常用模式字符
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日");  // 2023年12月15日
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy/MM/dd");      // 2023/12/15
SimpleDateFormat sdf3 = new SimpleDateFormat("dd-MM-yyyy");      // 15-12-2023
SimpleDateFormat sdf4 = new SimpleDateFormat("HH:mm:ss");        // 14:30:25
SimpleDateFormat sdf5 = new SimpleDateFormat("hh:mm:ss a");      // 02:30:25 下午
SimpleDateFormat sdf6 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); // 2023-12-15T14:30:25.123+0800
SimpleDateFormat sdf7 = new SimpleDateFormat("EEEE, MMMM dd, yyyy"); // 星期五, 十二月 15, 2023
3. 完整示例
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class SimpleDateFormatDemo {
    public static void main(String[] args) {
        try {
            // 1. 日期转字符串
            Date now = new Date();
            
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
            System.out.println("日期: " + sdf1.format(now));
            
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
            System.out.println("详细时间: " + sdf2.format(now));
            
            SimpleDateFormat sdf3 = new SimpleDateFormat("EEEE", Locale.CHINA);
            System.out.println("星期: " + sdf3.format(now));
            
            // 2. 字符串转日期
            String dateStr = "2023-12-15 14:30:00";
            SimpleDateFormat sdf4 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date parsedDate = sdf4.parse(dateStr);
            System.out.println("解析后的日期: " + parsedDate);
            
            // 3. 带时区的格式化
            SimpleDateFormat sdf5 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
            System.out.println("ISO格式: " + sdf5.format(now));
            
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}
4. 线程安全问题及解决方案
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadSafeDateFormat {
    // 方案1: 每次创建新的实例(开销大但安全)
    public String formatDate1(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(date);
    }
    
    // 方案2: 使用ThreadLocal(推荐用于多线程)
    private static final ThreadLocal<SimpleDateFormat> threadLocalSdf = 
        ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    
    public String formatDate2(Date date) {
        return threadLocalSdf.get().format(date);
    }
    
    // 方案3: 同步代码块
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    public synchronized String formatDate3(Date date) {
        return sdf.format(date);
    }
}

二、DateTimeFormatter(Java 8+ 推荐)

1. 基本用法
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class DateTimeFormatterDemo {
    public static void main(String[] args) {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        
        // 预定义格式器
        DateTimeFormatter isoFormatter = DateTimeFormatter.ISO_DATE_TIME;
        System.out.println("ISO格式: " + now.format(isoFormatter));
        
        // 自定义格式器
        DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        System.out.println("自定义格式: " + now.format(customFormatter));
        
        DateTimeFormatter chineseFormatter = DateTimeFormatter.ofPattern("yyyy年M月d日 EEEE HH:mm");
        System.out.println("中文格式: " + now.format(chineseFormatter));
    }
}
2. 完整示例
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;

public class Java8DateFormatExample {
    public static void main(String[] args) {
        // 1. 各种日期时间类型的格式化
        LocalDate date = LocalDate.now();
        LocalTime time = LocalTime.now();
        LocalDateTime dateTime = LocalDateTime.now();
        ZonedDateTime zonedDateTime = ZonedDateTime.now();
        
        // 2. 使用预定义格式
        System.out.println("基本ISO日期: " + date.format(DateTimeFormatter.BASIC_ISO_DATE));
        System.out.println("ISO日期时间: " + dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        System.out.println("ISO时区时间: " + zonedDateTime.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
        
        // 3. 本地化格式化
        DateTimeFormatter shortFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
        DateTimeFormatter mediumFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
        DateTimeFormatter longFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
        DateTimeFormatter fullFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL)
                .withLocale(Locale.CHINA);
        
        System.out.println("短格式: " + dateTime.format(shortFormatter));
        System.out.println("中格式: " + dateTime.format(mediumFormatter));
        System.out.println("长格式: " + dateTime.format(longFormatter));
        System.out.println("完整格式: " + dateTime.format(fullFormatter));
        
        // 4. 自定义格式
        DateTimeFormatter customFormatter1 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");
        DateTimeFormatter customFormatter2 = DateTimeFormatter.ofPattern("dd-MMM-yyyy", Locale.US);
        DateTimeFormatter customFormatter3 = DateTimeFormatter.ofPattern("'日期:' yyyy年MM月dd日 '时间:' HH时mm分");
        
        System.out.println("斜杠格式: " + dateTime.format(customFormatter1));
        System.out.println("英文月份: " + date.format(customFormatter2));
        System.out.println("带文字格式: " + dateTime.format(customFormatter3));
        
        // 5. 解析字符串为日期
        String dateStr = "2023-12-15 14:30:00";
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime parsedDateTime = LocalDateTime.parse(dateStr, parser);
        System.out.println("解析后的时间: " + parsedDateTime);
        
        // 6. 带时区的格式化
        DateTimeFormatter zonedFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z")
                .withZone(ZoneId.systemDefault());
        System.out.println("带时区: " + zonedFormatter.format(zonedDateTime));
    }
}
3. 实用工具类
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Date;

public class DateUtil {
    
    // 预定义的格式化器(线程安全,可以全局使用)
    public static final DateTimeFormatter DATE_FORMATTER = 
        DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final DateTimeFormatter TIME_FORMATTER = 
        DateTimeFormatter.ofPattern("HH:mm:ss");
    public static final DateTimeFormatter DATETIME_FORMATTER = 
        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static final DateTimeFormatter TIMESTAMP_FORMATTER = 
        DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
    
    /**
     * 格式化 LocalDateTime
     */
    public static String format(LocalDateTime dateTime, String pattern) {
        return dateTime.format(DateTimeFormatter.ofPattern(pattern));
    }
    
    /**
     * 格式化 LocalDate
     */
    public static String format(LocalDate date, String pattern) {
        return date.format(DateTimeFormatter.ofPattern(pattern));
    }
    
    /**
     * 解析字符串为 LocalDateTime
     */
    public static LocalDateTime parseDateTime(String dateStr, String pattern) {
        return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(pattern));
    }
    
    /**
     * Date 转 LocalDateTime
     */
    public static LocalDateTime toLocalDateTime(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }
    
    /**
     * LocalDateTime 转 Date
     */
    public static Date toDate(LocalDateTime dateTime) {
        return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
    }
    
    /**
     * 生成时间戳字符串
     */
    public static String generateTimestamp() {
        return LocalDateTime.now().format(TIMESTAMP_FORMATTER);
    }
    
    /**
     * 获取中文日期格式
     */
    public static String getChineseDate(LocalDate date) {
        return date.format(DateTimeFormatter.ofPattern("yyyy年M月d日 E")
                .withLocale(Locale.CHINA));
    }
    
    /**
     * 格式化持续时间(如:01:23:45)
     */
    public static String formatDuration(Duration duration) {
        long hours = duration.toHours();
        long minutes = duration.toMinutesPart();
        long seconds = duration.toSecondsPart();
        return String.format("%02d:%02d:%02d", hours, minutes, seconds);
    }
    
    /**
     * 获取日期范围
     */
    public static String getDateRange(LocalDate start, LocalDate end, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return start.format(formatter) + " 至 " + end.format(formatter);
    }
    
    public static void main(String[] args) {
        // 使用示例
        LocalDateTime now = LocalDateTime.now();
        
        System.out.println("标准格式: " + format(now, "yyyy-MM-dd HH:mm:ss"));
        System.out.println("中文格式: " + getChineseDate(now.toLocalDate()));
        System.out.println("时间戳: " + generateTimestamp());
        System.out.println("使用预定义格式器: " + now.format(DATETIME_FORMATTER));
        
        // 解析示例
        LocalDateTime parsed = parseDateTime("2023-12-15 14:30:00", "yyyy-MM-dd HH:mm:ss");
        System.out.println("解析结果: " + parsed);
    }
}

三、对比与选择建议

特性 SimpleDateFormat DateTimeFormatter
线程安全 ❌ 不安全 ✅ 安全
Java 版本 1.1+ Java 8+
性能 较好 优秀
易用性 简单 更直观
功能 基础 丰富
推荐度 旧项目维护 新项目首选

四、常见问题解决

1. 时区处理
// SimpleDateFormat 时区设置
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));

// DateTimeFormatter 时区设置
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
        .withZone(ZoneId.of("Asia/Shanghai"));
2. 语言环境(Locale)
// 中文环境
SimpleDateFormat sdfCN = new SimpleDateFormat("yyyy年MM月dd日 EEEE", Locale.CHINA);

// 英文环境
DateTimeFormatter formatterEN = DateTimeFormatter.ofPattern("EEEE, MMMM dd, yyyy", Locale.US);
3. 性能优化建议
// 缓存 DateTimeFormatter 实例
public class FormatterCache {
    private static final Map<String, DateTimeFormatter> FORMATTER_CACHE = new ConcurrentHashMap<>();
    
    public static DateTimeFormatter getFormatter(String pattern) {
        return FORMATTER_CACHE.computeIfAbsent(pattern, DateTimeFormatter::ofPattern);
    }
    
    public static String format(LocalDateTime dateTime, String pattern) {
        return dateTime.format(getFormatter(pattern));
    }
}
4. 错误处理
public class SafeDateParser {
    public static Date safeParse(String dateStr, String pattern) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
            sdf.setLenient(false); // 严格模式,防止"2023-02-30"被接受
            return sdf.parse(dateStr);
        } catch (ParseException e) {
            // 记录日志,返回默认值或抛出业务异常
            return null;
        }
    }
    
    public static LocalDateTime safeParseDateTime(String dateStr, String pattern) {
        try {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
            return LocalDateTime.parse(dateStr, formatter);
        } catch (DateTimeParseException e) {
            // 处理解析失败
            return null;
        }
    }
}

总结建议

  1. 新项目:优先使用 DateTimeFormatter(Java 8+)
  2. 旧项目维护:继续使用 SimpleDateFormat,注意线程安全
  3. 多线程环境:使用 ThreadLocal<SimpleDateFormat>DateTimeFormatter
  4. 复杂日期操作:使用 java.time 包(Java 8+)
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐