杰瑞科技汇

Java如何获取当前Date时间?

TL;DR)

方法 类/包 推荐度 说明
java.util.Date java.util 已过时,设计有缺陷,主要用于遗留代码。
java.util.Calendar java.util 已过时,比 Date 好用,但 API 复杂,易出错。
java.time.LocalDateTime java.time ⭐⭐⭐⭐⭐ 强烈推荐,Java 8+ 引入,现代、清晰、易用。
java.time.ZonedDateTime java.time ⭐⭐⭐⭐⭐ 强烈推荐,带时区的日期时间,用于精确时间。
java.time.Instant java.time ⭐⭐⭐⭐ 用于表示时间轴上的一个精确点(时间戳)。

传统方式 (已过时,不推荐用于新代码)

a) java.util.Date

这是最原始的方式,但它的设计存在一些问题,比如它同时包含了日期和时间,而且月份从 0 开始计数(0 代表一月)。

Java如何获取当前Date时间?-图1
(图片来源网络,侵删)

示例代码:

import java.util.Date;
public class GetDateExample {
    public static void main(String[] args) {
        // 直接创建 Date 对象,它代表当前时间
        Date now = new Date();
        // 打印当前时间
        // 注意:直接打印 Date 对象会输出其 toString() 方法的返回值
        System.out.println("当前时间 (Date): " + now);
        // 获取时间戳(自 1970年1月1日 00:00:00 GMT 以来的毫秒数)
        long timestamp = now.getTime();
        System.out.println("当前时间戳 (毫秒): " + timestamp);
    }
}

输出示例:

当前时间 (Date): Wed Oct 26 10:30:55 CST 2025
当前时间戳 (毫秒): 1698283855432

问题:

  • Date 的很多方法都已过时(@Deprecated)。
  • 处理时区非常麻烦。
  • API 不直观。

b) java.util.Calendar

为了弥补 Date 的不足,Java 引入了 Calendar,它提供了更丰富的功能,比如可以方便地获取/设置年、月、日等。

示例代码:

import java.util.Calendar;
public class GetCalendarExample {
    public static void main(String[] args) {
        // 获取一个 Calendar 实例,默认使用当前时间和默认时区
        Calendar calendar = Calendar.getInstance();
        // 获取年、月、日、时、分、秒
        // 注意:月份是从 0 开始的!0 代表一月,11 代表十二月。
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1; // 需要手动 +1
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int hour = calendar.get(Calendar.HOUR_OF_DAY); // 24小时制
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);
        System.out.printf("当前时间 (Calendar): %04d-%02d-%02d %02d:%02d:%02d%n",
                year, month, day, hour, minute, second);
    }
}

输出示例:

当前时间 (Calendar): 2025-10-26 10:30:55

问题:

  • API 仍然非常繁琐和冗长。
  • 线程不安全。
  • 月份从 0 开始计数等设计缺陷依然存在。
  • 自 Java 8 起,已标记为过时

现代方式 (Java 8+ 强烈推荐)

自 Java 8 开始,Java 引入了全新的 java.time 包,它由 JSR-310 标准定义,旨在彻底解决旧日期时间 API 的所有问题。对于任何新的 Java 项目,都应该优先使用 java.time 包中的类。

a) java.time.LocalDateTime - 最常用

LocalDateTime 是一个不可变的类,表示一个不带时区的日期和时间,非常适合用于应用程序内部的逻辑处理。

示例代码:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class GetLocalDateTimeExample {
    public static void main(String[] args) {
        // 1. 获取当前日期和时间
        LocalDateTime now = LocalDateTime.now();
        System.out.println("当前日期时间 (LocalDateTime): " + now);
        // 2. 获取年、月、日、时、分、秒
        int year = now.getYear();
        int month = now.getMonthValue(); // getMonth() 返回枚举,getMonthValue() 返回数字 (1-12)
        int day = now.getDayOfMonth();
        int hour = now.getHour();
        int minute = now.getMinute();
        int second = now.getSecond();
        System.out.printf("年: %d, 月: %d, 日: %d, 时: %d, 分: %d, 秒: %d%n",
                year, month, day, hour, minute, second);
        // 3. 格式化输出
        // 定义一个格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = now.format(formatter);
        System.out.println("格式化后的时间: " + formattedDateTime);
        // 4. 解析字符串
        String dateTimeString = "2025-12-31 23:59:59";
        LocalDateTime parsedDateTime = LocalDateTime.parse(dateTimeString, formatter);
        System.out.println("解析后的时间: " + parsedDateTime);
    }
}

输出示例:

