时间

JDK7 以前的时间相关类

关于时间的相关知识

全世界的时间, 有一个统一的计算标准.


图1

地球围绕太阳转一圈是一年, 自转一圈是一天.

同一条经线上的时间是一样的.

零度经线也叫做本初子午线.

在 1884 年的时候, 将格林威治的时间认为是世界标准时间.

全世界分为 24 个时区, 分为东 12 个区和西 12 个区. 每一个时区的时间都是在标准时间的基础上进行加或减.

本初子午线的右侧, 是东 12 个区, 称为东部地区, 是在标准时间的基础上增加时间. 中国位于东八区, 要在世界标准时间的基础上加 8 小时.

本初子午线的左侧, 是西 12 个区, 称为西部地区, 是在标准时间的基础上减时间.


图2

红色部分就是正午十二点.

格林尼治时间/格林威治时间 (Greenwich Mean Time) 简称 GMT.

格林威治时间的计算核心: 地球自转一天是 24 小时, 将 24 小时进行 24 等分, 太阳直射时为正午 12 点.

这个计算方法对于人们的日常生活是够用的, 但是后来人们发现地球的自转速度是不均匀的, 导致这种计算方式存在误差, 根据历史记录, 最大误差曾经达到了 16 分钟.

现在格林威治时间已经不再作为标准时间来使用了.

到了 2012 年 1 月, 取消了用了将近 130 年的回归制标准时间. 现在, 标准时间是由原子钟来提供的.

原子钟: 利用铯原子的震动的频率计算出来的时间, 作为世界标准时间 (UTC)

铯原子每震动 9,192,631,770 次等于 1 秒钟. 这种计算方式是非常精准的, 2000 万年的误差为 1 秒钟.


图4

Date 类

Date 类是一个 JDK 写好的 Javabean 类, 用来描述时间, 精确到毫秒.

利用空参构造创建的对象, 默认表示操作系统当前时间.

利用有参构造创建的对象, 表示指定的时间.

查看 Date 类的源码:


图5

图6

图7

图8

程序示例:

import java.util.Date;
public class Demo {
public static void main(String[] args) {
// public Date() // 创建 Date 对象, 表示当前时间
// public Date(long date) // 创建 Date 对象, 表示指定时间
// public void setTime(long time) // 设置/修改毫秒值
// public long getTime() // 获取时间对象的毫秒值
// 1. 创建对象表示一个时间
Date d1 = new Date();
System.out.println(d1); // Sun Nov 17 15:52:11 CST 2024
// 2. 创建对象表示一个指定的时间
Date d2 = new Date(0L); // 从时间原点开始, 过了 0 毫秒的那个时间, 也就是时间原点
System.out.println(d2); // Thu Jan 01 08:00:00 CST 1970. 我们在中国, 在东八区, 要在标准时间的基础上加八个小时
// 3. setTime 修改时间
// 1000 毫秒 = 1 秒
d2.setTime(1000L);
System.out.println(d2); // Thu Jan 01 08:00:01 CST 1970
// 4. getTime 获取某个指定时间对象的毫秒值
long time = d2.getTime();
System.out.println(time); // 1000
}
}

程序示例:

import java.util.Date;
import java.util.Random;
public class Demo {
public static void main(String[] args) {
/*
需求 1: 打印时间原点开始一年之后的时间
需求 2: 定义任意两个 Date 对象, 比较一下哪个时间在前, 哪个时间在后
*/
// 需求 2: 定义任意两个 Date 对象, 比较一下哪个时间在前, 哪个时间在后
Random r = new Random();
// 创建两个时间对象
Date d1 = new Date(Math.abs(r.nextInt()));
Date d2 = new Date(Math.abs(r.nextInt()));
long time1 = d1.getTime();
long time2 = d2.getTime();
if (time1 > time2) {
System.out.println("第一个时间在后面, 第二个时间在前面");
} else if (time1 < time2) {
System.out.println("第二个时间在后面, 第一个时间在前面");
} else {
System.out.println("表示两个时间一样");
}
}
private static void method() {
// 需求 1: 打印时间原点开始一年之后的时间
// 1. 创建一个对象, 表示时间原点
Date d1 = new Date(0L);
// 2. 获取 d1 时间的毫秒值
long time = d1.getTime();
// 3. 在这个基础上我们要加一年的毫秒值即可
time = time + 1000L * 60 * 60 * 24 * 365; // 加一个 L 防止计算结果超过 int 的范围
// 4. 把计算之后的时间毫秒值, 再设置回 d1 当中
d1.setTime(time);
// 5. 打印 d1
System.out.println(d1);
}
}

