java在处理时间的时候有很多方式,早期的SimpleDateFormat、Date、Calendar,以及后来的DateTimeFormatter、LocalDateTime等等,但是由于SimpleDateFormat存在线程不安全的问题,因此推荐使用DateTimeFormatter、LocalDateTime来处理时间,在这里对一些常用的方法做一个整理。
时间样式标识| 标识 | 含义 |
|---|---|
| Z | 时区,如:+0800 |
| yyyy | 我们一般所指的年份 |
| YYYY | Week year,当天所在的周属于的年份 |
| MM | 月 |
| dd | 日 |
| HH | 24小时制的小时,如果只有H则不补0 |
| hh | 12小时制的小时 |
| mm | 分钟,如果只有m则不补0 |
| ss | 秒,如果只有s则不补0 |
// 系统当前时区
ZoneId.systemDefault();
// 指定时区
ZoneId.of("Asia/Shanghai");
ZoneId.of("Europe/Zurich");
// 获取所有时区
ZoneId.getAvailableZoneIds();
// 获取指定时区
ZoneId.ofOffset("UTC", ZoneOffset.ofHours(8));
ZoneId.ofOffset("GMT", ZoneOffset.ofHours(8));
ZoneId.ofOffset("UTC", ZoneOffset.of("+0830"));
Instant时间点
// 获取某个时刻 Instant.now(); Instant.ofEpochSecond(1646739326); Instant.ofEpochMilli(1646739326986L); // 获取时间戳 // 秒级 long epochSecond = Instant.now().getEpochSecond(); // 毫秒级 long epochMilli = Instant.now().toEpochMilli(); long currentTimeMillis = System.currentTimeMillis(); // 转换为LocalDateTime Instant.now().atOffset(ZoneOffset.ofHours(8)).toLocalDateTime(); // 转换为Date Date.from(Instant.now()); // 从Date获取 Date date = new Date(); date.toInstant();
未找到Instant.now().toEpochMilli()和System.currentTimeMillis()之间的明显差异,因此根据个人习惯来选择就好。
LocalDateTime// 当前时间
LocalDateTime.now();
LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
// 声明一个时间
LocalDateTime.of(2022, 2, 28, 23, 50);
LocalDateTime.ofInstant(Instant.ofEpochSecond(1646739326), ZoneId.systemDefault());
LocalDateTime.ofEpochSecond(1646739326, 0, ZoneOffset.ofHours(8));
// 根据字符串获取时间
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime.parse("2022-05-23 14:35:56", formatter);
// 根据时间获取指定格式字符串
LocalDateTime tmpDateTime = LocalDateTime.now();
String timeStr = tmpDateTime.format(formatter);
// 获取年月日等
tmpDateTime.getYear();
tmpDateTime.getMonthValue();
tmpDateTime.getDayOfMonth();
tmpDateTime.getDayOfWeek();
tmpDateTime.getHour();
tmpDateTime.getMinute();
// 获取时间戳
tmpDateTime.toEpochSecond(ZoneOffset.ofHours(8));
// 转换为LocalDate、LocalTime、Instant
LocalDate tmpDate = tmpDateTime.toLocalDate();
LocalTime tmpTime = tmpDateTime.toLocalTime();
Instant tmpInstant = tmpDateTime.toInstant(ZoneOffset.ofHours(8));
// 比较日期
tmpDateTime.isAfter(LocalDateTime.now());
tmpDateTime.isBefore(LocalDateTime.now());
tmpDateTime.isEqual(LocalDateTime.now());
// 获取两个日期间的时间跨度
long dayGap = ChronoUnit.DAYS.between(LocalDateTime.now(), tmpDateTime);
long hourGap = ChronoUnit.HOURS.between(LocalDateTime.now(), tmpDateTime);
// 根据日期生成新的LocalDateTime
tmpDateTime.withYear(1999);
tmpDateTime.withDayOfMonth(30);
tmpDateTime.withHour(14);
tmpDateTime.withMinute(50);
// 减
tmpDateTime.minusDays(100);
tmpDateTime.minusHours(4);
// 加
tmpDateTime.plusDays(180);
tmpDateTime.plusHours(5);
// 截取到某个粒度
tmpDateTime.truncatedTo(ChronoUnit.HOURS);
tmpDateTime.truncatedTo(ChronoUnit.DAYS);
// 如果想获取一周的第一个时刻,下面这个用法是错误的
// tmpDateTime.truncatedTo(ChronoUnit.WEEKS);
// 正确的做法(下面的几种方法都行):
tmpDateTime.minusDays(tmpDateTime.getDayOfWeek().getValue() - DayOfWeek.MONDAY.getValue()).truncatedTo(ChronoUnit.DAYS);
TemporalAdjuster firstOfWeek = TemporalAdjusters.ofDateAdjuster(localDate -> localDate.minusDays(localDate.getDayOfWeek().getValue() - DayOfWeek.MONDAY.getValue()));
tmpDateTime.with(firstOfWeek).truncatedTo(ChronoUnit.DAYS);
tmpDateTime.toLocalDate().with(firstOfWeek).atStartOfDay();
// 注意上面使用的with(TemporalAdjuster)方法只会调整日期,不会调整时间
// 2022-03-08 22:08:56 => 2022-03-01 22:08:56
tmpDateTime.with(TemporalAdjusters.firstDayOfMonth());
LocalDate和LocalTime
LocalDate和LocalTime的使用和上面的LocalDateTime大体相同,这里列出一些前面没有出现的方法
// 获取那一天的00:00 tmpDate.atStartOfDay(); LocalDateTime.of(tmpDate, LocalTime.MIN); // 获取那一天的23:59 LocalDateTime.of(tmpDate, LocalTime.MAX); // 转换为LocalDateTime tmpDate.atTime(tmpTime); tmpDate.atTime(10, 59); // 是否是闰年 tmpDate.isLeapYear(); // 获取当月/当年有多长 tmpDate.lengthOfMonth(); tmpDate.lengthOfYear(); // 转换为LocalDateTime tmpTime.atDate(tmpDate);



