杰瑞科技汇

java date 转 string

在 Java 中,将 Date 对象转换为 String 是一个非常常见的操作,随着 Java 版本的演进,推荐的方法也在不断变化。

java date 转 string-图1
(图片来源网络,侵删)

下面我将从传统方法现代最佳实践,为你详细讲解如何进行转换。


核心思路

转换的核心思想是:

  1. 定义一个格式:你希望最终的字符串长什么样?yyyy-MM-dd HH:mm:ssMM/dd/yyyy
  2. 使用格式化工具:将 Date 对象和格式结合起来,生成符合格式的字符串。

使用 SimpleDateFormat (传统方法,Java 8 以前)

这是最经典、最广为人知的方法。SimpleDateFormat 是一个具体的类,用于格式化和解析日期。

基本用法

SimpleDateFormat 的构造函数接收一个模式字符串,用来定义日期和时间的格式。

java date 转 string-图2
(图片来源网络,侵删)

常用模式字符: | 字符 | 含义 | 示例 | | :--- | :--- | :--- | | y | 年 | yyyy (2025), yy (23) | | M | 月 | MM (07), M (7) | | d | 日 | dd (09), d (9) | | H | 时 (24小时制) | HH (15), H (15) | | h | 时 (12小时制) | hh (03), h (3) | | m | 分 | mm (05), m (5) | | s | 秒 | ss (09), s (9) | | S | 毫秒 | SSS (009) | | E | 星期 | E (星期三), EEEE (Wednesday) | | a | 上/下午 | a (下午) |

代码示例

import java.text.SimpleDateFormat;
import java.util.Date;
public class DateToStringSimpleDateFormat {
    public static void main(String[] args) {
        // 1. 获取当前的 Date 对象
        Date now = new Date();
        System.out.println("原始 Date 对象: " + now);
        // 2. 创建 SimpleDateFormat 对象,并指定格式
        // 格式: 年-月-日 时:分:秒
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 3. 调用 format() 方法进行转换
        String formattedDateTime = formatter.format(now);
        System.out.println("格式化后的字符串: " + formattedDateTime);
        // --- 其他格式示例 ---
        SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        String formattedDateTimeCN = formatter2.format(now);
        System.out.println("中文格式: " + formattedDateTimeCN);
        SimpleDateFormat formatter3 = new SimpleDateFormat("MM/dd/yyyy hh:mm a");
        String formattedDateTimeUS = formatter3.format(now);
        System.out.println("美式格式: " + formattedDateTimeUS);
    }
}

⚠️ 重要注意事项:线程安全问题

SimpleDateFormat非线程安全的,如果在多线程环境下共享同一个 SimpleDateFormat 实例,可能会导致数据错乱或程序异常。

错误用法 (多线程环境):

// 不要在多线程中这样使用!
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public void parseDate(String dateStr) throws ParseException {
    // 多个线程同时调用此方法会出问题
    Date date = sdf.parse(dateStr);
    // ...
}

解决方案:

  1. 每次创建新实例 (不推荐,性能开销大):

    // 每次调用都创建一个新的对象,效率低
    String formatted = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
  2. 使用 synchronized 同步块 (可以,但影响性能):

    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    public String format(Date date) {
        synchronized (sdf) {
            return sdf.format(date);
        }
    }
  3. 使用 ThreadLocal (推荐,性能好且安全):

    private static final ThreadLocal<SimpleDateFormat> threadLocalFormatter =
            ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
    public String format(Date date) {
        return threadLocalFormatter.get().format(date);
    }

使用 java.time.format.DateTimeFormatter (现代方法,Java 8+)

自 Java 8 引入了全新的日期时间 API (java.time),这是目前官方推荐的最佳实践,它解决了旧 API 的所有问题,包括线程安全。

基本用法

  1. 如果你有一个旧的 java.util.Date 对象,需要先将其转换为新的 java.time 类型,最简单的是转换为 Instant
  2. 然后使用 DateTimeFormatter 进行格式化。

代码示例

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
public class DateToStringJava8 {
    public static void main(String[] args) {
        // 1. 获取当前的 Date 对象
        Date now = new Date();
        System.out.println("原始 Date 对象: " + now);
        // 2. 将 java.util.Date 转换为 java.time.Instant
        Instant instant = now.toInstant();
        // 3. 将 Instant 转换为 ZonedDateTime (带时区)
        // 使用系统默认时区
        ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
        // 4. 创建 DateTimeFormatter 并指定格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 5. 使用 format() 方法进行转换
        String formattedDateTime = zonedDateTime.format(formatter);
        System.out.println("格式化后的字符串: " + formattedDateTime);
        // --- 其他格式示例 ---
        DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 EEEE");
        String formattedDateTimeCN = zonedDateTime.format(formatter2);
        System.out.println("中文格式: " + formattedDateTimeCN);
        DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm a z");
        String formattedDateTimeUS = zonedDateTime.format(formatter3);
        System.out.println("美式带时区格式: " + formattedDateTimeUS);
    }
}

DateTimeFormatter 的优势

  • 线程安全DateTimeFormatter 是不可变的,因此是线程安全的,可以在多个线程间安全地共享同一个实例。
  • 更丰富的 APIjava.time API 设计更优秀,功能更强大。
  • 时区处理:对时区的支持比旧版 API 更好。

总结与对比

特性 SimpleDateFormat (旧版) DateTimeFormatter (新版, Java 8+)
所属包 java.text java.time.format
线程安全 非线程安全 线程安全
API 设计 功能有限,API 有些混乱 API 设计清晰、一致、强大
Date 交互 直接作为核心类使用 需要通过 Instant 等中间类型转换
推荐度 不推荐用于新项目 强烈推荐,是现代 Java 的标准

最佳实践建议

  1. 对于新项目 (Java 8 及以上)始终优先使用 java.time API

    • java.util.Date 转为 Instant,再转为 ZonedDateTimeOffsetDateTime,然后用 DateTimeFormatter 格式化。
    • 如果可能,尽量避免在代码中使用 java.util.DateCalendar
  2. 对于维护旧项目 (Java 7 或更低):如果必须使用 SimpleDateFormat,请务必注意线程安全问题,最佳实践是使用 ThreadLocal 来为每个线程维护一个独立的实例。

  3. JDBC 交互:在与数据库交互时,尽量使用 JDBC 4.2+ 提供的 java.time 类型(如 TIMESTAMP WITH TIME ZONE),可以直接与 OffsetDateTimeZonedDateTime 映射,避免在 DateString 之间频繁转换。

分享:
扫描分享到社交APP
上一篇
下一篇