Java时间处理核心要点:Calendar、Date与格式化实战

唐可
唐可
发布时间:2026-10-14| 4人浏览过
原创

掌握Java时间处理的核心在于熟练使用 java.util.Calendar 和 java.text.SimpleDateFormat 类。本文总结从基础的时间格式化和类型转换,到复杂的日期间隔计算及数据库时间适配等实用操作。

获取特定月份的最大天数

在开发中,经常需要动态判断某年某月有多少天(例如区分闰年二月是28还是29天)。利用 Calendar 类的 getActualMaximum 方法可以准确获取指定月份的天数。

第1步:初始化并设置目标年月

目的:清除系统默认时间的干扰,设定具体的查询年份和月份。

  • 入口: Calendar.getInstance()
  • 动作: 调用 clear() 清理缓存,使用 set 设置年、月。注意 Calendar.MONTH 的值是从0开始计算的(0代表一月)。
  • 参数示例: year设为整数型,month为 i-1(假设i为用户输入的1-12月份的数值)。
Calendar time = Calendar.getInstance();
time.clear(); // 必须先清空,否则继承当前系统时间
time.set(Calendar.YEAR, year); 
time.set(Calendar.MONTH, i - 1);
int day = time.getActualMaximum(Calendar.DAY_OF_MONTH); // 获取本月最大天数

Date 与 Calendar 的类型转换

Date 和 Calendar 是Java中最基础的两个时间类,两者之间的相互转换非常频繁。

第2步:Calendar 转化为 Date

通过 getTime() 方法将日历对象提取为标准Date对象。

Calendar cal = Calendar.getInstance();
Date date = cal.getTime();

第3步:Date 转化为 Calendar

使用 setTime() 方法将Date对象填入日历实例中。

Date date = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);

日期时间的格式化输出

使用 SimpleDateFormat 类可以实现日期的字符串化显示或反向解析。这是日常日志记录、前端展示最常用功能。

第4步:定义格式化模板并执行

目的:将Date对象按照指定样式(如“年-月-日 时:分:秒”)转换为字符串。

  • 模式说明: yyyy代表四位年份,MM代表两位月份,dd代表日期,hh:mm:ss代表时分秒。
  • 代码实现:
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String timeStr = df.format(date);
System.out.println(timeStr);

星期相关运算

在处理排期或考勤系统时,常需计算某一天是一年中的第几周,或者反推某个周的日期。

第5步:计算特定日期是一年中的第几周

设置好年月日后,直接调用 WEEK_OF_YEAR 属性即可获取。

Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2006);
cal.set(Calendar.MONTH, 8); // 实际上是9月
cal.set(Calendar.DAY_OF_MONTH, 3);
int weekNo = cal.get(Calendar.WEEK_OF_YEAR);

第6步:根据年和周号推算具体日期

若已知某年第1周且想要找出该周周一是哪天:

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2006);
cal.set(Calendar.WEEK_OF_YEAR, 1);
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.println(df.format(cal.getTime())); // 输出示例:2006-01-02

时间加减法:add() 与 roll() 的区别

虽然不常用,但在某些特定业务逻辑下二者区别明显。关键在于是否引发上级单位(如月、年)的进位变化。

第7步:测试 add() 的全局进位特性

add(field, amount) 会对指定的时间字段进行加减,并会向上进位或借位。

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = Calendar.getInstance();
cal.set(2006, Calendar.SEPTEMBER, 3);
cal.add(Calendar.DATE, -4);
System.out.println(df.format(cal.getTime())); // 结果:2006-08-30 (跨越了月份)
cal.add(Calendar.DATE, 4);
System.out.println(df.format(cal.getTime())); // 恢复:2006-09-03

第8步:测试 roll() 的本级循环特性

roll(field, amount) 仅在当前字段内循环,不会改变比它大的字段值。

// 接上例环境,重置回9月3日
cal.set(2006, Calendar.SEPTEMBER, 3);
cal.roll(Calendar.DATE, -4);
// 如果原日期是9月3日,减4天后不会变成8月底,而是在当月循环
date = cal.getTime();
System.out.println(df.format(date)); 
cal.roll(Calendar.DATE, 4);
date = cal.getTime();
System.out.println(df.format(date)); 
// 可见roll()用于不需要改变年月的大小时