当前日期时间 (LocalDateTime): 2025-10-26T10:30:55.123
年: 2025, 月: 10, 日: 26, 时: 10, 分: 30, 秒: 55
格式化后的时间: 2025-10-26 10:30:55
解析后的时间: 2025-12-31T23:59:59

优点:

  • API 清晰、直观、不可变(线程安全)。
  • 月份从 1 开始,符合常识。
  • 内置了强大的格式化和解析功能。

b) java.time.ZonedDateTime - 带时区的精确时间

如果你的应用需要处理不同时区的时间,或者需要记录一个全球统一的时间点,ZonedDateTime 是最佳选择。

示例代码:

import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class GetZonedDateTimeExample {
    public static void main(String[] args) {
        // 1. 获取当前时间,并使用系统默认时区
        ZonedDateTime nowDefault = ZonedDateTime.now();
        System.out.println("当前时间 (默认时区): " + nowDefault);
        // 2. 获取指定时区的当前时间
        ZoneId newYorkZone = ZoneId.of("America/New_York");
        ZonedDateTime nowInNewYork = ZonedDateTime.now(newYorkZone);
        System.out.println("纽约当前时间: " + nowInNewYork);
        ZoneId shanghaiZone = ZoneId.of("Asia/Shanghai");
        ZonedDateTime nowInShanghai = ZonedDateTime.now(shanghaiZone);
        System.out.println("上海当前时间: " + nowInShanghai);
        // 3. 获取UTC (协调世界时) 时间
        ZonedDateTime nowInUtc = ZonedDateTime.now(ZoneId.of("UTC"));
        System.out.println("UTC当前时间: " + nowInUtc);
        // 4. 格式化输出
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
        System.out.println("格式化 (上海时间): " + nowInShanghai.format(formatter));
    }
}

输出示例:

当前时间 (默认时区): 2025-10-26T10:30:55.456+08:00[Asia/Shanghai]
纽约当前时间: 2025-10-25T22:30:55.456-04:00[America/New_York]
上海当前时间: 2025-10-26T10:30:55.456+08:00[Asia/Shanghai]
UTC当前时间: 2025-10-26T02:30:55.456Z
格式化 (上海时间): 2025-10-26 10:30:55 CST

优点:

  • 正确处理时区转换,避免夏令时等问题。
  • 是记录和传输时间的标准方式。

c) java.time.Instant - 时间戳

Instant 表示时间线上的一个精确点,类似于 System.currentTimeMillis(),但精度更高(纳秒级),它非常适合用于日志、数据库存储或与其他系统进行时间戳交换。

示例代码:

import java.time.Instant;
public class GetInstantExample {
    public static void main(String[] args) {
        // 1. 获取当前时间的 Instant 对象 (UTC时间)
        Instant now = Instant.now();
        System.out.println("当前 Instant: " + now);
        // 2. 获取时间戳 (秒和纳秒)
        long epochSecond = now.getEpochSecond(); // 从 1970-01-01T00:00:00Z 开始的秒数
        int nano = now.getNano(); // 纳秒部分
        System.out.println("时间戳 (秒): " + epochSecond);
        System.out.println("纳秒: " + nano);
        // 3. 与 System.currentTimeMillis() 对比
        long currentTimeMillis = System.currentTimeMillis();
        System.out.println("System.currentTimeMillis(): " + currentTimeMillis);
        // Instant 的 toEpochMilli() 方法可以获取毫秒级时间戳
        long instantMillis = now.toEpochMilli();
        System.out.println("Instant.toEpochMilli(): " + instantMillis);
        // 两者在毫秒级别上是相等的
        System.out.println("两者是否相等: " + (currentTimeMillis == instantMillis));
    }
}

输出示例:

当前 Instant: 2025-10-26T02:30:55.789Z
时间戳 (秒): 1698283855
纳秒: 789000000
System.currentTimeMillis(): 1698283855789
Instant.toEpochMilli(): 1698283855789
两者是否相等: true

如何选择?

  • 新项目、新功能:直接使用 java.time 包。
    • 只需要年月日时分秒,不带时区 -> LocalDateTime
    • 需要处理时区,或者需要精确的时间点 -> ZonedDateTime
    • 需要存储时间戳、记录日志 -> Instant
  • 维护旧项目
    • 如果代码已经大量使用 DateCalendar,可以继续维护。
    • 如果需要将旧代码迁移到新 API,可以使用 java.time 提供的转换方法,
      • Date.from(Instant.now())Instant 转为 Date
      • new Date().toInstant()Date 转为 Instant
分享:
扫描分享到社交APP
上一篇
下一篇