SimpleDateFormat 类

Date 类只能按照固定的格式打印时间, 而这个格式不符合一般的阅读习惯.

SimpleDateFormat 类的作用:

  • 格式化: 把时间变成我们喜欢的格式.

  • 解析: 把字符串表示的时间变成 Date 对象.


图9 SimpleDateFormat 类的构造方法

图10 SimpleDateFormat 类的成员方法

图11

图12

程序示例:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Demo3 {
public static void main(String[] args) throws ParseException {
/*
public simpleDateFormat() 默认格式
public simpleDateFormat(String pattern) 指定格式
public final string format(Date date) 格式化 (日期对象 -> 字符串)
public Date parse(string source) 解析 (字符串 -> 日期对象)
*/
// 1. 定义一个字符串表示时间
String str = "2023-11-11 11:11:11";
// 2. 利用空参构造创建 SimpleDateFormat 对象
// 细节:
// 创建对象的格式要跟字符串的格式完全一致
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(str);
// 3. 打印结果
System.out.println(date); // Sat Nov 11 11:11:11 CST 2023
System.out.println(date.getTime()); // 1699672271000
System.out.println("--------------------------------------------------------");
method1();
System.out.println("--------------------------------------------------------");
}
private static void method1() {
// 1. 利用空参构造创建 SimpleDateFormat 对象, 默认格式
SimpleDateFormat sdf1 = new SimpleDateFormat();
Date d1 = new Date(0L);
String str1 = sdf1.format(d1);
System.out.println(str1); // 1970/1/1 上午8:00
// 2. 利用带参构造创建 SimpleDateFormat 对象, 指定格式
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String str2 = sdf2.format(d1);
System.out.println(str2); // 1970年01月01日 08:00:00
// 课堂练习: yyyy年MM月dd日 时:分:秒 星期
SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EE");
String str3 = sdf3.format(d1);
System.out.println(str3); // 1970年01月01日 08:00:00 周四
}
}

程序示例:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class demo4 {
public static void main(String[] args) throws ParseException {
/*
* 假设, 你初恋的出生年月日为: 2000-11-11
* 请用字符串表示这个数据, 并将其转换为: 2000年11月11日
*
* 创建一个 Date 对象表示 2000年11月11日
* 创建一个 SimpleDateFormat 对象, 并定义格式为年月日把时间变成: 2000年11月11日
*/
// 1. 可以通过 2000-11-11 进行解析, 解析成一个 Date 对象
String str = "2000-11-11";
// 2. 解析
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf1.parse(str);
// 3. 格式化
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日");
String result = sdf2.format(date);
System.out.println(result); // 2000年11月11日
}
}

程序示例:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class demo5 {
public static void main(String[] args) throws ParseException {
/*
* 需求:
* 秒杀活动开始时间: 2023年11月11日 0:0:0 (毫秒值)
* 秒杀活动结束时间: 2023年11月11日 0:10:0 (毫秒值)
*
* 小贾下单并付款的时间为: 2023年11月11日 0:01:0
* 小皮下单并付款的时间为: 2023年11月11日 0:11:0
* 用代码说明这两位同学有没有参加上秒杀活动?
*/
// 1. 定义字符串表示三个时间
String startstr = "2023年11月11日 0:0:0";
String endstr = "2023年11月11日 0:10:0";
String orderstr = "2023年11月11日 0:01:00";
// 2. 解析上面的三个时间, 得到 Date 对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss");
Date startDate = sdf.parse(startstr);
Date endDate = sdf.parse(endstr);
Date orderDate = sdf.parse(orderstr);
// 3. 得到三个时间的毫秒值
long startTime = startDate.getTime();
long endTime = endDate.getTime();
long orderTime = orderDate.getTime();
// 4. 判断
if (orderTime >= startTime && orderTime <= endTime) {
System.out.println("参加秒杀活动成功"); // 参加秒杀活动成功
} else {
System.out.println("参加秒杀活动失败");
}
}
}

