184030-17373696308939

JDK8之前的日期、时间

Date

代表日期和时间

img

代码案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main(String[] args) {
// 创建一个Date对象,代表当前时间
Date date = new Date();
System.out.println(date);

// 获取当前时间的毫秒值
long time = date.getTime();
System.out.println(time);

// 创建一个Date对象,指定该对象代表的时间
time += 3 * 1000;
Date date2 = new Date(time);
System.out.println(date2);

// 通过setTime指定Date对象的时间
Date date3 = new Date();
date3.setTime(time);
System.out.println(date3);
}

代码运行的结果如下

img

SimpleDateFormat

SimpleDateFormat类不是线程安全的:通过查看SimpleDateFormat类的源码,我们得知:SimpleDateFormat是继承自DateFormat类,DateFormat类中维护了一个全局的Calendar变量。*DateFormat类中的Calendar对象被多线程共享,而Calendar对象本身不支持线程安全。*

代表简单日期格式化,可以用来把日期对象、时间毫秒值格式化成我们想要的形式

img

将Date对象格式化成字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 public static void main(String[] args) {
// 创建一个Date对象,代表当前时间
Date date = new Date();
System.out.println(date);

// 获取当前时间的毫秒值
long time = date.getTime();
System.out.println(time);

// 创建SimpleDateFormat对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EEE a");
String ds1 = sdf.format(date);
String ds2 = sdf.format(time);

System.out.println(ds1);
System.out.println(ds2);
}

将字符串反序列化成Date对象

1
2
3
4
5
6
7
8
9
public static void main(String[] args) throws ParseException {
// 定义一个日期字符串
String dateStr = "2024-10-11 15:22:22";

// 创建一个SimpleDateFormat对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(dateStr);
System.out.println(date);
}

Calendar

代表的是系统此刻时间对应的日历。

通过它可以单独获取、修改时间中的年、月、日、时、分、秒等。

Calendar的常用方法

img

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public static void main(String[] args) throws ParseException {
// 得到当前系统时间的日历对象
Calendar now = Calendar.getInstance();
System.out.println(now);

/**
* 打印出来的信息如下
* java.util.GregorianCalendar
* [time=1737430543014,areFieldsSet=true,areAllFieldsSet=true,lenient=true,
* zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,
* transitions=31,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,
* YEAR=2025,MONTH=0,WEEK_OF_YEAR=4,WEEK_OF_MONTH=4,DAY_OF_MONTH=21,DAY_OF_YEAR=21,
* DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=3,AM_PM=0,HOUR=11,HOUR_OF_DAY=11,MINUTE=35,
* SECOND=43,MILLISECOND=14,ZONE_OFFSET=28800000,DST_OFFSET=0]
*/

// 获取日历中的某个信息
int year = now.get(Calendar.YEAR);
int month = now.get(Calendar.MONTH);
System.out.println(year);
System.out.println(month);

// 获取日历中的Date对象
Date time = now.getTime();
System.out.println(time);

// 获取日期毫秒值
long timeInMillis = now.getTimeInMillis();
System.out.println(timeInMillis);

// 修改日历中的某个信息
now.set(Calendar.YEAR, 2022);
System.out.println(now);

// 为某个信息增加或者减少多少
now.add(Calendar.YEAR, 10);
System.out.println(now);
now.add(Calendar.YEAR, -20);
System.out.println(now);
}

如果参数field不知道怎么填,可以将Calendar对象打印出来,参考其中的字段

注意:Calendar是一个可变对象,修改后对象本身表示的时间将发生变化

JDK8新增的日期、时间

LocalDate

代表本地日期:年、月、日、星期

获取日期相关的信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void main(String[] args) {
// 获取LocalDate对象
LocalDate ld = LocalDate.now();

// 获取对象中的信息
int year = ld.getYear(); // 年
int month = ld.getMonthValue(); // 月
int day = ld.getDayOfMonth(); // 日
int dayOfWeek = ld.getDayOfWeek().getValue();// 星期几
int dayOfYear = ld.getDayOfYear();// 一年中的第几天

System.out.println(year);
System.out.println(month);
System.out.println(day);
System.out.println(dayOfWeek);
System.out.println(dayOfYear);
}

