【JAVA入门】Day21 - 时间类
文章目录
- 【JAVA入门】Day21 - 时间类
- 一、JDK7前的时间相关类
- 1.1 Date
- 1.2 SimpleDateFormat
- 1.3 Calendar
- 二、JDK8新增的时间相关类
- 2.1 Date 相关类
- 2.1.1 ZoneId 时区
- 2.1.2 Instant 时间戳
- 2.1.3 ZoneDateTime 带时区的时间
- 2.2 DateTimeFormat 相关类
- 2.2.1 DateTimeFormatter 时间的格式化和解析类
- 2.3 Calendar 相关类
- 2.3.1 LocalDate、LocalTime、LocalDateTime
- 2.4 JDK8 新增的三个工具类
Java 中的时间有一些相关类,它们都与时间的编程息息相关。
一、JDK7前的时间相关类
类名 | 作用 |
---|---|
Date | 时间类 |
SimpleDateFormat | 格式化时间 |
Calender | 日历类 |
世界上的时间,是有一个统一的计算标准的。
曾经的世界时间标准被称作 格林尼治时间 / 格林威治时间 (Greenwich Mean Time),简称GMT。GMT 的计算核心是:地球自转一天是24小时,太阳直射时为正午12点。但是由于误差太大,现在 GMT 已经被舍弃。
现在的世界时间标准是利用原子钟规定的,利用铯原子的振动频率计算出来的时间,作为世界标准时间(UTC)。
中国地处东八区,要在世界标准时间的基础上 + 8小时。
1.1 Date
Date 类是 JDK 写好的一个 Javabean 类,用来描述时间,精确到毫秒。
利用空参构造创建的对象,默认表示为系统当前时间。
利用有参构造创建的对象,表示为指定的时间。
方法 | 作用 |
---|---|
public Date() | 创建Date对象,表示系统当前时间 |
public Date(long date) | 创建Date对象,表示指定时间 |
public void setTime(long time) | 设置/修改毫秒值 |
public long getTime() | 获取时间对象的毫秒值 |
【练习】学习使用Date类。
package DateClass;
import java.util.Date;
import java.util.Random;
public class DateDemo2 {
public static void main(String[] args) {
//需求一:打印一年后的时间
extracted();
//需求二:比较两个Date对象哪个在前哪个在后
extracted1();
}
private static void extracted() {
//1.打印时间原点一年后的时间
Date d1 = new Date(0L);
//2.获取d1的毫秒值
long time = d1.getTime();
//3.加上一年后的毫秒值
time = time + 1000L * 60 * 60 * 24 * 365;
//4.把计算后的时间毫秒值,设置回d1中
d1.setTime(time);
//5.打印
System.out.println(d1);
}
private static void extracted1() {
Random r = new Random();
//创建两个时间对象
Date d1 = new Date(r.nextInt());
Date d2 = new Date(r.nextInt());
System.out.println(d1);
System.out.println(d2);
long time1 = d1.getTime();
long time2 = d2.getTime();
if(time1 > time2) {
System.out.println("d2在前,d1在后");
} else if(time2 > time1) {
System.out.println("d1在前,d2在后");
} else {
System.out.println("两时间一样");
}
}
}
}
1.2 SimpleDateFormat
Date 类只能以默认的格式展示,不符合人们的阅读习惯。
SimpleDateFormat 可以把日期格式化;也可以解析日期,即把字符串表示的时间编程 Date 对象。
构造方法 | 说明 |
---|---|
public SimpleDateFormat() | 构造一个SimpleDateFormat对象,使用默认格式 |
public SimpleDateFormat(String pattern) | 构造一个SimpleDateFormat对象,使用指定的格式 |
常用方法 | 说明 |
---|---|
public final String format(Date date) | 格式化(日期对象 -> 字符串) |
public Date parse(String source) | 解析(字符串 -> 日期对象) |
格式化的时间形式的常用模式对应关系如下:
【练习1】练习使用SimpleDateFormat。
package DateClass;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDemo3 {
public static void main(String[] args) throws ParseException {
//需求一:格式化时间
method1();
//需求二:解析字符串
method2();
}
private static void method2() throws ParseException {
//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);
//打印毫秒值
System.out.println(date.getTime());
}
private static void method1() {
//1.利用空参构造创建SimpleDateFormat对象,默认格式
SimpleDateFormat sdf = new SimpleDateFormat();
Date d1 = new Date(0L);
String str = sdf.format(d1);
System.out.println(str); //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
//3.格式2
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秒 周四
}
}
【练习2】把一个日期转换为另一种格式。
package DateClass;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDemo4 {
public static void main(String[] args) throws ParseException {
/*2000-11-11*/
String str = "2000-11-11";
//1.解析字符串为日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse(str);
//2.格式化日期为年月日
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日");
String result = sdf1.format(date);
//3.打印
System.out.println(result);
}
}
【练习3】判断两个同学是否秒杀成功。
package DateClass;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDemo5 {
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:00
小皮下单付款时间:2023年11月11日 0:11:00
计算两个人有没有参加成功
*/
//1.比较两个时间
String startStr = "2023年11月11日 0:0:0";
String endStr = "2023年11月11日 0:10:0";
String orderStr1 = "2023年11月11日 0:01:0";
String orderStr2 = "2023年11月11日 0:11:00";
//2.解析上面的时间,得到Date对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date startDate = sdf.parse(startStr);
Date endDate = sdf.parse(endStr);
Date orderDate1 = sdf.parse(orderStr1);
Date orderDate2 = sdf.parse(orderStr2);
//3.得到所有时间的毫秒值
long startTime = startDate.getTime();
long endTime = endDate.getTime();
long orderTime1 = orderDate1.getTime();
long orderTime2 = orderDate2.getTime();
//4.判断
if((startTime <= orderTime1)&&(orderTime1 <= endTime)) {
System.out.println("小贾同学秒杀成功了!");
}else{
System.out.println("小贾同学秒杀失败了...");
}
if((startTime <= orderTime2)&&(orderTime2 <= endTime)) {
System.out.println("小皮同学秒杀成功了!");
}else{
System.out.println("小皮同学秒杀失败了...");
}
}
}
1.3 Calendar
Calendar 就是日历类,它是时间类的补充,可以单独修改、获取事件中的年,月,日。
值得注意的是,Calendar 是一个抽象类,它不能直接创建对象。
我们需要通过一个静态方法来获取当前时间的日历对象。
public static Calendar getInstance()
Calendar 中常用的方法有这些:
方法名 | 说明 |
---|---|
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) | 为某个字段增加/减少指定的值 |
下面通过一个练习,熟悉一下这些方法。
package DateClass;
import java.util.Calendar;
import java.util.Date;
public class CalenderDemo1 {
public static void main(String[] args) {
//1.获取日历对象
//Calender是一个抽象类,不能直接new,而是通过一个静态方法获取子类对象
Calendar c = Calendar.getInstance();
//底层原理:
//会根据系统的不同时区来获取不同的日历对象
//把时间中的纪元,年,月,日,时,分,秒,星期,等等放到一个数组当中
//2.修改一下日历代表的时间为时间原点
//获取的时间信息有细节
// 月份范围:0~11,0代表一月,11代表十二月
// 星期:星期日是第一天,值为1;星期六的值为7
Date d = new Date(0L);
c.setTime(d);
//3.获取日期中某个字段信息
//参数为int类型
//0:纪元 1:年 2:月 3:一年中的第几周 ...
//Java当中,把索引数字都定义为了常量
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH) + 1;
int date = c.get(Calendar.DAY_OF_MONTH);
int week = c.get(Calendar.DAY_OF_WEEK);
System.out.println(year + ", " + month + ", "+ date+ ", " + getWeek(week));
//4.修改日历中某个字段
c.set(Calendar.YEAR, 2000);
c.set(Calendar.MONTH,12);
//月份12是指13月,这是不存在的
//系统会自动把年份调成次年
//5.为某个字段增加/减少值
c.add(Calendar.MONTH, -1);
}
//传入对应的数字:1~7
//返回对应的星期
//查表法:在方法中让数据跟索引产生对应关系
public static String getWeek(int index) {
String[] arr = {"","星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
return arr[index];
}
}
二、JDK8新增的时间相关类
JDK8 新增的时间相关类,解决了 JDK7 代码麻烦的问题,而且在安全层面下有了突破。
JDK7 在多线程环境下会导致数据安全问题产生,而 JDK8 的时间日期对象都是不可变的,解决了这个问题。
JDK8 主要新增了以下四种类:
2.1 Date 相关类
2.1.1 ZoneId 时区
时区类常用方法如下。
package DateClass;
import java.time.ZoneId;
import java.util.Set;
public class CalenderDemo2 {
public static void main(String[] args) {
/*
时区
*/
//1.获取所有的时区名称
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
System.out.println(zoneIds);
System.out.println(zoneIds.size());
//2.获取当前系统的默认时区
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId);
//3.获取指定的时区
ZoneId zoneId1 = ZoneId.of("Asia/Aqtau");
System.out.println(zoneId1);
}
2.1.2 Instant 时间戳
时间戳是一种新的计算时间方法,它可以精确到时间的纳秒值(标准时间)。
package DateClass;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class DateDemo6 {
public static void main(String[] args) {
//1.获取当前时间的Instant对象(标准时间)
Instant now = Instant.now();
System.out.println(now); //2024-08-16T10:35:23.164490400Z
//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
//获取1秒+1000000000纳秒后的时间
Instant instant3 = Instant.ofEpochSecond(1L, 1000000000L);
System.out.println(instant3); //1970-01-01T00:00:02Z
//3.指定时区
//指定时区后再获得当前系统时间,中国在东八区,会自动加上8个小时
ZonedDateTime zonedDateTime = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
System.out.println(zonedDateTime); //2024-08-16T18:45:01.710355900+08:00[Asia/Shanghai]
//4.isXxx 判断
Instant instant4 = Instant.ofEpochMilli(0L);
Instant instant5 = Instant.ofEpochMilli(1000L);
boolean result1 = instant4.isBefore(instant5);
System.out.println(result1); //true
boolean result2 = instant4.isAfter(instant5);
System.out.println(result2); //false
//5.增减时间
Instant instant6 = Instant.ofEpochMilli(3000L);
System.out.println(instant6); //1970-01-01T00:00:03Z
Instant instant7 = instant6.minusSeconds(1L);
System.out.println(instant7); //1970-01-01T00:00:02Z
Instant instant8 = instant6.plusMillis(5000L);
System.out.println(instant8); //1970-01-01T00:00:08Z
}
}
2.1.3 ZoneDateTime 带时区的时间
带时区的时间就是带上时区的时间。
package DateClass;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class DateDemo7 {
public static void main(String[] args) {
//1.获取当前带时区的时间对象
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now);
//2.获取指定的带时区时间对象
//年月日时分秒纳秒方式指定
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); //1970-01-01T08:00+08:00[Asia/Shanghai]
//3.withXxx 修改时间系列的方法,可以单独修改年月日等
ZonedDateTime time3 = time2.withYear(2000);
System.out.println(time3); //2000-01-01T08:00+08:00[Asia/Shanghai]
//4.减少时间
ZonedDateTime time4 = time3.minusYears(1);
System.out.println(time4);
//5.增加时间
ZonedDateTime time5 = time3.plusYears(1);
System.out.println(time5);
//细节:
//JDK8新增的时间对象都是不可变的
//如果我们进行任何形式的修改,调用者本身都不会改变,而是会产生一个新的时间
}
}
2.2 DateTimeFormat 相关类
2.2.1 DateTimeFormatter 时间的格式化和解析类
两个方法用来时间格式化和解析。被解析的时间对象可以是ZonedDateTime (带时区的时间类对象)。
package DateClass;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class DateDemo8 {
public static void main(String[] args) {
//获取时间对象
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));
}
}
2.3 Calendar 相关类
2.3.1 LocalDate、LocalTime、LocalDateTime
这三个类是这种关系,LocalDateTime 能表示的最全,年月日时分秒都可以,LocalDate 只能表示年月日,LocalTime 只能表示时分秒。LocalDate 和 LocalTime 之间可以互转。
LocalDate 类用法如下。
package DateClass;
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();
//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对象获取
Month m = ldDate.getMonth();
System.out.println(m);
System.out.println(m.getValue());
//方式二:用int变量接收
int month = ldDate.getMonthValue();
System.out.println(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);
System.out.println(withLocalDate == ldDate); //false
//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.of(nowDate1.getMonthValue(), nowDate1.getDayOfMonth());
System.out.println("今天是你的生日吗?" + birMd.equals(nowMd));
}
}
LocalTime 类用法如下。
package DateClass;
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, 30)); //时分秒
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));
//minus系列
System.out.println(nowTime.minusHours(10));
//plus系列
System.out.println(nowTime.plusHours(10));
}
}
2.4 JDK8 新增的三个工具类
它们是:
- Duration:时间间隔(秒,纳秒)
- Period:时间间隔(年,月,日)
- ChronoUnit:时间间隔(所有单位)
Period - 计算年月日之间的时间间隔。
package DateClass;
import java.time.LocalDate;
import java.time.Period;
public class TimeUtils {
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());
}
}
Duration - 计算时分秒之间的时间间隔
package DateClass;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
public class TimeUtils {
public static void main(String[] args) {
//当前本地年月日
LocalDateTime today = LocalDateTime.now();
System.out.println(today);
//出生日期的时间对象
LocalDateTime birthDate = LocalDateTime.of(2000,1,1,0,00,00);
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());
}
}
ChronoUnit - 计算年月日时分秒的时间间隔。
package DateClass;
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));
}
}