本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Java.time常见使用
小知识
- LocalDateTime:
java.time.LocalDateTime类表示ISO-8601日历系统中没有时区的日期时间,例如2007-12-03T10:15:30。表示与时区无关的日期和时间信息,不直接对应时刻,需要通过时区转换. - Instant:
java.time.Instant类在时间线上模拟单个瞬时点。不直接对应年月日信息,需要通过时区转换. - LocalDate:
java.time.LocalDate类表示ISO-8601日历系统中没有时区的日期,例如:2007-12-03表示与时区无关的日期,与LocalDateTime相比,只有日期信息,没有时间信息. - LocalTime:
java.time.LocalTime类表示ISO-8601日历系统中没有时区的时间,例如10:15:30表示与时区无关的时间,与LocalDateTime相比,只有时间信息,没有日期信息. - ZonedDateTime:
java.time.ZonedDateTime类表示ISO-8601日历系统中具有时区的日期时间,例如:2007-12-03T10:15:30+01:00 Europe/Paris.表示特定时区的日期和时间. - ZoneId/ZoneOffset:时区.
LocalDate
LocalDate todayDate = LocalDate.now();
System.out.println("获取今天的日期:" + todayDate);//====> 获取今天的日期:2021-04-19
LocalDate targetDay = LocalDate.of(2099, 12, 12);
System.out.println("获取指定的日期:" + targetDay);//====> 获取指定的日期:2099-12-12
System.out.println("格式化:" + targetDay.format(DateTimeFormatter.BASIC_ISO_DATE));
LocalDate feb = LocalDate.of(2099, 8, 12);
//withXxx()表示以该日期为基础,修改年、月、日字段,并返回一个新的日期
System.out.println(feb.withYear(2019));
System.out.println(feb.withDayOfYear(10));
System.out.println(feb.withDayOfMonth(10));
LocalDate stringDate = LocalDate.parse("20990202",DateTimeFormatter.BASIC_ISO_DATE);
System.out.println("从标准格式的字符串获取日期:" + stringDate);//====> 从标准格式的字符串获取日期:2099-02-02
System.err.println("不是标准的格式就会报错:" + LocalDate.parse("2099-2-2"));//====> Exception in thread "main" java.time.format.DateTimeParseException: Text '2099-2-2' could not be parsed at index 5
Period until = LocalDate.of(2021, 4, 22).until(LocalDate.of(2022, 8, 15));
System.out.println(until);
System.out.println(until.get(ChronoUnit.YEARS));
System.out.println(until.get(ChronoUnit.MONTHS));
System.out.println(until.get(ChronoUnit.DAYS));
//TemporalAdjusters调节器是用于修改时间对象的关键工具,包含很多常用调整方法
LocalDate firstDayOfThisMonth = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
System.out.println("获取当前月份的第一天:" + firstDayOfThisMonth);//====> 获取当前月份的第一天:2021-04-01
LocalDate secondDayOfThisMonth = LocalDate.now().withDayOfMonth(2);
System.out.println("获取当前月份的第二天:" + secondDayOfThisMonth);//====> 获取当前月份的第二天:2021-04-02
LocalDate lastDayOfThisMonth = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
System.out.println("获取当前月份的最后一天(不需要管该月有几天):" + lastDayOfThisMonth);//====> 获取当前月份的最后一天(不需要管该月有几天):2021-04-30
LocalDate afterLastDayOfThisMonth = lastDayOfThisMonth.plusDays(1);
System.out.println("获取当前月份最后一天的下一天:" + afterLastDayOfThisMonth);//====> 获取当前月份最后一天的下一天:2021-05-01
LocalDate firstMondayOf2099 = LocalDate.parse("2099-12-12").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
System.out.println("获取2099年的第一个月的第一个星期一:" + firstMondayOf2099);//====> 获取2099面的第一个月的第一个星期一:2099-12-07
boolean isLeapYear = LocalDate.now().isLeapYear();
System.out.println("判断是闰年吗:"+ isLeapYear);//====> 判断是闰年吗:false
LocalTime
LocalTime now = LocalTime.now();
System.out.println("获取当前时间,它是包含毫秒的:" + now);//====> 获取当前时间,它是包含毫秒的:20:05:33.116
LocalTime nowWithoutNano = LocalTime.now().withNano(0);
System.out.println("一般情况不需要毫秒:" + nowWithoutNano);//====> 一般情况不需要毫秒:20:05:33
LocalTime customTime = LocalTime.of(05, 20, 0);
System.out.println("创建一个时间:" + customTime); //====>创建一个时间:05:20
LocalTime praseTime = LocalTime.parse("05:20:00");
System.out.println("按照标准格式创建一个时间:" + praseTime);//====>按照标准格式创建一个时间:05:20
System.out.println("要按照标准格式来,不然报错。时间和日期不同,它有三种格式:1. " + LocalTime.parse("05:20")
+ " 2. " + LocalTime.parse("05:20:20") + " 3. " + LocalTime.parse("05:20:20.123"));
//====>要按照标准格式来,不然报错。时间和日期不同,它有三种格式:1. 05:20 2. 05:20:20 3. 05:20:20.123
//当前时间增加2小时的两种写法,其他类似
LocalTime nowTimePlus2Hour = LocalTime.now().plusHours(2);
LocalTime nowTimePlus2Hour2 = LocalTime.now().plus(2, ChronoUnit.HOURS);
System.out.println("时间增加2小时:" + nowTimePlus2Hour + " 《====》 " + nowTimePlus2Hour2);
System.out.println(LocalTime.now().compareTo(LocalTime.now().plusHours(10)));
//====>时间增加2小时:22:21:38.995 《====》 22:21:38.995
LocalDateTime
LocalDateTime localDateTime = LocalDateTime.now();
LocalDateTime plusYearsResult = localDateTime.plusYears(2L);
LocalDateTime plusMonthsResult = localDateTime.plusMonths(3L);
LocalDateTime plusDaysResult = localDateTime.plusDays(7L);
LocalDateTime plusHoursResult = localDateTime.plusHours(2L);
LocalDateTime plusMinutesResult = localDateTime.plusMinutes(10L);
LocalDateTime plusSecondsResult = localDateTime.plusSeconds(10L);
System.out.println("当前时间是 : " + localDateTime + "\n"
+ "当前时间加2年后为 : " + plusYearsResult + "\n"
+ "当前时间加3个月后为 : " + plusMonthsResult + "\n"
+ "当前时间加7日后为 : " + plusDaysResult + "\n"
+ "当前时间加2小时后为 : " + plusHoursResult + "\n"
+ "当前时间加10分钟后为 : " + plusMinutesResult + "\n"
+ "当前时间加10秒后为 : " + plusSecondsResult + "\n"
);
//也可以以另一种方式来相加减日期,即plus(long amountToAdd, TemporalUnit unit)
// 参数1 : 相加的数量, 参数2 : 相加的单位
LocalDateTime nextMonth = localDateTime.plus(1, ChronoUnit.MONTHS);
LocalDateTime nextYear = localDateTime.plus(1, ChronoUnit.YEARS);
LocalDateTime nextWeek = localDateTime.plus(1, ChronoUnit.WEEKS);
System.out.println("now : " + localDateTime + "\n"
+ "nextYear : " + nextYear + "\n"
+ "nextMonth : " + nextMonth + "\n"
+ "nextWeek :" + nextWeek + "\n"
);
// Duration.between()方法创建 Duration 对象
LocalDateTime from = LocalDateTime.of(2017, Month.JANUARY, 1, 00, 0, 0); // 2017-01-01 00:00:00
LocalDateTime to = LocalDateTime.of(2019, Month.SEPTEMBER, 12, 14, 28, 0); // 2019-09-15 14:28:00
Duration duration = Duration.between(from, to); // 表示从 from 到 to 这段时间
long days = duration.toDays(); // 这段时间的总天数
long hours = duration.toHours(); // 这段时间的小时数
long minutes = duration.toMinutes(); // 这段时间的分钟数
long seconds = duration.getSeconds(); // 这段时间的秒数
long milliSeconds = duration.toMillis(); // 这段时间的毫秒数
long nanoSeconds = duration.toNanos(); // 这段时间的纳秒数
System.out.println(LocalDateTime.of(2021, Month.DECEMBER, 8, 10, 59, 59));
System.out.println(to);
System.out.println(days);
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
String date2Str = dateTimeFormatter.format(LocalDateTime.now());
System.out.println(date2Str);
//新的格式化API中,格式化后的结果都默认是String,有时我们也需要返回经过格式化的同类型对象
DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String temp = dtf1.format(LocalDateTime.now());
LocalDateTime formatedDateTime = LocalDateTime.parse(temp, dtf1);
System.out.println(formatedDateTime);
System.out.println("---------long毫秒值转换为日期---------");
DateTimeFormatter df= DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
long timeMillis = System.currentTimeMillis();
System.out.println(timeMillis);
Instant instant = Instant.ofEpochMilli(timeMillis);
System.out.println(instant);
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.of("Asia/Shanghai"));
System.out.println(localDateTime);
String longToDateTime = df.format(localDateTime);
System.out.println(longToDateTime);
Instant start = Instant.now().plusMillis(TimeUnit.HOURS.toMillis(8));
System.out.println(start);
ZonedDateTime
//获得所有可用的时区
Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
System.out.println(availableZoneIds.size());
//获取默认ZoneId对象
ZoneId defZoneId = ZoneId.systemDefault();
System.out.println(defZoneId);
//获取指定时区的ZoneId对象
ZoneId shanghaiZoneId = ZoneId.of("Asia/Shanghai");
System.out.println(shanghaiZoneId);
//下面可以得到字符串 Asia/Shanghai
String shanghai = ZoneId.SHORT_IDS.get("CTT");
System.out.println(shanghai);
//ZoneId.SHORT_IDS返回一个Map<String, String> 是时区的简称与全称的映射。
Map<String, String> map = ZoneId.SHORT_IDS;
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey()+"===="+entry.getValue());
}
//2017-01-20T17:35:20.885+08:00[Asia/Shanghai]
ZonedDateTime.now();
//2017-01-01T12:00+08:00[Asia/Shanghai]
ZonedDateTime.of(2017, 1, 1, 12, 0, 0, 0, ZoneId.of("Asia/Shanghai"));
//使用一个准确的时间点来创建ZonedDateTime,下面这个代码会得到当前的UTC时间,会比北京时间早8个小时
System.out.println(ZonedDateTime.ofInstant(Instant.now(), ZoneId.of("UTC")));
//atZone方法可以将LocalDateTime转换为ZonedDateTime,下面的方法将时区设置为UTC。
//假设现在的LocalDateTime是2017-01-20 17:55:00 转换后的时间为2017-01-20 17:55:00[UTC]
ZonedDateTime zonedDateTimeUTC = LocalDateTime.now().atZone(ZoneId.of("UTC"));
System.out.println(zonedDateTimeUTC);
//使用静态of方法创建zonedDateTime
ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("UTC"));
ZonedDateTime zonedDateTime = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("Asia/Shanghai"));
System.out.println(zonedDateTime);
//withZoneSameLocal返回指定时区中的一个新ZonedDateTime,替换时区为指定时区,
//表示相同的本地时间的该时区 时间。(时间不变,只改变时区)
System.out.println(zonedDateTime.withZoneSameLocal(ZoneId.of("UTC")));
//withZoneSameInstant返回指定时区中的一个新ZonedDateTime,替换为指定时区,
//表示相同时间点的该时区时间。(时间会会根据时区+/-)
System.out.println(zonedDateTime.withZoneSameInstant(ZoneId.of("UTC")));
Clock
// Java 8增加了一个Clock时钟类用于获取当时的时间戳,或当前时区下的日期时间信息。
// 以前用到System.currentTimeInMillis()和
// TimeZone.getDefault()的地方都可用Clock替换。
//根据系统时钟返回当前时间并设置为UTC。
Clock clock = Clock.systemUTC();
System.out.println("Clock : " + clock.millis());
// 根据系统时钟区域返回时间
Clock defaultClock = Clock.systemDefaultZone();
System.out.println("Clock : " + defaultClock.millis());
时区转换的一个栗子
//栗子 https://zhuanlan.zhihu.com/p/65128406
//首先使用ZonedDateTime+DateTimeFormatter将获取到的时间转换为带时区的时间对象;
// 需要注意的是字符T属于时间格式化中的模式字母,
// 如果想把它作为普通字符看待的话需要加'' -> "yyyy-MM-dd'T'HH:mm:ssZ"
//然后使用ZonedDateTime的withZoneSameInstant()方法,
// 进行时间的转换,转换后时间会根据时区之间的时差自动转换。
String dateTimeStr1 = "2021-05-05T22:48:52+0800";
String dateTimeStr2 = "2021-05-05T22:48:52+0700";
// String -> ZoneDateTime
ZonedDateTime zonedDateTime1 =
ZonedDateTime.parse(dateTimeStr1, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ"));
System.out.println(zonedDateTime1);
ZonedDateTime zonedDateTime2 =
ZonedDateTime.parse(dateTimeStr2, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ"));
System.out.println(zonedDateTime2);
// 1. ZoneDateTime(+0800) -> ZoneDateTime(-0800) 时间会会根据时区+/-
ZonedDateTime losAngelesZonedDateTime1 =
zonedDateTime1.withZoneSameInstant(ZoneId.of("America/Los_Angeles"));
System.out.println(losAngelesZonedDateTime1);
ZonedDateTime losAngelesZonedDateTime2 =
zonedDateTime2.withZoneSameInstant(ZoneId.of("America/Los_Angeles"));
System.out.println(losAngelesZonedDateTime2);
// 2. ZoneDateTime(+0800) -> ZoneDateTime(-0800) 时间不变,只改变时区
ZonedDateTime result = zonedDateTime1.withZoneSameLocal(ZoneId.of("Asia/Shanghai"));
System.out.println(result);