Calendar 类


图1

可以做, 但是比较麻烦.

Calendar 代表了系统当前时间的日历对象, 可以单独修改, 获取时间中的年, 月, 日.

细节: Calendar 是一个抽象类, 不能直接创建对象.

获取 Calendar 日历类对象的方法:


图2

图3

BuddhistCalendar 是佛历.

JapaneseImperialCalendar 是日本帝国历.

GregorianCalendar 是格林威治日历, 即公历.

程序示例:

import java.util.Calendar;
public class CalendarDemo2 {
public static void main(String[] args) {
/*
* public static Calendar lgetInstance() 获取当前时间的日历对象
* public final Date getTime() 获取日期对象
* public final setTime(Date date) 给日历设置日期对象
* public long getTimeInMillis() 拿到时间毫秒值
* public void setTimeInMillis(long millis) 给日历设置时间毫秒值
* public int get(int field) 获取日期中的某个字段信息
* public void set(int field,int value) 修改日历的某个字段信息
* public void add(int field,int amount) 为某个字段增加/减少指定的值
*/
// 1. 获取日历对象
// 细节 1: Calendar 是一个抽象类, 不能直接 new, 而是通过一个静态方法获取到子类对象
// 底层原理:
// 会根据系统的不同时区来获取不同的日历对象, 默认表示当前时间.
// 把会把时间中的纪元, 年, 月, 日, 时, 分, 秒, 星期, 等等的都放到一个数组当中
// 日 : 纪元
// 1 : 年
// 2 : 月
// 3 : 一年中的第几周
// 4 : 一个月中的第几周
// 5 : 一个月中的第几天 (日期)
// ....
// 细节 2:
// 月份: 范围 0~11 如果获取出来的是 0, 那么实际上是 1 月.
// 星期: 在老外的眼里, 星期日是一周中的第一天
// 1 (星期日) 2 (星期一) 3 (星期二) 4 (星期三) 5 (星期四) 6 (星期五) 7 (星期六)
Calendar c = Calendar.getInstance();
System.out.println(c);
}
}

getInstance() 源码:


图4

进入 createCalendar() 方法:


图5

Calendar 可以看作是一个抽象类. 它的实现, 采用了设计模式中的工厂方法.

当我们通过 Calendar.getInstance() 获取日历时, 默认的是返回的一个 GregorianCalendar 对象.

程序示例:

import java.util.Calendar;
import java.util.Date;
public class CalendarDemo2 {
public static void main(String[] args) {
/*
* public static Calendar lgetInstance() 获取当前时间的日历对象
* public final Date getTime() 获取日期对象
* public final setTime(Date date) 给日历设置日期对象
* public long getTimeInMillis() 拿到时间毫秒值
* public void setTimeInMillis(long millis) 给日历设置时间毫秒值
* public int get(int field) 获取日期中的某个字段信息
* public void set(int field,int value) 修改日历的某个字段信息
* public void add(int field,int amount) 为某个字段增加/减少指定的值
*/
// 1. 获取日历对象
// 细节 1: Calendar 是一个抽象类, 不能直接 new, 而是通过一个静态方法获取到子类对象
// 底层原理:
// 会根据系统的不同时区来获取不同的日历对象, 默认表示当前时间.
// 把会把时间中的纪元, 年, 月, 日, 时, 分, 秒, 星期, 等等的都放到一个数组当中
// 日 : 纪元
// 1 : 年
// 2 : 月
// 3 : 一年中的第几周
// 4 : 一个月中的第几周
// 5 : 一个月中的第几天 (日期)
// .... 一共 17 个属性, 所以索引最大为 16
// 细节 2:
// 月份: 范围 0~11 如果获取出来的是. 那么实际上是 1 月.
// 星期: 在老外的眼里,星期日是一周中的第一天
// 1 (星期日) 2 (星期一) 3 (星期二) 4 (星期三) 5 (星期四) 6 (星期五) 7 (星期六)
Calendar c = Calendar.getInstance();
// 2. 修改一下日历代表的时间
Date d = new Date(0L);
c.setTime(d);
System.out.println(c);
}
}

