本文纲要
- 世界标准时间与计算机时间原点
Date类
构造方法
成员方法getTime()和setTime()SimpleDateFormat格式化和解析
格式化:将Date转换为字符串
解析:将字符串转换为Date
综合练习:秒杀资格判断(含流程图)- JDK8 新时间类
为什么需要 JDK8 时间类
体验 JDK8 的简洁 LocalDateTime获取时间对象LocalDateTime获取时间中的每个值LocalDateTime转换方法LocalDateTime格式化与解析plus系列方法:添加或减少时间minus系列方法:减少或增加时间with系列方法:修改时间- 时间间隔对象
Period和Duration - JDK8 时间类小结
世界标准时间与计算机时间原点
在深入学习 Java 时间 API 之前,有必要了解几个背景知识。
-
世界标准时间:格林威治标准时间(Greenwich Mean Time,GMT),由英国伦敦格林威治天文台提供,现已被更精确的原子钟替代(误差每两千万年仅一秒)。我国采用北京时间,位于东八区,需在标准时间上加 8 小时。
-
时间单位换算:
1 秒 = 1000 毫秒,1 毫秒 = 1000 微秒,1 微秒 = 1000 纳秒。其中“1 秒 = 1000 毫秒”使用最频繁。 -
计算机时间原点:1970 年 1 月 1 日 00:00:00(Unix 纪元),这也是 C 语言的诞生时间,Java 继承了该传统。
System.currentTimeMillis()返回的正是从该原点至今的毫秒数。
Date 类
Java 中 java.util.Date 类表示一个特定的时间,精确到毫秒。本节演示代码位于 com.wb.mydate 包下,项目结构如下:
src
└── com
└── wb
├── mydate
│ ├── DateDemo1.java
│ ├── DateDemo2.java
│ ├── DateDemo3.java
│ ├── DateDemo4.java
│ └── DateDemo5.java
└── jdk8date
├── JDK8DateDemo1.java
├── JDK8DateDemo2.java
...
└── JDK8DateDemo10.java
1 ) 构造方法
Date 提供两个常用构造:
Date():空参构造,封装当前系统时间。Date(long date):带参构造,从时间原点经过指定毫秒后的时间(注意东八区需 +8 小时)。
示例
// DateDemo1.java
package com.wb.mydate;
import java.util.Date;
public class DateDemo1 {
public static void main(String[] args) {
// 空参构造:表示当前时间
Date date1 = new Date();
System.out.println(date1);
// 带参构造:从时间原点经过 0 毫秒 → 1970-01-01 08:00:00 (东八区)
Date date2 = new Date(0L);
System.out.println(date2);
// 表示 1970年1月1日 上午9点(1小时 = 3600秒 × 1000 毫秒)
Date date3 = new Date(3600L * 1000);
System.out.println(date3);
}
}
要点:
- 空参构造获得当前时间。
- 带参构造传入毫秒值,基准是
1970-01-01 08:00:00(北京时间)。
2 ) 成员方法 getTime() 和 setTime()
getTime():返回该 Date 对象对应的毫秒值(从时间原点开始的毫秒数)。setTime(long time):设置 Date 对象的时间(传入毫秒值)。
示例
// DateDemo2.java
package com.wb.mydate;
import java.util.Date;
public class DateDemo2 {
public static void main(String[] args) {
// method1(); // 获取毫秒值
// method2(); // 设置时间
}
// 演示 getTime()
private static void method1() {
Date date1 = new Date(); // 当前时间
long time = date1.getTime(); // 获取毫秒值
System.out.println(time);
long time2 = System.currentTimeMillis(); // 与系统方法对比
System.out.println(time2);
}
// 演示 setTime()
private static void method2() {
Date date1 = new Date(); // 当前时间
date1.setTime(0L); // 设置为时间原点
System.out.println(date1);
}
}
SimpleDateFormat 格式化和解析
SimpleDateFormat 位于 java.text 包,用于将 Date 对象与字符串相互转换,自定义时间显示格式。
常用模式字母:
| 字母 | 含义 |
|---|---|
| y | 年 |
| M | 月 |
| d | 日 |
| H | 时(0-23) |
| m | 分 |
| s | 秒 |
1 ) 格式化:将 Date 转换为字符串
// DateDemo3.java
package com.wb.mydate;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDemo3 {
public static void main(String[] args) {
Date date = new Date(); // 当前时间
// 创建格式对象,指定输出样式
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String result = sdf.format(date); // 格式化
System.out.println(result);
}
}
格式字符串中的字母必须严格使用上表,其他字符原样输出。
2 ) 解析:将字符串转换为 Date
// DateDemo4.java
package com.wb.mydate;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDemo4 {
public static void main(String[] args) throws ParseException {
String s = "2048-01-01";
// 解析时格式必须与字符串格式完全一致
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse(s); // 解析成 Date
System.out.println(date);
}
}
解析时若格式不匹配会抛出 ParseException。
3 ) 综合练习:秒杀资格判断
秒杀活动:开始时间 2020 年 11 月 11 日 0:0:0,结束时间同一天 0:10:0。
小贾下单时间:0:03:47,小皮下单时间:0:10:11。判断谁成功参与。
解题思路:将时间字符串转换为毫秒值进行比较。
// DateDemo5.java
package com.wb.mydate;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDemo5 {
public static void main(String[] args) throws ParseException {
String start = "2020年11月11日 0:0:0";
String end = "2020年11月11日 0:10:0";
String jia = "2020年11月11日 0:03:47";
String pi = "2020年11月11日 0:10:11";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
// 所有时间转为毫秒值
long startTime = sdf.parse(start).getTime();
long endTime = sdf.parse(end).getTime();
long jiaTime = sdf.parse(jia).getTime();
long piTime = sdf.parse(pi).getTime();
// 判断小贾
if (jiaTime >= startTime && jiaTime <= endTime) {
System.out.println("小贾同学参加上了秒杀活动");
} else {
System.out.println("小贾同学没有参加上秒杀活动");
}
System.out.println("------------------------");
// 判断小皮
if (piTime >= startTime && piTime <= endTime) {
System.out.println("小皮同学参加上了秒杀活动");
} else {
System.out.println("小皮同学没有参加上秒杀活动");
}
}
}
输出结果:小贾参加成功,小皮失败(10:11 超出了结束时间)。
JDK8 新时间类
JDK7 之前用 Date + SimpleDateFormat 进行时间计算时需要反复转换(字符串 → Date → 毫秒 → 加/减 → Date → 字符串),代码繁琐易错。JDK8 引入了全新的时间 API,代码更简洁、语义更清晰。
体验 JDK8 的简洁
需求:将 2020年11月11日 00:00:00 加 1 天。
JDK7 方式:
// JDK8DateDemo1.java (部分)
private static void JDKMethod() throws ParseException {
String s = "2020年11月11日 00:00:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date date = sdf.parse(s);
long time = date.getTime();
time = time + (1000 * 60 * 60 * 24); // 加一天的毫秒
Date newDate = new Date(time);
String result = sdf.format(newDate);
System.out.println(result);
}
JDK8 方式:
// JDK8DateDemo1.java
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class JDK8DateDemo1 {
public static void main(String[] args) {
String s = "2020年11月11日 00:00:00";
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
LocalDateTime localDateTime = LocalDateTime.parse(s, pattern);
LocalDateTime newLocalDateTime = localDateTime.plusDays(1); // 直接加1天
String result = newLocalDateTime.format(pattern);
System.out.println(result);
}
}
对比可见,JDK8 API 省去了毫秒值的中间计算,代码更直观
LocalDateTime 获取时间对象
JDK8 将时间细化为三个类:
LocalDate:只包含年、月、日。LocalTime:只包含时、分、秒。LocalDateTime:包含年、月、日、时、分、秒。
常用创建方法:
now():静态方法,获取当前系统时间。of(int year, int month, int day, int hour, int minute, int second):指定时间。
// JDK8DateDemo2.java
package com.wb.jdk8date;
import java.time.LocalDateTime;
public class JDK8DateDemo2 {
public static void main(String[] args) {
// 当前时间
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
// 指定时间:2020年11月11日 11:11:11
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 11, 11, 11);
System.out.println(localDateTime);
}
}
of 方法的参数有范围限制(如月份 1-12),超出会抛出异常。
LocalDateTime 获取时间中的每个值
LocalDateTime 提供了丰富的 get 方法,直接获取各个字段,返回 int 类型:
// JDK8DateDemo3.java
package com.wb.jdk8date;
import java.time.LocalDateTime;
public class JDK8DateDemo3 {
public static void main(String[] args) {
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 11, 11, 20);
int year = localDateTime.getYear(); // 年
int month = localDateTime.getMonthValue(); // 月 (1-12)
int day = localDateTime.getDayOfMonth(); // 日 (1-31)
int dayOfYear = localDateTime.getDayOfYear(); // 一年中的第几天
int minute = localDateTime.getMinute(); // 分钟
int hour = localDateTime.getHour(); // 小时
System.out.println("年:" + year);
System.out.println("月:" + month);
System.out.println("日:" + day);
System.out.println("一年中第 " + dayOfYear + " 天");
System.out.println("小时:" + hour);
System.out.println("分钟:" + minute);
}
}
注意:getMonth() 返回的是枚举类型 Month(如 NOVEMBER),getDayOfWeek() 返回 DayOfWeek 枚举。一般获取数值时推荐使用 getMonthValue()、getDayOfMonth() 等。
LocalDateTime 转换方法
若只关心日期或只关心时间,可在 LocalDateTime 基础上转换:
toLocalDate()→ 仅保留年、月、日。toLocalTime()→ 仅保留时、分、秒。
// JDK8DateDemo4.java
package com.wb.jdk8date;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class JDK8DateDemo4 {
public static void main(String[] args) {
LocalDateTime localDateTime = LocalDateTime.of(2020, 12, 12, 8, 10, 12);
LocalDate localDate = localDateTime.toLocalDate(); // 2020-12-12
LocalTime localTime = localDateTime.toLocalTime(); // 08:10:12
System.out.println(localDate);
System.out.println(localTime);
}
}
LocalDateTime 格式化与解析
JDK8 使用 DateTimeFormatter 替代 SimpleDateFormat,用法类似。
- 格式化:
format()方法。 - 解析:静态方法
parse(字符串, 格式器)。
// JDK8DateDemo5.java
package com.wb.jdk8date;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class JDK8DateDemo5 {
public static void main(String[] args) {
// 格式化
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 12, 13, 14, 15);
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
String s = localDateTime.format(pattern);
System.out.println(s);
// 解析
String str = "2020年11月12日 13:14:15";
LocalDateTime parse = LocalDateTime.parse(str, pattern);
System.out.println(parse);
}
}
plus 系列方法:添加或减少时间
plusXxx() 方法返回一个新的 LocalDateTime 对象,参数为正数时向后添加,负数时向前减少
常用方法:plusYears(), plusMonths(), plusDays(), plusHours(), plusMinutes() 等
// JDK8DateDemo6.java
package com.wb.jdk8date;
import java.time.LocalDateTime;
public class JDK8DateDemo6 {
public static void main(String[] args) {
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
// 加 1 年 → 2021-11-11 13:14:15
LocalDateTime newLocalDateTime = localDateTime.plusYears(1);
System.out.println(newLocalDateTime);
// 加 -1 年 → 相当于减 1 年 → 2019-11-11 13:14:15
LocalDateTime newLocalDateTime2 = localDateTime.plusYears(-1);
System.out.println(newLocalDateTime2);
}
}
minus 系列方法:减少或增加时间
minusXxx() 方法与 plus 语义相反:正数向前减少,负数向后增加。
// JDK8DateDemo7.java
package com.wb.jdk8date;
import java.time.LocalDateTime;
/**
* JDK8 时间类减少或者添加时间的方法
*/
public class JDK8DateDemo7 {
public static void main(String[] args) {
// public LocalDateTime minusYears(long years) 减去或者添加年
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
// 减 1 年 → 2019-11-11 13:14:15
LocalDateTime newLocalDateTime1 = localDateTime.minusYears(1);
System.out.println(newLocalDateTime1);
// 减 -1 年 → 相当于加 1 年 → 2021-11-11 13:14:15
LocalDateTime newLocalDateTime2 = localDateTime.minusYears(-1);
System.out.println(newLocalDateTime2);
}
}
日常开发中更推荐使用 plus 系列,语义更符合直觉
with 系列方法:修改时间
withXxx() 方法用于直接修改某个字段的值,返回新对象。注意参数必须在合法范围内(如月份 1-12),否则抛出异常。
// JDK8DateDemo8.java
package com.wb.jdk8date;
import java.time.LocalDateTime;
/**
* JDK8 时间类修改时间
*/
public class JDK8DateDemo8 {
public static void main(String[] args) {
// public LocalDateTime withYear(int year) 修改年
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
// 修改年份为 2048 → 2048-11-11 13:14:15
LocalDateTime newLocalDateTime1 = localDateTime.withYear(2048);
System.out.println(newLocalDateTime1);
// 修改月份为 20(超出范围)→ 抛出 DateTimeException
// LocalDateTime newLocalDateTime2 = localDateTime.withMonth(20);
// System.out.println(newLocalDateTime2);
}
}
时间间隔对象 Period 和 Duration
JDK8 提供两个类用于计算时间间隔:
- Period:基于
LocalDate,计算两个日期之间的年、月、日。
通过Period.between(开始日期, 结束日期)获取间隔对象,再调用getYears()、getMonths()、getDays()、toTotalMonths()等方法 - Duration:基于包含时间的类(如 LocalDateTime、LocalTime),计算两个时间之间的秒、毫秒、纳秒。通过
Duration.between(开始时间, 结束时间)获取间隔对象,再调用toSeconds()、toMillis()、toNanos()等方法。
// JDK8DateDemo9.java
package com.wb.jdk8date;
import java.time.LocalDate;
import java.time.Period;
/**
* 计算两个日期的间隔(年、月、日)
*/
public class JDK8DateDemo9 {
public static void main(String[] args) {
LocalDate localDate1 = LocalDate.of(2020, 1, 1);
LocalDate localDate2 = LocalDate.of(2048, 12, 12);
Period period = Period.between(localDate1, localDate2);
System.out.println(period); // P28Y11M11D
System.out.println("年数:" + period.getYears()); // 28
System.out.println("月数:" + period.getMonths()); // 11
System.out.println("天数:" + period.getDays()); // 11
System.out.println("总月数:" + period.toTotalMonths()); // 347
}
}
// JDK8DateDemo10.java
package com.wb.jdk8date;
import java.time.Duration;
import java.time.LocalDateTime;
/**
* 计算两个时间的间隔(秒、毫秒、纳秒)
*/
public class JDK8DateDemo10 {
public static void main(String[] args) {
LocalDateTime localDateTime1 = LocalDateTime.of(2020, 1, 1, 13, 14, 15);
LocalDateTime localDateTime2 = LocalDateTime.of(2020, 1, 2, 11, 12, 13);
Duration duration = Duration.between(localDateTime1, localDateTime2);
System.out.println(duration); // PT21H57M58S
System.out.println("秒数:" + duration.toSeconds()); // 79078
System.out.println("毫秒:" + duration.toMillis()); // 79078000
System.out.println("纳秒:" + duration.toNanos()); // 79078000000000
}
}
JDK8 时间类小结
JDK8 新时间 API 的核心要点:
| 分类 | 关键类/方法 | 说明 |
|---|---|---|
| 日期时间类 | LocalDate / LocalTime / LocalDateTime | 分别表示日期、时间、日期+时间 |
| 创建对象 | now()、 of(...) | 当前时间 / 指定时间 |
| 获取字段 | getYear()、getMonthValue()、getDayOfMonth() 等 | 获取年、月、日、时、分、秒 |
| 转换 | toLocalDate()、toLocalTime() | 从 LocalDateTime 提取日期或时间 |
| 格式化/解析 | DateTimeFormatter.ofPattern() + format() / parse() | 替代 SimpleDateFormat |
| 时间加减 | plusXxx() / minusXxx() | 参数正数向前,负数向后 |
| 修改字段 | withXxx() | 直接修改某个字段,返回新对象 |
| 时间间隔 | Period.between() / Duration.between() | 计算日期间隔(年月日) / 时间间隔(秒毫秒纳秒) |
所有方法均返回新对象,原对象不受影响,符合不可变设计。遇到遗忘的方法,可查阅 JDK API 文档,通过 LocalDateTime 等类名快速定位
从古老的 Date 到简洁的 JDK8 时间类,到现在已经掌握了 Java 时间处理的核心技能。多加练习,熟能生巧!
1633

被折叠的 条评论
为什么被折叠?



