
目录
1.2 Java8 新时间 API(java.time 包,重点掌握)
1.2.4 TemporalAdjusters 时间调节器,获取边界时间(高频业务)
本节学习目标
- 了解旧版
java.util.Date日期类,知道大部分 API 已经过时 - 熟练掌握 Java8 全新时间日期 API:
LocalDateTime、DateTimeFormatter、TemporalAdjusters - 掌握日期获取、构造、字符串解析格式化、日期加减运算、获取周 / 月 / 年边界
- 掌握
BigDecimal大高精度浮点数类,解决 double 浮点精度丢失问题 - 掌握 BigDecimal 构造注意事项、加减乘除运算、除法舍入模式
第一部分 日期相关类
1.1 旧版 Date 类(java.util.Date)
Date是 Java 早期提供代表时间日期的类,时间精确到毫秒。

⚠️大量构造方法、成员方法已经被
@Deprecated标记为过时废弃,不推荐新项目使用,了解即可。
import java.util.Date;
public class TestDate {
public static void main(String[] args) {
// 获取系统当前时间
Date date1 = new Date();
System.out.println(date1);
// 【已过时,不推荐使用】
// 参数年份:是相对于1900的偏移量,123 → 1900+123 =2023年
// 月份从0开始!0代表一月,2代表3月
Date date2 = new Date(123,2,5);
System.out.println(date2);
}
}
旧 Date 痛点:
- 年份需要 + 1900,月份 0 开始,极易写错;
- 可变对象,时间可以被修改,线程不安全;
- API 设计混乱,大部分方法废弃。 ✅Java8 及以后优先使用新时间包
java.time。
1.2 Java8 新时间 API(java.time 包,重点掌握)
核心类:
LocalDateTime:日期 + 时间(年月日时分秒)LocalDate:只有年月日LocalTime:只有时分秒DateTimeFormatter:日期字符串格式化解析器TemporalAdjusters:时间调节器,获取当月第一天、当周周一、周日等
重要特性:LocalDateTime 对象不可变!所有 plus/minus/with 操作,返回全新对象,原对象本身不会修改。
1.2.1 获取当前系统时间、指定时间、字符串解析
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class TestLocalDateTime {
public static void main(String[] args) {
//1 获取系统当前的日期时间
LocalDateTime now = LocalDateTime.now();
System.out.println("当前时间:" + now);
//2 手动指定年月日时分秒,构造时间对象 of(year,month,day,hour,minute,second)
LocalDateTime dt = LocalDateTime.of(2023,5,15,10,30);
System.out.println("指定时间:" + dt);
//3 按照标准ISO格式字符串解析 "yyyy‑MM‑ddTHH:mm:ss"
LocalDateTime parse1 = LocalDateTime.parse("2023-05-15T10:30:00");
System.out.println(parse1);
//4 自定义格式字符串解析(业务最常用)
String dateStr = "2026-10-01 10:30:21";
//注意大小写!yyyy年 MM月 dd日 HH24小时制 mm分钟 ss秒
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime parse2 = LocalDateTime.parse(dateStr, formatter);
System.out.println("自定义解析结果:" + parse2);
}
}
⚠️格式模板大小写大坑,千万不能写混:
yyyy:4 位年份;MM两位月份;dd两位日期HH24 小时;hh12 小时;mm分钟;ss秒
1.2.2 获取时间各个字段(年、月、日、时、分、秒)
import java.time.LocalDateTime;
public class TestGetTimeField {
public static void main(String[] args) {
LocalDateTime dateTime = LocalDateTime.now();
int year = dateTime.getYear(); //年
int month = dateTime.getMonthValue(); //月份【1‑12】!注意getMonth()返回枚举,getMonthValue返回数字
int day = dateTime.getDayOfMonth(); //当月几号
int hour = dateTime.getHour(); //小时
int minute = dateTime.getMinute(); //分钟
int second = dateTime.getSecond(); //秒
System.out.println("年:"+year);
System.out.println("月:"+month);
System.out.println("日:"+day);
System.out.println("时:"+hour);
System.out.println("分:"+minute);
System.out.println("秒:"+second);
//附加信息
System.out.println("本周星期几(1=周一,7=周日):" + dateTime.getDayOfWeek().getValue());
System.out.println("本月的第几天:" + dateTime.getDayOfMonth());
System.out.println("当年的第几天:" + dateTime.getDayOfYear());
}
}
1.2.3 日期加减运算 plus /minus
plusXXX()增加时间;minusXXX()减少时间;返回新对象,原对象不变!
import java.time.LocalDateTime;
public class TestTimePlusMinus {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
//增加、减少天数
LocalDateTime plus1Day = now.plusDays(1);
LocalDateTime minus1Day = now.minusDays(1);
System.out.println("加1天:" + plus1Day);
System.out.println("减1天:" + minus1Day);
//增加、减少周
LocalDateTime plusWeek = now.plusWeeks(1);
LocalDateTime minusWeek = now.minusWeeks(1);
System.out.println("加1周:" + plusWeek);
//增加、减少月份
LocalDateTime plusMonth = now.plusMonths(1);
LocalDateTime minusMonth = now.minusMonths(1);
System.out.println("加1月:" + plusMonth);
//增加、减少年份
LocalDateTime plusYear = now.plusYears(1);
LocalDateTime minusYear = now.minusYears(1);
System.out.println("加1年:" + plusYear);
}
}
1.2.4 TemporalAdjusters 时间调节器,获取边界时间(高频业务)
TemporalAdjusters可以获取:当周周一 / 周日,当月第一天、当月最后一天。
import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
public class TestAdjust {
public static void main(String[] args) {
LocalDateTime current = LocalDateTime.now();
// 获取本周周一:previousOrSame 当前或者往前找最近的周一
LocalDateTime monday = current.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
// 获取本周周日:nextOrSame 当前或者往后找最近的周日
LocalDateTime sunday = current.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
System.out.println("本周周一:" + monday);
System.out.println("本周周日:" + sunday);
// 获取当月第一天,当月最后一天
LocalDateTime firstDayOfMonth = current.with(TemporalAdjusters.firstDayOfMonth());
LocalDateTime lastDayOfMonth = current.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("当月第一天:" + firstDayOfMonth);
System.out.println("当月最后一天:" + lastDayOfMonth);
}
}
方法说明
previousOrSame:取当前或者往前找匹配星期nextOrSame:取当前或者往后找匹配星期
补充:LocalDateTime 是不可变类,
.with()会返回全新时间对象,原 current 对象不会被修改。
第二部分 BigDecimal 高精度运算
包:
java.math.BigDecimaldouble/float 二进制浮点数,会有精度丢失,金融、货币计算,绝对不能直接使用 double。BigDecimal实现十进制高精度数字运算,解决浮点精度丢失。
2.1 构造对象(重点坑!不要直接传 double)
import java.math.BigDecimal;
public class TestBigDecimalCreate {
public static void main(String[] args) {
// ❌不推荐:传入double,double本身已经精度丢失,BigDecimal保存的是失真之后的值
BigDecimal num1 = new BigDecimal(1.99);
System.out.println(num1);
//输出:1.9899999999999999911182158029987476766109466552734375
// ✅推荐!使用字符串构造,精确表示十进制小数
BigDecimal num2 = new BigDecimal("2.99");
System.out.println(num2);
// 如果必须把double转为BigDecimal,使用静态方法 valueOf()
double d = 3.14;
BigDecimal num3 = BigDecimal.valueOf(d);
System.out.println(num3);
}
}
官方文档说明:
new BigDecimal(double val):把二进制浮点数精确还原,不能用来做十进制精确计算,尽量避开。new BigDecimal(String val):字符串构造,金融业务首选。BigDecimal.valueOf(double)等价于Double.toString(double),可以消除部分 double 失真。