程序示例:

import java.util.Calendar;
import java.util.Date;
public class CalendarDemo2 {
public static void main(String[] args) {
/*
* public static Calendar lgetInstance() 获取当前时间的日历对象
* public final Date getTime() 获取日期对象
* public final setTime(Date date) 给日历设置日期对象
* public long getTimeInMillis() 拿到时间毫秒值
* public void setTimeInMillis(long millis) 给日历设置时间毫秒值
* public int get(int field) 获取日期中的某个字段信息
* public void set(int field,int value) 修改日历的某个字段信息
* public void add(int field,int amount) 为某个字段增加/减少指定的值
*/
// 1. 获取日历对象
// 细节 1: Calendar 是一个抽象类, 不能直接 new, 而是通过一个静态方法获取到子类对象
// 底层原理:
// 会根据系统的不同时区来获取不同的日历对象, 默认表示当前时间.
// 把会把时间中的纪元, 年, 月, 日, 时, 分, 秒, 星期, 等等的都放到一个数组当中
// 日 : 纪元
// 1 : 年
// 2 : 月
// 3 : 一年中的第几周
// 4 : 一个月中的第几周
// 5 : 一个月中的第几天 (日期)
// .... 一共 17 个属性, 所以索引最大为 16
// 细节 2:
// 月份: 范围 0~11 如果获取出来的是. 那么实际上是 1 月.
// 星期: 在老外的眼里,星期日是一周中的第一天
// 1 (星期日) 2 (星期一) 3 (星期二) 4 (星期三) 5 (星期四) 6 (星期五) 7 (星期六)
Calendar c = Calendar.getInstance();
// puslic int get(int field) 取日期中的某个字段信息
// public void set(int field,int value) 修改日历的某个字段信息
// public void add(int fieldint amount) 为某个字段增加/减少指定的值
int year = c.get(1);
int month = c.get(2);
int date = c.get(5);
System.out.println(year + ", " + month + ", " + date); // 2024, 8, 19
Date d = new Date(0L);
c.setTime(d);
int year1 = c.get(1);
int month1 = c.get(2) + 1;
int date1 = c.get(5);
System.out.println(year1 + ", " + month1 + ", " + date1); // 1970, 1, 1
// Java 在 Calendar 类中, 把索引对应的数字都定义成常量,
// 用数字当然也可以, 但是容易忘记, 阅读性也很低, 以后建议用常量,
// 常量值可以进入 Calendar 类的源码中查看
int year2 = c.get(Calendar.YEAR);
int month2 = c.get(Calendar.MONTH) + 1;
int date2 = c.get(Calendar.DAY_OF_MONTH);
int week2 = c.get(Calendar.DAY_OF_WEEK);
System.out.println(year2 + "," + month2 + "," + date2 + "," + week2); // 1970,1,1,5
// 最后的数字 5 表示星期四, 但是阅读性不强, 可以将其显示为星期四, 将该操作放在 getWeek() 中
System.out.println(year2 + "," + month2 + "," + date2 + "," + getWeek(week2)); // 1970,1,1,星期四
}
// 查表法:
// 表: 容器
// 让数据跟索引产生对应的关系
// 传入对应的数字: 1 ~7
// 返回对应的星期
public static String getWeek(int index) {
// 定义一个数组, 让汉字星期几 跟 1~7 产生对应关系
String[] arr = {"", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
// 根据索引返回对应的星期
return arr[index];
}
}

程序示例:

import java.util.Calendar;
public class CalendarDemo2 {
public static void main(String[] args) {
/*
* public static Calendar lgetInstance() 获取当前时间的日历对象
* public final Date getTime() 获取日期对象
* public final setTime(Date date) 给日历设置日期对象
* public long getTimeInMillis() 拿到时间毫秒值
* public void setTimeInMillis(long millis) 给日历设置时间毫秒值
* public int get(int field) 获取日期中的某个字段信息
* public void set(int field,int value) 修改日历的某个字段信息
* public void add(int field,int amount) 为某个字段增加/减少指定的值
*/
// 1. 获取日历对象
// 细节 1: Calendar 是一个抽象类, 不能直接 new, 而是通过一个静态方法获取到子类对象
// 底层原理:
// 会根据系统的不同时区来获取不同的日历对象, 默认表示当前时间.
// 把会把时间中的纪元, 年, 月, 日, 时, 分, 秒, 星期, 等等的都放到一个数组当中
// 日 : 纪元
// 1 : 年
// 2 : 月
// 3 : 一年中的第几周
// 4 : 一个月中的第几周
// 5 : 一个月中的第几天 (日期)
// .... 一共 17 个属性, 所以索引最大为 16
// 细节 2:
// 月份: 范围 0~11 如果获取出来的是. 那么实际上是 1 月.
// 星期: 在老外的眼里,星期日是一周中的第一天
// 1 (星期日) 2 (星期一) 3 (星期二) 4 (星期三) 5 (星期四) 6 (星期五) 7 (星期六)
Calendar c = Calendar.getInstance();
// puslic int get(int field) 取日期中的某个字段信息
// public void set(int field,int value) 修改日历的某个字段信息
// public void add(int fieldint amount) 为某个字段增加/减少指定的值
c.set(Calendar.YEAR, 2023);
c.set(Calendar.MONTH, 8);
c.set(Calendar.MONTH, 12); // 月份大于 11 时, 自动改变年份, 自动向后排, 此时相当于下一年的一月份
c.set(Calendar.DAY_OF_MONTH, 10);
// 调用方法在这个基础上增加一个月
c.add(Calendar.MONTH, -1);
int year2 = c.get(Calendar.YEAR);
int month2 = c.get(Calendar.MONTH) + 1;
int date2 = c.get(Calendar.DAY_OF_MONTH);
int week2 = c.get(Calendar.DAY_OF_WEEK);
System.out.println(year2 + "," + month2 + "," + date2 + "," + getWeek(week2)); // 2023,12,10,星期日
}
// 查表法:
// 表: 容器
// 让数据跟索引产生对应的关系
// 传入对应的数字: 1 ~7
// 返回对应的星期
public static String getWeek(int index) {
// 定义一个数组, 让汉字星期几 跟 1~7 产生对应关系
String[] arr = {"", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
// 根据索引返回对应的星期
return arr[index];
}
}

JDK8 新增的时间相关类


图1

图2

分成四组:


图3

全世界一共分为 24 个时区. 每一个时区内, 时间都是一样的.

但是 Java 定义时区时不是按照东一区, 东二区这种方式去定义的. 而是按照洲名/城市名或者国家名/城市名的格式来定义.

在中国, Java 定义了不止一个时区: Asia/Shanghai, Asia/Taipei, Asia/Chongqing. 一般都用上海.

全世界范围内, Java 一共定义了 600 个时区.

ZoneId 时区


图1

点击控制台, 点击 Ctrl + F, 可以在控制台输出的内容中进行搜索.

程序示例:

import java.time.ZoneId;
import java.util.Set;
public class Demo1 {
public static void main(String[] args) {
/*
static Set<string> getAvailableZoneIds() 获取 Java 中支持的所有时区
static ZoneId systemDefault() 获取系统默认时区
static Zoneld of(string zoneld) 获取一个指定时区
*/
// 1. 获取所有的时区名称
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
System.out.println(zoneIds.size()); // 600
System.out.println(zoneIds);
// 2. 获取当前系统的默认时区
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId); // Asia/Shanghai
// 3. 获取指定的时区
ZoneId zoneId1 = ZoneId.of("Asia/Pontianak");
System.out.println(zoneId1); // Asia/Pontianak
}
}

Instant 时间戳


图1

程序示例:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Demo2 {
public static void main(String[] args) {
/*
* static Instant now() 获取当前时间的 Instant 对象 (标准时间)
* static Instant ofXxxx(long epochMilli) 根据 (秒/毫秒/纳秒) 获取 Instant 对象
* ZonedDateTime atZone(ZoneIdzone) 指定时区
* boolean isxxx(Instant otherInstant) 判断系列的方法
* Instant minusXxx(long millisToSubtract) 减少时间系列的方法
* Instant plusXxx(long millisToSubtract) 增加时间系列的方法
*/
// 1. 获取当前时间的 Instant 对象 (标准时间)
Instant now = Instant.now();
System.out.println(now);
// 2. 根据 (秒/毫秒/纳秒) 获取 Instant 对象
Instant instant1 = Instant.ofEpochMilli(0L);
System.out.println(instant1); // 1970-01-01T00:00:00z
Instant instant2 = Instant.ofEpochSecond(1L);
System.out.println(instant2); // 1970-01-01T00:00:01Z
Instant instant3 = Instant.ofEpochSecond(1L, 1000000000L);
System.out.println(instant3); // 1970-01-01T00:00:027
// 3. 指定时区
ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
System.out.println(time);
// 4. isXxx 判断
Instant instant4 = Instant.ofEpochMilli(0L);
Instant instant5 = Instant.ofEpochMilli(1000L);
// 5. 用于时间的判断
// isBefore: 判断调用者代表的时间是否在参数表示时间的前面
boolean result1 = instant4.isBefore(instant5);
System.out.println(result1); // true
// isAfter: 判断调用者代表的时间是否在参数表示时间的后面
boolean result2 = instant4.isAfter(instant5);
System.out.println(result2); // false
// 6. Instant minusXxx(long millisToSubtract) 减少时间系列的方法
Instant instant6 = Instant.ofEpochMilli(3000L);
System.out.println(instant6); // 1970-01-01T00:00:03Z
Instant instant7 = instant6.minusSeconds(1);
System.out.println(instant7); // 1970-01-01T00:00:02Z
}
}

ZoneDateTime 带时区的时间


图1

程序示例:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Demo3 {
public static void main(String[] args) {
/*
* static ZonedDateTime now() 获取当前时间的 ZonedDateTime 对象
* static ZonedDateTime ofXxxx(. . . ) 获取指定时间的 ZonedDateTime 对象
* ZonedDateTime withXxx(时间) 修改时间系列的方法
* ZonedDateTime minusXxx(时间) 减少时间系列的方法
* ZonedDateTime plusXxx(时间) 增加时间系列的方法
*/
// 1. 获取当前时间对象 (带时区)
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now);
// 2. 获取指定的时间对象 (带时区) 1/年月日时分秒纳秒方式指定
ZonedDateTime time1 = ZonedDateTime.of(2023, 10, 1,
11, 12, 12, 0, ZoneId.of("Asia/Shanghai"));
System.out.println(time1);
// 通过 Instant + 时区的方式指定获取时间对象
Instant instant = Instant.ofEpochMilli(0L);
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
ZonedDateTime time2 = ZonedDateTime.ofInstant(instant, zoneId);
System.out.println(time2);
// 3. withXxx 修改时间系列的方法
ZonedDateTime time3 = time2.withYear(2000);
System.out.println(time3);
// 4. 减少时间
ZonedDateTime time4 = time3.minusYears(1);
System.out.println(time4);
// 5. 增加时间
ZonedDateTime time5 = time4.plusYears(1);
System.out.println(time5);
}
}