直接修改某个信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
// 获取LocalDate对象
LocalDate ld = LocalDate.now();

// 直接修改某个信息
LocalDate ld2 = ld.withYear(2098);
LocalDate ld3 = ld2.withMonth(12);
LocalDate ld4 = ld3.withDayOfMonth(31);
LocalDate ld5 = ld4.withDayOfYear(1);
// 可以看到是一个不可变对象,修改信息原对象的值没有改变
System.out.println(ld);
System.out.println(ld2);
System.out.println(ld3);
System.out.println(ld4);
System.out.println(ld5);
}

把某个信息增加多少

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) {
// 获取LocalDate对象
LocalDate ld = LocalDate.now();

// 把某个信息增加多少
LocalDate ld2 = ld.plusYears(2);
System.out.println(ld2);

LocalDate ld3 = ld2.plusMonths(2);
System.out.println(ld3);

LocalDate ld4 = ld3.plusDays(2);
System.out.println(ld4);

LocalDate ld5 = ld4.plusWeeks(10);
System.out.println(ld5);

}

把某个信息减少多少

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) {
// 获取LocalDate对象
LocalDate ld = LocalDate.now();

// 把某个信息增加多少
LocalDate ld2 = ld.minusYears(2);
System.out.println(ld2);

LocalDate ld3 = ld2.minusMonths(2);
System.out.println(ld3);

LocalDate ld4 = ld3.minusDays(2);
System.out.println(ld4);

LocalDate ld5 = ld4.minusWeeks(10);
System.out.println(ld5);

}

获取指定日期的LocalDate对象

1
2
3
4
5
6
7
8
 public static void main(String[] args) {
// 获取指定日期的LocalDate对象
LocalDate ld1 = LocalDate.of(2020, 12, 21);
System.out.println(ld1);

LocalDate ld2 = LocalDate.of(2020, Month.FEBRUARY, 21);
System.out.println(ld2);
}

判断两个日期是否相等,在前还是在后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void main(String[] args) {
// 获取指定日期的LocalDate对象
LocalDate ld1 = LocalDate.of(2020, 12, 21);
System.out.println(ld1);

LocalDate ld2 = LocalDate.of(2020, Month.FEBRUARY, 21);
System.out.println(ld2);

boolean f1 = ld1.equals(ld2);
System.out.println(f1);

boolean f2 = ld1.isAfter(ld2);
System.out.println(f2);

boolean f3 = ld1.isBefore(ld2);
System.out.println(f3);
}

LocalTime

代表本地时间:时、分、秒、纳秒

获取时间相关的信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) {
LocalTime now = LocalTime.now();
System.out.println(now);

// 获取时间相关的信息
int hour = now.getHour();// 小时
int minute = now.getMinute();// 分钟
int second = now.getSecond();// 秒
int nano = now.getNano();// 纳秒
System.out.println(hour);
System.out.println(minute);
System.out.println(second);
System.out.println(nano);
}

直接修改某个信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void main(String[] args) {
LocalTime now = LocalTime.now();
System.out.println(now);

// 直接修改某个信息
LocalTime lt1 = now.withHour(1);
System.out.println(lt1);

LocalTime lt2 = lt1.withMinute(1);
System.out.println(lt2);

LocalTime lt3 = lt2.withSecond(1);
System.out.println(lt3);

LocalTime lt4 = lt3.withNano(1);
System.out.println(lt4);
}

把某个信息增加多少

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  public static void main(String[] args) {
LocalTime now = LocalTime.now();
System.out.println(now);

// 把某个信息增加多少
LocalTime lt1 = now.plusHours(1);
System.out.println(lt1);

LocalTime lt2 = now.plusMinutes(20);
System.out.println(lt2);

LocalTime lt3 = now.plusSeconds(200);
System.out.println(lt3);

}

