首页 > Java > java教程 > 正文

如何在Java中使用SimpleDateFormat格式化日期

P粉602998670
发布: 2025-09-22 08:11:01
原创
887人浏览过
使用SimpleDateFormat格式化日期需创建实例并调用format()方法,但其非线程安全,推荐用ThreadLocal或Java 8的DateTimeFormatter替代。

如何在java中使用simpledateformat格式化日期

在Java中,使用

SimpleDateFormat
登录后复制
格式化日期,核心就是将一个
Date
登录后复制
对象转换成我们人类能读懂的、特定格式的字符串。它通过定义一个模式字符串(pattern string)来指导日期时间的显示方式,让原本无序的日期数据变得井井有条。

使用

SimpleDateFormat
登录后复制
格式化日期,通常分两步走:首先,你需要根据想要的日期时间格式,创建一个
SimpleDateFormat
登录后复制
实例;接着,调用这个实例的
format()
登录后复制
方法,传入你的
Date
登录后复制
对象,就能得到格式化后的字符串了。

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateFormatterExample {
    public static void main(String[] args) {
        // 1. 获取当前日期时间
        Date now = new Date();

        // 2. 定义你想要的日期时间格式
        // 例如:"yyyy-MM-dd HH:mm:ss" 会显示像 "2023-10-27 15:30:00" 这样的格式
        // "yyyy年MM月dd日 E HH时mm分ss秒" 会显示像 "2023年10月27日 星期五 15时30分00秒"
        String pattern = "yyyy-MM-dd HH:mm:ss"; // 我个人最常用的一种,简洁明了

        // 3. 创建 SimpleDateFormat 实例
        SimpleDateFormat formatter = new SimpleDateFormat(pattern);

        // 4. 使用 format() 方法将 Date 对象格式化为字符串
        String formattedDate = formatter.format(now);

        System.out.println("原始日期: " + now);
        System.out.println("格式化后的日期: " + formattedDate);

        // 反过来,如果你有一个日期字符串,想把它解析成 Date 对象,也可以用 parse() 方法
        String dateString = "2024-01-01 08:00:00";
        SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date parsedDate = parser.parse(dateString);
            System.out.println("解析后的日期: " + parsedDate);
        } catch (java.text.ParseException e) {
            System.err.println("日期字符串解析失败: " + e.getMessage());
        }
    }
}
登录后复制

这里面的模式字符串(pattern string)是关键。

y
登录后复制
代表年份,
M
登录后复制
代表月份,
d
登录后复制
代表日期,
H
登录后复制
代表24小时制的小时,
H
登录后复制
代表12小时制的小时,
M
登录后复制
代表分钟,
s
登录后复制
代表秒,
s
登录后复制
代表毫秒,
E
登录后复制
代表星期几。字符的数量会影响输出的格式,比如
MM
登录后复制
会输出两位数的月份(01-12),
MMM
登录后复制
会输出缩写(Jan, Feb),
MMMM
登录后复制
会输出完整名称(January, February)。我通常会根据需求去查阅一下Java官方文档,确保模式字符的正确使用,因为有时候一些细微的差别会导致意想不到的输出。

SimpleDateFormat的线程安全问题:那些隐藏的坑

说实话,

SimpleDateFormat
登录后复制
用起来确实方便,但它有一个非常大的“坑”,那就是它不是线程安全的。我第一次遇到这个问题时,是在一个多线程环境中,偶尔会发现日期格式化结果是错乱的,甚至直接抛出异常,当时真是把我搞得一头雾水。

立即学习Java免费学习笔记(深入)”;

简单来说,

SimpleDateFormat
登录后复制
format()
登录后复制
parse()
登录后复制
方法内部使用了共享的成员变量,当多个线程同时访问这些方法时,这些共享变量的状态就可能被意外修改,导致结果不一致。这就好比多个厨师共用一个案板,但每个人都在上面切菜,没有加锁,最后案板上的东西就乱套了。

为了解决这个问题,通常有几种做法:

百度智能云·曦灵
百度智能云·曦灵

百度旗下的AI数字人平台