DateTimeFormatter 类: 用于时间的格式化和解析


图1

程序示例:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class demo4 {
public static void main(String[] args) {
/*
* static DateTimeFormatter ofPattern(格式) 获取格式对象
* String format(时间对象) 按照指定方式格式化
*/
// 获取时间对象
ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
// 解析/格式化器
DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm;ss EE a");
// 格式化
System.out.println(dtf1.format(time));
}
}

LocalDate, LocalTime, LocalDateTime 类

这三个类都是和 日历 Calendar 相关的.


图1

图2

程序示例:

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.MonthDay;
public class LocalDateDemo {
public static void main(String[] args) {
// 1. 获取当前时间的日历对象 (包含年月日)
LocalDate nowDate = LocalDate.now();
// System.out.println("今天的日期:" + nowDate);
// 2. 获取指定的时间的日历对象
LocalDate ldDate = LocalDate.of(2023, 1, 1);
System.out.println("指定日期:" + ldDate);
System.out.println("=============================");
// 3. get 系列方法获取日历中的每一个属性值
// 获取年
int year = ldDate.getYear();
System.out.println("year: " + year);
// 获取月
// 方式一:
Month m = ldDate.getMonth();
System.out.println(m);
System.out.println(m.getValue());
// 方式二:
int month = ldDate.getMonthValue();
System.out.println("month: " + month);
// 获取日
int day = ldDate.getDayOfMonth();
System.out.println("day:" + day);
// 获取一年的第几天
int dayofYear = ldDate.getDayOfYear();
System.out.println("dayOfYear:" + dayofYear);
// 获取星期
DayOfWeek dayOfWeek = ldDate.getDayOfWeek();
System.out.println(dayOfWeek);
System.out.println(dayOfWeek.getValue());
// is 开头的方法表示判断
System.out.println(ldDate.isBefore(ldDate));
System.out.println(ldDate.isAfter(ldDate));
// with 开头的方法表示修改, 只能修改年月日
LocalDate withLocalDate = ldDate.withYear(2000);
System.out.println(withLocalDate);
// minus 开头的方法表示减少, 只能减少年月日
LocalDate minusLocalDate = ldDate.minusYears(1);
System.out.println(minusLocalDate);
// plus 开头的方法表示增加, 只能增加年月日
LocalDate plusLocalDate = ldDate.plusDays(1);
System.out.println(plusLocalDate);
// -------------
// 判断今天是否是你的生日
LocalDate birDate = LocalDate.of(2000, 1, 1);
LocalDate nowDate1 = LocalDate.now();
MonthDay birMd = MonthDay.of(birDate.getMonthValue(), birDate.getDayOfMonth());
MonthDay nowMd = MonthDay.from(nowDate1);
System.out.println("今天是你的生日吗? " + birMd.equals(nowMd));// 今天是你的生日吗?
}
}