把某个信息减少多少

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args) {
LocalTime now = LocalTime.now();
System.out.println(now);

// 把某个信息减少多少
LocalTime lt1 = now.minusHours(1);
System.out.println(lt1);

LocalTime lt2 = now.minusMinutes(20);
System.out.println(lt2);

LocalTime lt3 = now.minusSeconds(200);
System.out.println(lt3);

}

获取指定时间的LocalTime对象

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) {
LocalTime lt1 = LocalTime.of(10, 10, 10);
System.out.println(lt1);

LocalTime lt2 = LocalTime.of(20, 20, 20);
System.out.println(lt2);

LocalTime lt3 = LocalTime.of(20, 20, 20);
System.out.println(lt3);
}

判断两个时间是否相等,在前还是在后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void main(String[] args) {
LocalTime lt1 = LocalTime.of(10, 10, 10);
System.out.println(lt1);

LocalTime lt2 = LocalTime.of(20, 20, 20);
System.out.println(lt2);

LocalTime lt3 = LocalTime.of(20, 20, 20);
System.out.println(lt3);

boolean f1 = lt2.equals(lt3);
System.out.println(f1);

boolean f2 = lt2.isAfter(lt1);
System.out.println(f2);

boolean f3 = lt2.isBefore(lt1);
System.out.println(f3);

}

LocalDateTime

代表本地日期、时间:年、月、日、星期、时、分、秒、纳秒

LocalDateTime大多数API与前面LocalDate,LocalTime一致

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
// LocalDateTime与LocalDate,LocalTime的相互转换
LocalDateTime now = LocalDateTime.now();

LocalDate ld = now.toLocalDate();
LocalTime lt = now.toLocalTime();
System.out.println(ld);
System.out.println(lt);

LocalDateTime ldt = LocalDateTime.of(ld, lt);
System.out.println(ldt);
}

ZoneId

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(String[] args) {
// 获取当前的时区
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId);

// 获取Java支持的全部时区
Set<String> set = ZoneId.getAvailableZoneIds();
System.out.println(set);

// 把某个时区ID封装成ZoneId对象
ZoneId zoneId1 = ZoneId.of("America/Los_Angeles");
System.out.println(zoneId1);

// 获取某个时区的ZoneDateTime对象
ZonedDateTime now = ZonedDateTime.now(zoneId1);
System.out.println(now);

// 获取系统默认时区的ZoneDateTime对象
ZonedDateTime systemNow = ZonedDateTime.now();
System.out.println(systemNow);
}

Instant 时间线上的某个时刻/时间戳

通过获取instant的对象可以拿到此刻的时间,该时间由两部分组成:从1970-01-01 00:00:00开始走到此刻的总秒数+不够1秒的纳秒数

img

1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String[] args) {
// 获取当前时间的Instant对象
Instant now = Instant.now();
System.out.println(now);

// 获取当前时间的从1970-1-1到现在的总秒数
long epochSecond = now.getEpochSecond();
System.out.println(epochSecond);

// 获取不到一秒的纳秒
int nano = now.getNano();
System.out.println(nano);
}

DateTimeFormatter

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) {
// 得到DateTimeFormatter对象
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

LocalDateTime now = LocalDateTime.now();
// 第一种写法
String rs = formatter.format(now);
System.out.println(rs);

// 第二种写法
String rs2 = now.format(formatter);
System.out.println(rs2);

// 解析时间字符串
String dateStr = "2024-11-23 10:10:10";
LocalDateTime date = LocalDateTime.parse(dateStr, formatter);
System.out.println(date);
}

Period

计算日期间隔

可以用于计算两个LocalDate对象相差的年数、月数、天数。

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) {
// 得到两个日期
LocalDate ld1 = LocalDate.of(2024, 1, 1);
LocalDate ld2 = LocalDate.of(2024, 6, 11);

// 得到Period对象
Period p = Period.between(ld1, ld2);

// 计算相隔几年
int years = p.getYears();
System.out.println(years);
// 计算相隔几月
int months = p.getMonths();
System.out.println(months);
// 计算相隔几日
int days = p.getDays();
System.out.println(days);
}