2.2 加减乘运算
⚠️BigDecimal 是不可变对象!加减乘除不会修改原来对象,运算结果返回全新 BigDecimal 对象,需要接收返回值。
import java.math.BigDecimal;
public class TestBigDecimalCalc {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("1.35");
BigDecimal b = new BigDecimal("3.22");
BigDecimal addRes = a.add(b); //加法
System.out.println("加法:" + addRes);
BigDecimal subRes = a.subtract(b); //减法
System.out.println("减法:" + subRes);
BigDecimal mulRes = a.multiply(b); //乘法
System.out.println("乘法:" + mulRes);
}
}
2.3 除法运算(高频坑)
如果除法结果是无限循环小数,直接调用divide(b)会抛出ArithmeticException算术异常!
// 报错版本
BigDecimal a = new BigDecimal("1.35");
BigDecimal b = new BigDecimal("3.22");
BigDecimal divRes = a.divide(b);
// Exception in thread "main" java.lang.ArithmeticException: Non‑terminating decimal expansion; no exact representable decimal result.
✅解决方案:指定保留小数位数 + 舍入模式 divide(除数,保留小数位数,舍入模式) 常用舍入模式:RoundingMode.HALF_UP 四舍五入。
import java.math.BigDecimal;
import java.math.RoundingMode;
public class TestBigDecimalDiv {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("1.35");
BigDecimal b = new BigDecimal("3.22");
//保留4位小数,四舍五入
BigDecimal divRes = a.divide(b,4, RoundingMode.HALF_UP);
System.out.println("除法结果:" + divRes); //输出0.4193
}
}

另一种写法,传入
MathContext设置精度
BigDecimal divRes = a.divide(b, new MathContext(4,RoundingMode.HALF_UP));
📔本篇核心考点总结
- 旧
java.util.Date大量 API 过时,年份偏移 1900,月份从 0 开始;线程不安全,新项目不用。 - Java8 新时间包
java.time,LocalDateTime代表日期时间,对象不可变,plus/minus/with 返回新对象,原对象不变。 DateTimeFormatter.ofPattern()自定义解析格式,注意大小写区分:yyyy MM dd HH mm ss。TemporalAdjusters调节器:获取当周周一 / 周日、当月第一天、当月最后一天。BigDecimal用于金融高精度计算;禁止直接 new BigDecimal (double),优先字符串构造或者 valueOf ()。- BigDecimal 运算不会修改原对象,运算结果必须接收返回对象。
- divide 除法遇到无限小数会抛异常,必须指定小数位数 + 舍入模式,常用
RoundingMode.HALF_UP四舍五入。
面试简答 Q:为什么金融计算不能直接用 double? A:double 是二进制浮点数,部分十进制小数无法精确存储,会产生精度丢失,金融业务用 BigDecimal。 Q:LocalDateTime plusDays 之后,原来对象时间会改变吗? A:不会,LocalDateTime 不可变,返回全新对象,原对象内容保持不变。

转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/wuqingyigexiaoba/article/details/165757444