程序示例:

import java.time.LocalTime;
public class LocalTimeDemo {
public static void main(String[] args) {
// 获取本地时间的日历对象. (包含时分秒)
LocalTime nowTime = LocalTime.now();
System.out.println("今天的时间:" + nowTime);
int hour = nowTime.getHour(); // 时
System.out.println("hour: " + hour);
int minute = nowTime.getMinute(); // 分
System.out.println("minute: " + minute);
int second = nowTime.getSecond(); // 秒
System.out.println("second:" + second);
int nano = nowTime.getNano(); // 纳秒
System.out.println("nano:" + nano);
System.out.println("------------------------------------");
System.out.println(LocalTime.of(8, 20)); // 时分
System.out.println(LocalTime.of(8, 20, 30)); // 时分秒
System.out.println(LocalTime.of(8, 20, 30, 150)); // 时分秒纳秒
LocalTime mTime = LocalTime.of(8, 20, 30, 150);
// is 系列的方法
System.out.println(nowTime.isBefore(mTime));
System.out.println(nowTime.isAfter(mTime));
// with 系列的方法, 只能修改时, 分, 秒
System.out.println(nowTime.withHour(10));
// plus 系列的方法, 只能修改时, 分, 秒
System.out.println(nowTime.plusHours(10));
}
}