百度智能云·曦灵 83
查看详情 百度智能云·曦灵
  1. 每次使用时都创建新实例:这是最直接,也最笨但最安全的方法。每次需要格式化或解析日期时,都

    new SimpleDateFormat()
    登录后复制
    一个新对象。这虽然解决了线程安全问题,但频繁创建对象会带来一定的性能开销,尤其是在高并发场景下,我个人会尽量避免这种方式。

    // 每次都创建新实例,确保线程安全
    public String formatThreadSafe(Date date) {
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
    }
    登录后复制
  2. 使用

    ThreadLocal
    登录后复制
    包装:这是我比较推荐的一种方案,它能保证每个线程都拥有自己的
    SimpleDateFormat
    登录后复制
    实例,既避免了线程安全问题,又避免了频繁创建对象的开销。

    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class ThreadLocalDateFormat {
        private static final ThreadLocal<SimpleDateFormat> formatter = ThreadLocal.withInitial(
            () -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    
        public static String format(Date date) {
            return formatter.get().format(date);
        }
    
        public static Date parse(String dateString) throws java.text.ParseException {
            return formatter.get().parse(dateString);
        }
    
        public static void main(String[] args) {
            // 示例:在多个线程中使用
            for (int i = 0; i < 5; i++) {
                new Thread(() -> {
                    try {
                        String formatted = format(new Date());
                        System.out.println(Thread.currentThread().getName() + " formatted: " + formatted);
                        Date parsed = parse("2023-11-11 11:11:11");
                        System.out.println(Thread.currentThread().getName() + " parsed: " + parsed);
                    } catch (java.text.ParseException e) {
                        e.printStackTrace();
                    }
                }, "Thread-" + i).start();
            }
        }
    }
    登录后复制

    这种方式在Java 8之前是处理

    SimpleDateFormat
    登录后复制
    线程安全问题的标准做法,既保证了正确性,又兼顾了性能。

现代Java日期API:使用DateTimeFormatter的优雅之道

在我看来,Java 8引入的

java.time
登录后复制
包(也称为JSR 310)彻底改变了Java日期时间处理的格局,它提供了一套全新的、更强大、更易用且线程安全的API。如果你正在使用Java 8或更高版本,我强烈建议你放弃
SimpleDateFormat
登录后复制
,转而使用
DateTimeFormatter
登录后复制

DateTimeFormatter
登录后复制
java.time
登录后复制
包中用于格式化和解析日期时间的核心类,它与
LocalDate
登录后复制
LocalTime
登录后复制
LocalDateTime
登录后复制
ZonedDateTime
登录后复制
等类配合使用。它的设计初衷就考虑到了线程安全,因此你无需担心多线程并发问题。

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

public class ModernDateFormatterExample {
    public static void main(String[] args) {
        // 1. 获取当前日期时间
        LocalDateTime now = LocalDateTime.now();

        // 2. 定义你想要的日期时间格式
        // DateTimeFormatter 的模式与 SimpleDateFormat 类似,但更严格和清晰
        String pattern = "yyyy-MM-dd HH:mm:ss";
        // 我个人觉得,对于一些标准格式,直接用预定义的常量更方便,比如 ISO_LOCAL_DATE_TIME
        // DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; // 2023-10-27T15:30:00

        // 3. 创建 DateTimeFormatter 实例
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);

        // 4. 使用 format() 方法将 LocalDateTime 对象格式化为字符串
        String formattedDateTime = now.format(formatter);

        System.out.println("原始日期时间: " + now);
        System.out.println("格式化后的日期时间: " + formattedDateTime);

        // 反过来,解析字符串到 LocalDateTime
        String dateTimeString = "2024-01-01 09:30:15";
        try {
            LocalDateTime parsedDateTime = LocalDateTime.parse(dateTimeString, formatter);
            System.out.println("解析后的日期时间: " + parsedDateTime);
        } catch (DateTimeParseException e) {
            System.err.println("日期时间字符串解析失败: " + e.getMessage());
        }

        // 对于只处理日期或时间的情况,也有对应的类
        // LocalDate today = LocalDate.now();
        // DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        // System.out.println("格式化日期: " + today.format(dateFormatter));
    }
}
登录后复制

DateTimeFormatter
登录后复制
的好处显而易见:它不仅解决了线程安全问题,还提供了更丰富的API,例如链式调用、对时区处理的良好支持等等。它的模式字符串虽然和
SimpleDateFormat
登录后复制
有些相似,但更加直观和一致。在我看来,一旦你开始使用
java.time
登录后复制
包,你就会发现之前的日期时间处理简直是“上古时代”的体验了。从项目的长期维护性和代码的健壮性考虑,我总是推荐优先使用
DateTimeFormatter
登录后复制

以上就是如何在Java中使用SimpleDateFormat格式化日期的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号