前言
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时区
// 系统当前时区
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);
注意:
LocalDateTime tmpDateTime = LocalDateTime.parse("20220316", DateTimeFormatter.ofPattern("yyyyMMdd"));
如果只是转换日期格式,那么不要使用LocalDateTime
,而是使用LocalDate
,上述代码会抛出异常
Text '20220316' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {},ISO resolved to 2022-03-16 of type java.time.format.Parsed