程序示例:

public class LocalDateTimeDemo {
public static void main(String[] args) {
// 当前时间的的日历对象 (包含年月日时分秒)
LocalDateTime nowDateTime = LocalDateTime.now();
System.out.println("今天是:" + nowDateTime); // 今天是:
System.out.println(nowDateTime.getYear()); // 年
System.out.println(nowDateTime.getMonthValue()); // 月
System.out.println(nowDateTime.getDayOfMonth()); // 日
System.out.println(nowDateTime.getHour()); // 时
System.out.println(nowDateTime.getMinute()); // 分
System.out.println(nowDateTime.getSecond()); // 秒
System.out.println(nowDateTime.getNano()); // 纳秒
// 日: 当年的第几天
System.out.println("dayofYear:" + nowDateTime.getDayOfYear());
// 星期
System.out.println(nowDateTime.getDayOfWeek());
System.out.println(nowDateTime.getDayOfWeek().getValue());
// 月份
System.out.println(nowDateTime.getMonth());
System.out.println(nowDateTime.getMonth().getValue());
LocalDate ld = nowDateTime.toLocalDate();
System.out.println(ld);
LocalTime lt = nowDateTime.toLocalTime();
System.out.println(lt.getHour());
System.out.println(lt.getMinute());
System.out.println(lt.getSecond());
}
}

