经过之前对于API的学习:JAVA基础 —— API
接下来的文章让我们来了解一下不同类下的方法,但是这些方法不要去背。
而是要去记一下类名和类作用,也可以在以后去查阅API帮助文档。
Math、System、Runtime和Object | JAVA基础 (常用API)—— Math、System、Runtime和Object |
BigInteger和BigDecimal | JAVa基础(常用API) —— BigInteger和BigDecimal |
正则表达式 | JAVA基础(常用API) —— 正则表达式 |
时间相关类 | JAVA基础(常用API) —— 时间相关类 |
包装类 | JAVA基础(常用API) —— 包装类 |
目录
一、 JDK7以前时间相关类
时间的相关知识点:
世界标准时间: 格林尼治时间 / 格林威治时间 (Greenwich Mean Time) 简称GMT;
目前世界标准时间(UTC)已经替换为原子钟
中国标准时间:世界标准时间 + 8小时
时间换算单位:1秒 = 1000毫秒 ; 1毫秒 = 1000微秒 ; 1微秒 = 1000纳秒
1. Date时间类
Date类是一个JDK写好的Javabean类,用来描述时间,精确到毫秒。
- 利用空参构造创建的对象,默认表示系统当前时间。
- 利用有参构造有参构造创建的对象,表示指定的时间。
创建日期对象
- Date date = new Date();
- Date date = new Date( 指定毫秒值 );
修改时间对象中的毫秒值 setTime ( 毫秒值 ); 获取时间对象中的毫秒值 getTime( );
public class DateTest {
public static void main(String[] args) {
// 1.创建对象表示一个事件
Date d1 = new Date();
System.out.println(d1); // Tue Feb 28 21:18:31 CST 2023
// 2.创建对象表示一个指定时间
Date d2 = new Date(0L);
System.out.println(d2); // Thu Jan 01 08:00:00 CST 1970
// 3.修改时间
d2.setTime(1000L);
// 1000毫秒 = 1 秒
System.out.println(d2); // Thu Jan 01 08:00:01 CST 1970
// 4.获取时间
long time = d2.getTime();
// 将时间毫秒值或取出来 可以进行计算和比较
System.out.println(time); // 1000
}
}
2. SimpleDateFormat类
既然已经有Date类了,我们为什么还要用SimpleDateFormat类呢?
这样的结果很明显不符合我们的阅读习惯,所以我们引入了SimpleDateFormat类。
- 格式化:把时间变成我们习惯的形式。
- 解析:把字符串表示的时候变成Date对象。
2.1 构造方法
构造方法 | 说明 |
public SimpleDateFormat() | 构造一个SimpleDateFormat,使用默认格式 |
public SimpleDateFormat(String pattern) | 构造一个SimpleDateFormat,使用指定格式 |
2.2 成员方法
常用方法 | 说明 |
public final String format (Date date) | 格式化(日期对象 - > 字符串) |
public Date barse(String source) | 解析(字符串 - > 日期对象) |
2.3 格式化的时间形式的常用模式对应关系
public class DateTest {
public static void main(String[] args) throws ParseException {
// 一、格式化
method();
// 二、解析
// 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()); // 1699672271000
}
public static void method() {
// 1.利用空参构造创建SimpleDateFormat对象,默认格式
SimpleDateFormat sdf = new SimpleDateFormat();
Date d = new Date(0L);
String str = sdf.format(d);
System.out.println(str); // 70-1-1 上午8:00
// 2.利用带参构造创建SimpleDateFormat对象,指定格式
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date d1 = new Date(0L);
String str1 = sdf1.format(d1);
System.out.println(str1); // 1970年01月01日 08:00:00
// 练习: yyyy年MM月dd日 时:分:秒 +星期
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EE");
Date d2 = new Date(0L);
String str2 = sdf2.format(d2);
System.out.println(str2); // 1970年01月01日 08:00:00 星期四
}
}
3. Calendar类
为什么要学Calendar类呢?
因此,我们能够找到一个像日历一样的对象,找到月份在其基础上加一就可以了。
- Calendar代表了系统当前时间的日历对象,可以单独修改,获取时间中的年、月、日。
- 细节:Calendar是一个抽象类,不能直接创建对象。
- 获取Calendar日历对象的方法:
方法名 说明 public static Calendar getInstance() 获取当前时间的日历对象
3.1 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) | 为某个字段增加/减少指定的值 |
public class DateTest {
public static void main(String[] args) throws ParseException {
// 1.获取日历对象
// 细节1:Calendar是一个抽象类,并不能直接new ,需要通过静态方法获取到子类对象
// 底层原理
// 会根据系统不同时区获取不同日历对象
// 把时间中的纪元:年月日时分秒星期等方法一个数组中
Calendar c = Calendar.getInstance();
System.out.println(c);
// 2.修改日历代表时间
// 细节2:
// 如果获取的是月份: 则范围0~11 0:一月份 11:十二月份
// 如果是星期: 国际上 星期日是一周第一天 所以 1 :星期天
Date d = new Date(0L);
c.setTime(d);
System.out.println(c);
// 3.获取日期中某段字符信息
// c数组: 0 :纪元 | 1:年 | 2:月 | 3 :一年中第几周 | 4:一月中第几周 | 5:一月中第几天
int year = c.get(1);
int month = c.get(2) + 1; // 月份范围0~11 所以获取值+1
int date = c.get(5);
// java在Calendar类中,把索引对应数字都定义为常量
int week = c.get(Calendar.DAY_OF_WEEK);
System.out.println(year + "," + month + "," + date + "," + week); // 1970,1,1,5
// 那我们怎么做可以让输出结果为:1970,1,1,星期四呢?
// 定义一个方法getWeek
System.out.println(year + "," + month + "," + date + "," + getWeek(week));
// 4.修改日历的某个字段信息
c.set(Calendar.YEAR, 2000);
c.set(Calendar.MONTH, 11);
int year1 = c.get(Calendar.YEAR);
int month1 = c.get(Calendar.MONTH) + 1;
System.out.println(year1 + "," + month1 + "," + date); // 2000,12,1
// 5. 为摸个字段增加或减少指定的值
c.add(Calendar.MONTH, 1);
int month2 = c.get(Calendar.MONTH) + 1;
System.out.println(year1 + "," + month2 + "," + date); // 2000,1,1
}
// 传入对应数字 : 1~7
// 返回对应星期
public static String getWeek(int index) {
// 定义数组 让汉字与数字产生对应关系
String[] arr = { "", "星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
// 根据索引返回星期
return arr[index];
}
}
二、JDK8新增时间相关类
为什么要学习JDK8新增时间相关类?
JDK7时间类 JDK8时间类
代码层次 安全层面 JDK7 代码麻烦(日期对象计算和比较都要转换为毫秒值)
多线程环境下会导致数据安全的问题 JDK8 简单(有判断的方法、计算时间间隔的方法) 时间日期对象都是不可变的,解决了这个问题
1. Date类
- ZoneId:时区
- Instant:时间戳
- ZoneDateTime:带时区的时间
1.1 ZoneId时区
方法名 | 说明 |
static Set<String> getAvailableZoneIds () | 获取java中支持的所有的时区 |
static ZoneId systemDefault() | 获取系统默认时区 |
static ZoneId of (String zoneId) | 获取一个指定时区 |
public class DateTest {
public static void main(String[] args) throws ParseException {
//1.获取所有时区名称
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
System.out.println(zoneIds.size()); //602
System.out.println(zoneIds);
//2.获取当前系统的默认时区
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId); //Asia/Shanghai
//3.获取指定的时区
ZoneId zoneId1 = ZoneId.of("Asia/Yangon");
System.out.println(zoneId1); //Asia/Yangon
}
}
1.2 Instant时间戳
方法名 | 说明 |
static Instant now( ) | 获取当前时间的Instant对象(标准时间) |
static Instant ofXxxx( long epochMilli) | 根据(秒/毫秒/纳秒)获取Instant对象 |
zonedDateTime atzone(zoneId zone) | 指定时区 |
boolean isXxx( Instant otherInstant) | 判断系列的方法 |
Instant minusXxx( long millisToSubtract) | 减少时间系列的方法 |
Instant plusXxx( long millisToSubtract) | 增加时间系列的方法 |
public class DateTest {
public static void main(String[] args) throws ParseException {
// 1.获取当前时间的Instant对象(标准时间)
Instant now = Instant.now();
System.out.println(now); // 2023-03-01T02:30:56.124Z
// 2.根据指定(秒/毫秒/微秒)获取Instant对象
Instant instant1 = Instant.ofEpochMilli(0L);
System.out.println(instant1); // 1970-01-01T00:00:00Z
Instant instant2 = Instant.ofEpochSecond(1L);
System.err.println(instant2); // 1970-01-01T00:00:01Z
Instant instant3 = Instant.ofEpochSecond(1L, 1000000000L);
System.out.println(instant3); // 1970-01-01T00:00:02Z
// 3.制定时区
ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
System.out.println(time); // 2023-03-01T10:35:46.241+08:00[Asia/Shanghai]
// 4.用于时间的判断 isXxx
// isBefore:判断调用者代表时间是否在参数表示时间前面
Instant instant4 = Instant.ofEpochMilli(0L);
Instant instant5 = Instant.ofEpochMilli(1000L);
boolean result = instant4.isBefore(instant5);
System.out.println(result); // true
// isAfter:判断调用者代表时间是否在参数表示时间后面
boolean result1 = instant4.isAfter(instant5);
System.out.println(result1); // fasle
// 5.减少时间系列
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
}
}
1.3 ZoneDateTime带时区的时间
方法名 | 说明 |
static zonedDateTime now( ) | 获取当前时间的ZonedDateTime对象 |
static zonedDateTime ofXxxx( ) | 获取指定时间的ZonedDateTime对象 |
zonedDateTime withXxx(时间) | 修改时间系列的方法 |
zonedDateTime minusXxx(时间) | 减少时间系列的方法 |
zonedDateTime plusXxx(时间) | 增加时间系列的方法 |
public class DateTest {
public static void main(String[] args) throws ParseException {
// 1获取当前时间(带时区)
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now); // 2023-03-01T10:53:00.648+08:00[Asia/Shanghai]
// 2.获取指定的时间对象(带时区)
// 年月日时分秒方式指定
ZonedDateTime time1 = ZonedDateTime.of(2023, 10, 1, 11, 12, 12, 1, ZoneId.of("Asia/Shanghai"));
System.out.println(time1); // 2023-10-01T11:12:12.000000001+08:00[Asia/Shanghai]
// 通过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.修改时间系列方法
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); // 1999-01-01T08:00+08:00[Asia/Shanghai]
// JDK8新增的时间对象是不可变的
// 当我们修改了时间
// 那么调用者是不会发生改变的 ,其实产生了一个新的时间
}
}
2. 日期格式化类:SimpleDateFormat
DateTimeFormatter:用于时间的格式化和解析
方法名 说明 static DateTineFormatter ofPattern ( 格式 ) 获取格式对象 String format( 时间对象 ) 按照指定方式格式化
public class DateTest {
public static void main(String[] args) throws ParseException {
// 获取时间对象
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)); // 2023-03-01 11:05:00 星期三 上午
}
}
3. 日历类:Calendar
- LocalDate:年、月、日
- LocalTime:时、分、秒
- LocalDateTime:年、月、日 时、分、秒
方法名 说明 public LocalDate toLocalDate() LocalDateTime转换为一个 LocalDate对象 public LocalTime toLocalTime () LocalDateTime转换为一个 LocalTime对象
方法名 | 说明 |
static XXX now ( ) | 获取当前时间的对象 |
static XXX of ( ) | 获取指定时间的对象 |
get开头的方法 | 获取日历中的年、月、日、时、分、秒等信息 |
isBefore,isAfter | 比较两个LocalDate |
with开头的 | 修改时间系列的方法 |
minus开头的 | 减少时间系列的方法 |
plus开头的 | 增加时间系列的方法 |
public class DateTest {
public static void main(String[] args) throws ParseException {
// 1.获取当前时间的日历对象(包含 年月日)
LocalDate nowDate = LocalDate.now();
System.out.println(nowDate); // 2023-03-01
// 2.获取指定的时间的日历对象
LocalDate ldDate = LocalDate.of(2023, 1, 1);
System.out.println(ldDate); // 2023-01-01
// 3.get系列方法获取日历中的每一个属性值
// 获取年
int year = ldDate.getYear();
System.out.println(year); // 2023
// 获取月
int month = ldDate.getMonthValue();
System.out.println(month); // 1
// 获取日
int day = ldDate.getDayOfMonth();
System.out.println(day); // 1
// 获取一年中的第几天
int dayOfYear = ldDate.getDayOfYear();
System.out.println(dayOfYear); // 1
// 获取星期
DayOfWeek dayOfWeek = ldDate.getDayOfWeek();
System.out.println(dayOfWeek); // SUNDAY
System.out.println(dayOfWeek.getValue()); // 7
// is开头
System.out.println(ldDate.isBefore(ldDate)); // false
System.out.println(ldDate.isAfter(ldDate)); // false
// with开头
LocalDate withLocalDate = ldDate.withYear(2000);
System.out.println(withLocalDate); // 2000-01-01
// minus开头
LocalDate minusLocalDate = ldDate.minusYears(1);
System.out.println(minusLocalDate); // 2022-01-01
// plus开头
LocalDate plusLocalDate = ldDate.plusYears(1);
System.out.println(plusLocalDate); // 2024-01-01
}
}
4. 工具类
- Duration:时间间隔(秒,纳秒):用于计算两个"时间"间隔
- Period:时间间隔(年,月,日):用于计算两个"日期"间隔
- ChronoUnit:时间间隔(所有单位):用于计算两个"日期"间隔
public class DateTest {
public static void main(String[] args) throws ParseException {
// 1.period日期
LocalDate today = LocalDate.now();
System.out.println(today); // 2023-03-01
LocalDate date = LocalDate.of(2000, 1, 1);
System.out.println(date); // 2000-01-01
Period period = Period.between(date, today);
System.out.println(period); // P23Y2M
System.out.println(period.getYears()); // 23
System.out.println(period.getMonths()); // 2
System.out.println(period.getDays()); // 0
System.out.println(period.toTotalMonths()); // 278
// 2.duration日期
LocalDateTime todayTime = LocalDateTime.now();
System.out.println(todayTime); // 2023-03-01T11:39:25.614
LocalDateTime time = LocalDateTime.of(2000, 1, 1, 0, 00, 00);
System.out.println(time); // 2000-01-01T00:00
Duration duration = Duration.between(time, todayTime);
System.out.println(duration); // PT203051H39M25.614S
System.out.println(duration.toDays()); // 时间差天数 8460
System.out.println(duration.toHours()); // 时间差小时数 203051
System.out.println(duration.toMinutes()); // 时间差分钟数 12183099
System.out.println(duration.toMinutes()); // 时间差毫秒数 12183099
System.out.println(duration.toNanos()); // 时间差纳秒数 730985965614000000
// 3.ChronoUnit日期
System.out.println("相差年数" + ChronoUnit.YEARS.between(time, todayTime)); // 相差年数23
}
}