Duration

计算时间间隔

可以用于计算两个时间对象相差的天数、小时数、分数、秒数、纳秒数;支持LocalTime、LocalDateTime、Instant等时间

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public static void main(String[] args) {
// 得到两个LocalDateTime对象
LocalDateTime ldt1 = LocalDateTime.of(2024, 11, 12, 1, 2, 3);
LocalDateTime ldt2 = LocalDateTime.of(2024, 12, 1, 8, 12, 55);

// 得到Duration对象
Duration duration = Duration.between(ldt1, ldt2);

// 计算相隔多少天
long days = duration.toDays();
System.out.println(days);
// 计算相隔多少小时
long hours = duration.toHours();
System.out.println(hours);
// 计算相隔多少分
long minutes = duration.toMinutes();
System.out.println(minutes);
// 计算相隔多少秒
long seconds = duration.getSeconds();
System.out.println(seconds);
// 计算相隔多少毫秒
long millis = duration.toMillis();
System.out.println(millis);
// 计算相隔多少纳秒
long nanos = duration.toNanos();
System.out.println(nanos);
}

时间单位

ChronoUnit

JDK 8引入了java.time.temporal.ChronoUnit枚举类来表示时间单位,这个类定义了一组用于日期和时间计算的标准单位。这些单位可以用来加减时间、计算两个日期或时间之间的差异等。以下是ChronoUnit中一些常见的枚举值:

  • NANOS:表示纳秒(十亿分之一秒)。
  • MICROS:表示微秒(百万分之一秒)。
  • MILLIS:表示毫秒(千分之一秒)。
  • SECONDS:表示秒。
  • MINUTES:表示分钟。
  • HOURS:表示小时。
  • HALF_DAYS:表示半天(12小时)。
  • DAYS:表示天。
  • WEEKS:表示周。
  • MONTHS:表示月。
  • YEARS:表示年。
  • DECADES:表示十年。
  • CENTURIES:表示世纪。
  • MILLENNIA:表示千年。
  • ERAS:表示纪元。

TimeUnit

TimeUnit 是 Java 并发包 java.util.concurrent 中的一个枚举类,它提供了一种表示和操作时间单位的标准化方式。TimeUnit 枚举类中的每个实例都代表一种时间单位,如纳秒、微秒、毫秒、秒、分钟、小时和天等。这种设计不仅使代码更加清晰易读,还能够避免手动进行时间单位转换时可能出现的错误。

以下是 TimeUnit 中包含的一些常用的时间单位:

  • NANOSECONDS:纳秒
  • MICROSECONDS:微秒
  • MILLISECONDS:毫秒
  • SECONDS:秒
  • MINUTES:分钟
  • HOURS:小时
  • DAYS:天

TimeUnit 提供了一些非常有用的方法来处理时间值,包括但不限于:

  • ***\*convert(long sourceDuration, TimeUnit sourceUnit)\****:将指定的时间量从一个时间单位转换为当前时间单位。
  • ***\*toNanos(long duration)\****, ***\*toMicros(long duration)\****, ***\*toMillis(long duration)\****, ***\*toSeconds(long duration)\****, ***\*toMinutes(long duration)\****, ***\*toHours(long duration)\****, ***\*toDays(long duration)\****:将给定时间单位的数量转换为相应的时间单位值(例如,将小时数转换为秒数)。
  • ***\*sleep(long timeout)\****:让当前正在执行的线程停留(“睡眠”)指定的时间量。这是对 Thread.sleep 方法的一种更可读的替代方案。

使用 TimeUnit 可以让你的代码更加直观地表达时间的概念,并且减少了由于手工计算时间单位转换而导致的错误。例如,如果你想让一个线程休眠2秒钟,可以使用 TimeUnit.SECONDS.sleep(2); 这样的代码,这比直接使用 Thread.sleep(2000); 更加明确和易于理解。