三个工具类: Duration, Period 和 ChronoUnit

程序示例:

import java.time.LocalDate;
import java.time.Period;
public class PeriodDemo {
public static void main(String[] args) {
// 当前本地 年月日
LocalDate today = LocalDate.now();
System.out.println(today);
// 生日的年月日
LocalDate birthDate = LocalDate.of(2000, 1, 1);
System.out.println(birthDate);
Period period = Period.between(birthDate, today); // 第二个参数减第一个参数
System.out.println("相差的时间间隔对象:" + period);
System.out.println(period.getYears());
System.out.println(period.getMonths());
System.out.println(period.getDays());
System.out.println(period.toTotalMonths());
}
}

程序示例:

import java.time.Duration;
import java.time.LocalDateTime;
public class DurationDemo {
public static void main(String[] args) {
// 本地日期时间对象.
LocalDateTime today = LocalDateTime.now();
System.out.println(today);
// 出生的日期时间对象
LocalDateTime birthDate = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
System.out.println(birthDate);
Duration duration = Duration.between(birthDate, today); // 第二个参数减第一个参数
System.out.println("相差的时间间隔对象:" + duration);
System.out.println("============================================");
System.out.println(duration.toDays()); // 两个时间差的天数
System.out.println(duration.toHours()); // 两个时间差的小时数
System.out.println(duration.toMinutes()); // 两个时间差的分钟数
System.out.println(duration.toMillis()); // 两个时间差的毫秒数
System.out.println(duration.toNanos()); // 两个时间差的纳秒数
}
}

程序示例:

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
public class ChronoUnitDemo {
public static void main(String[] args) {
// 当前时间
LocalDateTime today = LocalDateTime.now();
System.out.println(today);
// 生日时间
LocalDateTime birthDate = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
System.out.println(birthDate);
System.out.println("相差的年数:" + ChronoUnit.YEARS.between(birthDate, today));
System.out.println("相差的月数:" + ChronoUnit.MONTHS.between(birthDate, today));
System.out.println("相差的周数:" + ChronoUnit.WEEKS.between(birthDate, today));
System.out.println("相差的天数:" + ChronoUnit.DAYS.between(birthDate, today));
System.out.println("相差的时数:" + ChronoUnit.HOURS.between(birthDate, today));
System.out.println("相差的分数:" + ChronoUnit.MINUTES.between(birthDate, today));
System.out.println("相差的秒数:" + ChronoUnit.SECONDS.between(birthDate, today));
System.out.println("相差的毫秒数:" + ChronoUnit.MILLIS.between(birthDate, today));
System.out.println("相差的微秒数:" + ChronoUnit.MICROS.between(birthDate, today));
System.out.println("相差的纳秒数:" + ChronoUnit.NANOS.between(birthDate, today));
System.out.println("相差的半天数:" + ChronoUnit.HALF_DAYS.between(birthDate, today));
System.out.println("相差的十年数:" + ChronoUnit.DECADES.between(birthDate, today));
System.out.println("相差的世纪(百年)数:" + ChronoUnit.CENTURIES.between(birthDate, today));
System.out.println("相差的千年数:" + ChronoUnit.MILLENNIA.between(birthDate, today));
System.out.println("相差的纪元数:" + ChronoUnit.ERAS.between(birthDate, today));
}
}
posted @   有空  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示

目录导航