建议: 除非有特殊需求,一般日期计算优先使用 add()。

计算两个时间段的间隔天数

计算日期间隔是常见需求,以下是三种常见的实现方式,精度依次递增。

第9步:基于毫秒差计算(简单但可能有误差)

适用于粗略计算,直接相减后除以一天的毫秒数(1000 * 60 * 60 * 24)。为防止start晚于end,应先做交换处理。

public int getIntervalDays(Calendar startday, Calendar endday) {
    if (startday.after(endday)) {
        Calendar cal = startday;
        startday = endday;
        endday = cal;
    }
    long sl = startday.getTimeInMillis();
    long el = endday.getTimeInMillis();
    long ei = el - sl;
    return (int) (ei / (1000 * 60 * 60 * 24));
}

第10步:传入 Date 对象的同名方法

逻辑同上,只是获取时间戳的方式改为 getTime()。

public int getIntervalDays(Date startday, Date endday) {
    if (startday.after(endday)) {
        Date cal = startday;
        startday = endday;
        endday = cal;
    }
    long sl = startday.getTime();
    long el = endday.getTime();
    long ei = el - sl;
    return (int) (ei / (1000 * 60 * 60 * 24));
}

第11步:改进的精确跨天计算(处理跨年多天问题)

上述方法直接用毫秒除可能会因为夏令时或微小时差产生1天的误差。更严谨的做法是利用 DAY_OF_YEAR 累加每年的天数来处理跨年情况。

public int getDaysBetween(Calendar d1, Calendar d2) {
    if (d1.after(d2)) { 
        java.util.Calendar swap = d1;
        d1 = d2;
        d2 = swap;
    }
    int days = d2.get(Calendar.DAY_OF_YEAR) - d1.get(Calendar.DAY_OF_YEAR);
    int y2 = d2.get(Calendar.YEAR);
    if (d1.get(Calendar.YEAR) != y2) { 
        d1 = (Calendar) d1.clone();
        do {
            days += d1.getActualMaximum(Calendar.DAY_OF_YEAR);
            d1.add(Calendar.YEAR, 1);
        } while (d1.get(Calendar.YEAR) != y2);
    }
    return days;
}

日期与其他类型的相互转换

在实际应用中,往往涉及到 String、Long 和 SQL Date 之间的转换。

第12步:String 转为 Date 再转 Long

用于从文本中提取时间进行跨度比较。注意 parse 抛出的异常需在外部处理。

java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("M/dd/yyyy hh:mm:ss a", java.util.Locale.US);
java.util.Date d = sdf.parse("5/13/2003 10:31:37 AM");
long dvalue = d.getTime();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String mDateTime1 = formatter.format(d);

第13步:数据库专用日期类型转换(SQL Date & Timestamp)

JDBC编程中,Oracle的DATE只需年月日,对应 java.sql.Date;SQL Server的DateTime含时分秒,对应 java.sql.Timestamp。

A. 字符串转 java.sql.Date

public final static java.sql.Date string2Date(String dateString) throws Exception {
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
    dateFormat.setLenient(false); // 严格校验
    java.util.Date timeDate = dateFormat.parse(dateString);
    java.sql.Date dateTime = new java.sql.Date(timeDate.getTime());
    return dateTime;
}

B. 字符串转 java.sql.Timestamp

public final static java.sql.Timestamp string2Time(String dateString) throws Exception {
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss.SSS", Locale.ENGLISH);
    dateFormat.setLenient(false);
    java.util.Date timeDate = dateFormat.parse(dateString);
    java.sql.Timestamp dateTime = new java.sql.Timestamp(timeDate.getTime());
    return dateTime;
}

C. Date 直接转 Timestamp

// 方法一:利用getTime
Timestamp t = new Timestamp(new Date().getTime());

// 方法二:逐个获取日历字段构造
Timestamp tt = new Timestamp(
    Calendar.getInstance().get(Calendar.YEAR) - 1900,
    Calendar.getInstance().get(Calendar.MONTH),
    Calendar.getInstance().get(Calendar.DATE),
    Calendar.getInstance().get(Calendar.HOUR),
    Calendar.getInstance().get(Calendar.MINUTE),
    Calendar.getInstance().get(Calendar.SECOND), 0
);

以上就是Java时间处理核心要点的详细内容,更多关于Java开发技巧的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。