Java 8系列Java日期时间的新主宰者:LocalDateLocalTimeLocalDateTimeZonedDateTime
Posted 善良勤劳勇敢而又聪明的老杨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 8系列Java日期时间的新主宰者:LocalDateLocalTimeLocalDateTimeZonedDateTime相关的知识,希望对你有一定的参考价值。
热门系列:
-
【Java 8系列】收集器Collector与工具类Collectors
-
【Java 8系列】Stream详解,看这一篇就够啦
-
【Java 8系列】Lambda 表达式,一看就废
-
【Java 8系列】Java开发者的判空利器 – Optional
-
程序人生,精彩抢先看
目录
2.1 LocalDate、LocalTime、LocalDateTime
1、前言
本系列一直在分享Java8的新增特性与API,今天和大家一起扒一扒Java的新时间类库:java.time;
之前我在往期博文:【Java编程系列】Java判断世界各时区的夏令时、冬令时 中就有提到过,为什么现在不适用Date时间类,而改用java.time库中的时间类。答案很简单:就是多线程安全性问题!
2、正文
本文主要分享和举例一些常用的类,下面正式开整!!本篇的时间类,都是使用的ISO-8601日历系统时间!
ISO-8601日历系统是当今世界上大多数地方使用的现代民用日历系统。它等效于多用的格里高利历系统,该系统在今天一直适用today年的规则。对于当今编写的大多数应用程序,ISO-8601规则完全适用。但是,任何利用历史日期并要求它们准确的应用程序都将发现ISO-8601方法不合适。
2.1 LocalDate、LocalTime、LocalDateTime
注:以上3个类,在使用和功能上基本一样,只是所代表的对象不同,所以放在一起讲解!
- LocalDate:是一个不可变的日期时间对象,代表一个日期,通常被视为年-月-日;此类是不可变的并且是线程安全的。
- LocalTime:是一个不可变的日期时间对象,代表一个时间,通常被视为时分秒。时间以纳秒精度表示;此类是不可变的并且是线程安全的。
- LocalDateTime:是一个不变的日期时间对象,代表一个日期时间,通常被视为年-月-日-时-分-秒。也可以访问其他日期和时间字段,例如,一年中的某天,一周中的某天和一周中的某周。时间以纳秒精度表示;此类是不可变的并且是线程安全的。
下面来看看常用的一些方法,三者取其一,咱们以LocalDateTime为例展开(举栗子一目了然,所以下面尽可能以代码形式讲解):
2.1.1 获取当前时间
public static void main(String[] args)
//获取当前时间
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("本地当前日期时间:"+localDateTime);
System.out.println();
//设置时区为美国纽约
System.out.println("美国当前日期时间:"+LocalDateTime.now(ZoneId.of("America/New_York")));
System.out.println();
输出:
本地当前日期时间:2020-12-28T15:25:20.707
美国当前日期时间:2020-12-28T02:25:20.708
2.1.2 获取当前时间毫秒数/时间戳
public static void main(String[] args)
//获取当前时间
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("本地当前日期时间:"+localDateTime);
long millisecond = localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
System.out.println("获取时间戳:"+millisecond/1000);
System.out.println("获取毫秒数:"+millisecond);
System.out.println();
输出:
本地当前日期时间:2020-12-28T16:43:32.971
获取时间戳:1609145012
获取毫秒数:1609145012971
2.1.3 获取年、月、日与星期几
public static void main(String[] args)
//获取当前时间
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("本地当前日期时间:"+localDateTime);
//获取年、月、日、星期几
int year = localDateTime.getYear();
System.out.println("获取年份(第一种方式):"+year);
year = localDateTime.get(ChronoField.YEAR);
System.out.println("获取年份(第二种方式):"+year);
System.out.println();
int month = localDateTime.getMonthValue();
System.out.println("获取月份(第一种方式):"+month);
month = localDateTime.getMonth().getValue();
System.out.println("获取月份(第二种方式):"+month);
month = localDateTime.get(ChronoField.MONTH_OF_YEAR);
System.out.println("获取月份(第三种方式):"+month);
System.out.println();
int dayOfWeek = localDateTime.getDayOfWeek().getValue();
System.out.println("获取星期几(第一种方式):"+dayOfWeek);
dayOfWeek = localDateTime.get(ChronoField.DAY_OF_WEEK);
System.out.println("获取星期几(第二种方式):"+dayOfWeek);
System.out.println();
int dayOfMonth = localDateTime.getDayOfMonth();
System.out.println("获取本月当日(第一种方式):"+dayOfMonth);
dayOfMonth = localDateTime.get(ChronoField.DAY_OF_MONTH);
System.out.println("获取本月当日(第二种方式):"+dayOfMonth);
System.out.println();
int dayOfYear = localDateTime.getDayOfYear();
System.out.println("获取本年当日(第一种方式):"+dayOfYear);
dayOfYear = localDateTime.get(ChronoField.DAY_OF_YEAR);
System.out.println("获取本年当日(第二种方式):"+dayOfYear);
输出:
本地当前日期时间:2020-12-29T10:32:49.698
获取年份(第一种方式):2020
获取年份(第二种方式):2020
获取月份(第一种方式):12
获取月份(第二种方式):12
获取月份(第三种方式):12
获取星期几(第一种方式):2
获取星期几(第二种方式):2
获取本月当日(第一种方式):29
获取本月当日(第二种方式):29
获取本年当日(第一种方式):364
获取本年当日(第二种方式):364
2.1.4 设置自定义时间
public static void main(String[] args)
//设置自定义时间
LocalDateTime tempTime = LocalDateTime.of(2020,11,28,15,00,01);
System.out.println("自定义设置的日期时间:"+tempTime);
System.out.println();
//设置自定义日期
LocalDate tempDate = LocalDate.of(2019,10,1);
System.out.println("自定义设置的日期:"+tempDate);
System.out.println();
输出:
自定义设置的日期时间:2020-11-28T15:00:01
自定义设置的日期:2019-10-01
2.1.5 日期/时间替换成指定的日期/时间
这里会用到一个方法,adjustInto():将指定的时间对象调整为具有与此对象相同的日期和时间
public static void main(String[] args)
//获取当前时间
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("本地当前日期时间:"+localDateTime);
System.out.println();
//设置自定义时间
LocalDateTime tempTime = LocalDateTime.of(2020,11,28,15,00,01);
System.out.println("自定义设置的日期时间:"+tempTime);
System.out.println();
// //设置自定义日期
LocalDate tempDate = LocalDate.of(2019,10,1);
System.out.println("自定义设置的日期:"+tempDate);
System.out.println();
//通过adjustInto方法实现日期转换
//将指定的时间对象调整为具有与此对象相同的日期和时间
localDateTime = (LocalDateTime)tempDate.adjustInto(localDateTime);
tempTime = (LocalDateTime)tempDate.adjustInto(tempTime);
System.out.println("转换后的localDateTime:"+localDateTime);
System.out.println("转换后的tempTime:"+tempTime);
System.out.println();
输出:
本地当前日期时间:2020-12-28T15:30:20.609
自定义设置的日期时间:2020-11-28T15:00:01
自定义设置的日期:2019-10-01
转换后的localDateTime:2019-10-01T15:30:20.609
转换后的tempTime:2019-10-01T15:00:01
2.1.6 日期时间与字符串相互转换
private static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
private static final String YYYYMMDD_HH_MM_SS = "yyyy/MM/dd HH:mm:ss";
public static void main(String[] args)
//获取当前时间
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("本地当前日期时间:"+localDateTime);
//日期与字符串相互转换
//日期转字符串
String dateTimeStr = localDateTime.format(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
System.out.println("日期时间格式化成字符串后:"+dateTimeStr);
//字符串转日期
String convertTime = "2020/12/12 12:12:12";
LocalDateTime convertLocalDateTime = LocalDateTime.parse(convertTime,DateTimeFormatter.ofPattern(YYYYMMDD_HH_MM_SS));
System.out.println("由字符串转换成的日期时间为:"+convertLocalDateTime);
输出:
本地当前日期时间:2020-12-29T10:43:45.295
日期时间格式化成字符串后:2020-12-29 10:43:45
由字符串转换成的日期时间为:2020-12-12T12:12:12
2.1.7 Date与LocalDateTime相互转换
private static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
private static final String YYYYMMDD_HH_MM_SS = "yyyy/MM/dd HH:mm:ss";
public static void main(String[] args)
//获取当前时间
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("本地当前日期时间:"+localDateTime);
//Date转换成LocalDateTime
Date date = new Date();
LocalDateTime date2LocalDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
System.out.println("Date转换成LocalDateTime后>>>>"+date2LocalDateTime);
//LocalDateTime转换成Date
Date localDateTime2Date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
System.out.println("LocalDateTime转换成Date后>>>>"+localDateTime2Date);
System.out.println("格式化一下>>>>"+FastDateFormat.getInstance(YYYY_MM_DD_HH_MM_SS).format(localDateTime2Date));
输出:
本地当前日期时间:2020-12-29T11:02:16.883
Date转换成LocalDateTime后>>>>2020-12-29T11:02:16.884
LocalDateTime转换成Date后>>>>Tue Dec 29 11:02:16 CST 2020
格式化一下>>>>2020-12-29 11:02:16
2.1.8 获取偏移日期时间
此处需要提一下,会常用的两个类似功能的方法:minus()和 plus(),其中还有一些类似的指定方法,如:
LocalDateTime | minus(long amountToSubtract, TemporalUnit unit) | 返回此日期时间的副本,减去指定的数量。 |
---|---|---|
LocalDateTime | minus(TemporalAmount amountToSubtract) | 返回此日期时间的副本,减去指定的数量。 |
LocalDateTime | minusDays(long days) |
返回此副本的副本,LocalDateTime 其中减去指定的天数。
|
LocalDateTime | minusHours(long hours) |
返回此副本的副本,LocalDateTime 其中减去指定的小时数。
|
LocalDateTime | minusMinutes(long minutes) |
返回此副本的副本,LocalDateTime 其中减去指定的分钟数。
|
LocalDateTime | minusMonths(long months) |
返回此副本的副本,LocalDateTime 其中减去指定的月数。
|
LocalDateTime | minusNanos(long nanos) |
返回此副本的副本,LocalDateTime 其中减去指定的纳秒数。
|
LocalDateTime | minusSeconds(long seconds) |
返回此副本的副本,LocalDateTime 其中减去指定的秒数。
|
LocalDateTime | minusWeeks(long weeks) |
返回此副本的副本,LocalDateTime 其中减去指定的周数。
|
LocalDateTime | minusYears(long years) |
返回此副本的副本,LocalDateTime 其中减去指定的年数。
|
LocalDateTime | plus(long amountToAdd, TemporalUnit unit) | 返回此日期时间的副本,其中添加了指定的数量。 |
---|---|---|
LocalDateTime | plus(TemporalAmount amountToAdd) | 返回此日期时间的副本,其中添加了指定的数量。 |
LocalDateTime | plusDays(long days) |
返回LocalDateTime 带有指定天数的副本。
|
LocalDateTime | plusHours(long hours) |
返回LocalDateTime 带有指定小时数的副本。
|
LocalDateTime | plusMinutes(long minutes) |
返回LocalDateTime 带有指定分钟数的副本。
|
LocalDateTime | plusMonths(long months) |
返回LocalDateTime 带有指定月份数的副本。
|
LocalDateTime | plusNanos(long nanos) |
返回此副本的副本,LocalDateTime 其中添加了指定的纳秒数。
|
LocalDateTime | plusSeconds(long seconds) |
返回此副本的副本,LocalDateTime 其中添加了指定的秒数。
|
LocalDateTime | plusWeeks(long weeks) |
返回此副本的副本,LocalDateTime 其中添加了指定的周数。
|
LocalDateTime | plusYears(long years) |
返回LocalDateTime 带有指定年限的副本。
|
下面列举几个常用栗子:
public static void main(String[] args)
//获取当前时间
LocalDateTime localDateTime = LocalDateTime.now(ZoneId.systemDefault());
System.out.println("本地当前日期时间:"+localDateTime);
//获取偏移时间
//偏移天(正数:往后偏移;负数:往过去时间偏移)
System.out.println("明日此时:"+localDateTime.plusDays(1));
System.out.println("明日此时1:"+localDateTime.minusDays(-1));
System.out.println("前天此时:"+localDateTime.plusDays(-2));
//偏移时
System.out.println("当前时间后2个小时:"+localDateTime.plusHours(2));
System.out.println("当前时间前5个小时:"+localDateTime.plusHours(-5));
//偏移年
System.out.println("去年此时:"+localDateTime.plusYears(-1));
//偏移月
System.out.println("下月此时:"+localDateTime.plusMonths(1));
//偏移周
System.out.println("上周此时:"+localDateTime.plusWeeks(-1));
输出:
本地当前日期时间:2020-12-29T11:22:24.914
明日此时:2020-12-30T11:22:24.914
明日此时1:2020-12-30T11:22:24.914
前天此时:2020-12-27T11:22:24.914
当前时间后2个小时:2020-12-29T13:22:24.914
当前时间前5个小时:2020-12-29T06:22:24.914
去年此时:2019-12-29T11:22:24.914
下月此时:2021-01-29T11:22:24.914
上周此时:2020-12-22T11:22:24.914
2.2 ZonedDateTime
ZonedDateTime其实就是含有时区的LocalDateTime,其实就是LocalDateTime+ZoneId,其对照关系可以如图:
所以,其对应的功能基本与上述一致,因此不再赘述!
2.3 ZoneId
ZoneId是时区ID类,主要包含了各时区信息!一般对时区没有要求的情况,我们会使用:
ZoneId.systemDefault()
来设置默认时区!
通过源代码查看,目前常用的时区映射关系有如下这些:
public static final Map<String, String> SHORT_IDS;
/**
* 当前为ZoneId源码,除了
* 以下中文注释为作者个人翻译而来,非源码注释
**/
static
Map<String, String> map = new HashMap<>(64);
//"Australia/Darwin","澳洲/达尔文"
map.put("ACT", "Australia/Darwin");
//"Australia/Sydney","澳洲/悉尼"
map.put("AET", "Australia/Sydney");
//"America/Argentina/Buenos_Aires","美洲/阿根廷/布宜诺斯艾利斯"
map.put("AGT", "America/Argentina/Buenos_Aires");
//"Africa/Cairo","非洲/开罗"
map.put("ART", "Africa/Cairo");
//"America/Anchorage","美洲/安克雷奇"
map.put("AST", "America/Anchorage");
//"America/Sao_Paulo","美洲/圣保罗"
map.put("BET", "America/Sao_Paulo");
//"Asia/Dhaka","亚洲/达卡"
map.put("BST", "Asia/Dhaka");
//"Africa/Harare","非洲/哈拉雷"
map.put("CAT", "Africa/Harare");
//"America/St_Johns","美洲/圣约翰"
map.put("CNT", "America/St_Johns");
//"America/Chicago","美洲/芝加哥"
map.put("CST", "America/Chicago");
//"Asia/Shanghai","亚洲/上海"
map.put("CTT", "Asia/Shanghai");
//"Africa/Addis_Ababa","非洲/亚的斯亚贝巴"
map.put("EAT", "Africa/Addis_Ababa");
//"Europe/Paris","欧洲/巴黎"
map.put("ECT", "Europe/Paris");
//"America/Indiana/Indianapolis","美洲/印第安纳州/印第安纳波利斯"
map.put("IET", "America/Indiana/Indianapolis");
//"Asia/Kolkata","亚洲/加尔各答"
map.put("IST", "Asia/Kolkata");
//"Asia/Tokyo","亚洲/东京"
map.put("JST", "Asia/Tokyo");
//"Pacific/Apia","太平洋/阿皮亚"
map.put("MIT", "Pacific/Apia");
//"Asia/Yerevan","亚洲/埃里温"
map.put("NET", "Asia/Yerevan");
//"Pacific/Auckland","太平洋/奥克兰"
map.put("NST", "Pacific/Auckland");
//"Asia/Karachi","亚洲/卡拉奇"
map.put("PLT", "Asia/Karachi");
//"America/Phoenix","美洲/凤凰城"
map.put("PNT", "America/Phoenix");
//"America/Puerto_Rico","美洲/波多黎各"
map.put("PRT", "America/Puerto_Rico");
//"America/Los_Angeles","美洲/洛杉矶"
map.put("PST", "America/Los_Angeles");
//"Pacific/Guadalcanal","太平洋/瓜达尔卡纳尔岛"
map.put("SST", "Pacific/Guadalcanal");
//"Asia/Ho_Chi_Minh","亚洲/胡志明市"
map.put("VST", "Asia/Ho_Chi_Minh");
//"-05:00","东部标准时间"(纽约、华盛顿)
map.put("EST", "-05:00");
//"-07:00","山地标准时间"
map.put("MST", "-07:00");
//"-10:00","夏威夷-阿留申标准时区"
map.put("HST", "-10:00");
SHORT_IDS = Collections.unmodifiableMap(map);
举个栗子:
System.out.println("美国纽约当前日期时间:"+LocalDateTime.now(ZoneId.of("America/New_York")));
//输出:
美国纽约当前日期时间:2020-12-29T04:10:53.257
2.4 Instant
Instant类,是包含时间线上的某一个瞬时点。
举个栗子:
public static void main(String[] args)
//获取当前时间
LocalDateTime localDateTime = LocalDateTime.now(ZoneId.systemDefault());
System.out.println("本地当前日期时间戳:"+localDateTime.atZone(ZoneId.systemDefault()).toEpochSecond());
System.out.println();
Instant instant = Instant.from(localDateTime.atZone(ZoneId.systemDefault()).plusHours(-1));
System.out.println("前一小时此时的时间戳:"+instant.getEpochSecond());
System.out.println("前一小时此时的毫秒数:"+instant.toEpochMilli());
输出:
本地当前日期时间戳:1609235707
//刚好相差3600秒
前一小时此时的时间戳:1609232107
前一小时此时的毫秒数:1609232107078
2.5 时间工具类
/**
* Date工具类
* @author Yangy
*/
public class DateUtils
private static final ZoneId ZONE_ID = ZoneId.systemDefault();
/**
* LocalDateTime转化为Date
*
* @param localDateTime
* @return
*/
public static Date toDate(LocalDateTime localDateTime)
return Date.from(localDateTime.atZone(ZONE_ID).toInstant());
/**
* LocalDateTime转化为Date
*
* @param localDateTime
* @return
*/
public static Date toDate(LocalDate localDate)
return Date.from(localDate.atStartOfDay(ZONE_ID).toInstant());
/**
* Date转化为LocalDateTime
*
* @param date
* @return
*/
public static LocalDateTime toLocalDateTime(Date date)
return LocalDateTime.ofInstant(date.toInstant(), ZONE_ID);
/**
* LocalDate转化为LocalDateTime
*
* @param localDate
* @return
*/
public static LocalDateTime toLocalDateTime(LocalDate localDate)
return LocalDateTime.of(localDate, LocalTime.MIN);
/**
* Date转化为LocalDate
*
* @param date
* @return
*/
public static LocalDate toLocalDate(Date date)
return date.toInstant().atZone(ZONE_ID).toLocalDate();
/**
* Date转化为字符串
*
* @param date
* @param formatter
* @return
*/
public static String format(Date date, DateFormatter formatter)
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZONE_ID);
return formatter.getDateTimeFormatter().format(localDateTime);
/**
* 字符串转化为Date
*
* @param text
* @param formatter
* @return
*/
public static Date parse(String text, DateFormatter formatter)
return formatter.parse(text);
public static enum DateFormatter
/**
* 格式yyyy
*
*/
YEAR_FORMATTER(DateTimeFormatter.ofPattern("yyyy", Locale.CHINA))
@Override
public Date parse(String text)
Year year = Year.parse(text, dateTimeFormatter);
return Date.from(year.atDay(1).atStartOfDay(ZONE_ID).toInstant());
,
/**
*
* 格式yyyy-MM
*
*/
YEAR_MONTH_FORMATTER(DateTimeFormatter.ofPattern("yyyy-MM", Locale.CHINA))
@Override
public Date parse(String text)
YearMonth yearMonth = YearMonth.parse(text, dateTimeFormatter);
return Date.from(yearMonth.atDay(1).atStartOfDay(ZONE_ID).toInstant());
,
/**
*
* 格式yyyy-MM-dd
*
* @author Val Song Dec 17, 2017 7:26:25 PM
*
*/
DATE_FORMATTER(DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.CHINA))
@Override
public Date parse(String text)
LocalDate localDate = LocalDate.parse(text, dateTimeFormatter);
return Date.from(localDate.atStartOfDay(ZONE_ID).toInstant());
,
/**
* 格式yyyy-MM-dd HH:mm:ss
*
*/
DATE_TIME_FORMATTER(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.CHINA))
@Override
public Date parse(String text)
LocalDateTime localDateTime = LocalDateTime.parse(text, dateTimeFormatter);
return Date.from(localDateTime.atZone(ZONE_ID).toInstant());
,
/**
* 格式yyyyMMdd_HHmmss
*
*/
YYYYMMDD_HHMMSS_FORMATTER(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss", Locale.CHINA))
@Override
public Date parse(String text)
LocalDateTime localDateTime = LocalDateTime.parse(text, dateTimeFormatter);
return Date.from(localDateTime.atZone(ZONE_ID).toInstant());
;
protected DateTimeFormatter dateTimeFormatter;
private DateFormatter(DateTimeFormatter dateTimeFormatter)
this.dateTimeFormatter = dateTimeFormatter;
public DateTimeFormatter getDateTimeFormatter()
return dateTimeFormatter;
public abstract Date parse(String text);
3、总结
1.切记,LocalDate、LocalTime、LocalDateTime这几个类,都是没有设置时区的日期时间类,所以,对时区有要求的时候,必须手动设置指定时区;否则,采用默认时区即可!
2.除了国内,世界其他很多地区都有夏冬令时的区分!所以,业务针对时区和夏冬令时有区别的,需要注意这一点!
最后,希望此文如果对你有帮助的话,请点赞、留言、关注我吧!
扫描左侧二维码,即可查看作者公众号内的更多精彩内容,先感谢各位朋友的支持啦!!!
以上是关于Java 8系列Java日期时间的新主宰者:LocalDateLocalTimeLocalDateTimeZonedDateTime的主要内容,如果未能解决你的问题,请参考以下文章
Java 8系列收集器Collector与工具类Collectors
Java 8系列Java开发者的判空利器 -- Optional
Java 8系列全网最通俗易懂的Java8版本新特性知识汇总,看完不懂你捶我
Java 8系列全网最通俗易懂的Java8版本新特性知识汇总,看完不懂你捶我
Java日期时间API系列8-----Jdk8中java.time包中的新的日期时间API类的LocalDate源码分析