文章目录
- 1.为什么需要引入新的日期和时间?
- 2.新的日期和时间API设计原则
- 3.Java8中的日期和时间API包含的包
- 4.常用类以及方法
- 4.1LocalDate
- 4.1.1常用API
- 4.1.2案例展示
- 4.1.3拓展使用
- 4.2LocalTime
- 4.3LocalDateTime
- 4.3.1常用API
- 4.3.2案例展示
- 4.3.3拓展使用
- 4.4Instant
- 4.4.1常用API
- 4.4.2概念关系
- 4.5Period
- 4.5.1常用API
- 4.5.2案例使用
- 4.6Duration
- 4.6.1常用API
- 4.6.2案例展示
- 4.7DateTimeFormatter
- 4.7.1常用API
- 4.7.2案例展示
- 4.8ZoneId和ZonedDateTime
1.为什么需要引入新的日期和时间?
- Date如果不格式化,打印出的日期可读性差
Date date = new Date();
Wed May 13 16:06:28 CST 2020
LocalDate localDate = LocalDate.now();
2020-05-13
- Java8之前所有的日期类都是可变的, 这就导致了线程不安全
- Java的日期和时间类的定义不一致,在java.util和java.sql中都包含日期类
- java.util.Date同时包含日期和时间,但是java.sql中只包含日期,将其纳入java.sql中是不合适的,而且最糟糕的是:着两个类中的日期类的名字都是一样的
- 对于时间、时间戳、格式化及解析,没有一些明确定义的类, 而且对于格式化和解析的需求,Java中有java.text.DateFormat抽象类,但是通常我们用的是SimpleDateFormat
- 日期不支持国际化,没有时区支持,即使Java引入java.util.Calendar和java.uril.TimeZone类,但是问题依然存在
- 使用SimpleDateFormat对时间进行格式化, 但SimpleDateFormat是线程不安全的:
- format方法中的calendar是共享变量,并且这个共享变量没有做线程安全控制,当多个线程同时使用相同的SimpleDateFormat对象进行格式化的时候,多个线程会同时调用calendar.setTime方法,可能一个线程刚设置好time值,另外一个线程马上把设置的time值修改了导致返回的格式化时间可能是错误的
- SimpleDateFormat除了format是线程不安全以外,parse方法也是线程不安全的。parse方法实际调用alb.establish(calendat).getTime()方法来解析,alb.establish(calendar).getTime()方法来解析,alb.establish(calendar)方法里主要完成了:
- 填充日期对象cal的属性值
- 使用calb中属性设置cal
- 返回设置好的cal对象,但是这三步不是原子操作
- `Date和Calendar都是可变的.能把2014年3月18日修改成4月18日意味着什么呢?这种设计会被拖入维护的噩梦
2.新的日期和时间API设计原则
- 不变性:新的日期/时间API中,所有的类都是不可变的,实现了线程安全;
- 关注点分离:新的API中将人可读的日期时间和机器时间(unix timestamp)明确分离,它为日期(Date)、时间(Time)、日期时间(DateTime)、时间戳(unix timestamp)以及时区定义了不同的类
- 清晰明了:新的API中,方法都被
明确定义
用以完成相同的行为
,例如,想要拿到当前实例,可以用new()方法,在所有的类方法中都实现了formate()和parse()方法,不再是之前用单独一个类去解决,而且新的API中所有的类都使用了工厂模式和策略模式; - 实用性:所有新的日期和时间API类都实现了一系列方法用以完成通用的需求,例如:加、减、格式化、解析、从日期或时间中提取单独部分等等;
- 可扩展性:新的日期/时间API是基于[国际标准ISO 8601](https://baike.baidu.com/item/ISO 8601),其实我们也是可以将其用于非IOS的日历上
3.Java8中的日期和时间API包含的包
- java.time包:这是新的Java日期/时间API的基础包,所有的主要基础类都是该包的一部分,例如:LocalDate、LocalTime、LocalDateTime、Instant、Period、Duration等类。这些类都是线程安全的
- java.time.chrono包:这个包为非ISO的日历标准定义了一些泛化的API,我们可以拓展AbstractChronology来创建自己的日历标准
- java.time.formate包:这个包包含能够格式化和解析日期时间对象的类,
在绝大数情况下,我们不应该直接使用它
,因为java.time包中相应的类已经提供了格式化和解析的方法 - java.time.temporal包:这个包含一些时态对象,可以用其找出关于某个日期/时间对象的某个特定日期或时间,比如说找到某个月的第一天或最后一天,可以根据withXXX的格式进行区分
- java.time.zone包:这个包支持不同的时区以及相关规则的类
4.常用类以及方法
我们使用比较频繁地可能是以下几个类:
- Instant: 代表的是时间戳,时刻
- LocalDate:不包含具体时间(时分秒)的日期
- LocalTime: 不包含日期的时间
- LocalDateTime: 包含了日期以及时间
- Period: 计算日期差,用于LocalDate之前的比较
- Duration: 计算日期时间差,用于LocalDateTime之间的比较,也可用于Instant之间的比较
- ChronoUnit(java.time.temporal): 用于比较所有的单位时间的工具类
- 时区: ZoneId, ZoneOffset
- 带时区的日期和时间: ZonedDateTime
- DateTimeFormatter(java.time.format): 日期格式化器
4.1LocalDate
LocalDate是不变的日期时间对象代表一个日期,往往被视为年月日。
4.1.1常用API
方法 | 描述 |
static LocalDate now() | 从默认时区的系统时钟获取当前日期 |
static LocalDate of(int year, int month, int dayofMonth) | 从一年,一个月和一天获得一个LocalDate的实例 |
int get(TemporalField field) | 从这个日期时间作为一个int获取指定字段的值,一般使用实现类ChronoField |
int getYear() | 获取年份字段 |
int getMonthValue() | 获取月份 |
int getDayofMonth() | 获取当月的第几天,一般用这个方法获取日 |
String format(DateTimeFormatter formatter) | 格式化日期,日期转String |
static LocalDate parse(CharSequence text, DateTimeFormatter formatter) | 字符串转日期 |
static LocalDateTime parse(CharSequence text) | 获得LocalDate实例从一个字符串 |
int compareTo(chronoLocalDate other) | 将此日期与另一个日期比较 |
boolean isAfter(ChronoLocalDate other) | 检查此日期是否在指定日期之后 |
boolean isBefore(ChronoLocalDate other) | 检查此日期是否在指定日期之前 |
boolean isEqual(ChronoLocalDate other) | 检查此日期是否等于指定日期 |
LocalDate plus(long amountToAdd, TemporalUnit unit) | 返回此日期的一个副本, 添加指定的TemporalUnit。 |
LocalDate minusDays(long daysToSubtract) | 返回此LocalDate的副本,并减去指定的天数(年份和月份类似) |
LocalDate plusDays(long daysToAdd) | 返回此LocalDate的副本,并增加指定的天数(年份和月份类似 |
long until(Temporal endExclusive, TemporalUnit unit) | 计算时间的量,直到指定单元的另一个日期为止 |
ZonedDateTime atStartofDay(ZoneId zone) | 根据时区中的规则,在最找的有效时间内从此日期返回划分的日期时间 |
LocalDate with(TemporalAdjuster adjuster) | 返回此日期的调整副本 |
LocalDate with(TemporalField field, long newValue) | 给字段的字段设置新值 |
LocalDate withYear(int year) | 返回此日期的副本与年更改。 |
LocalDate withMonth(int month) | 返回此日期的副本与更改的月份 |
LocalDate withDayOfMonth(int dayOfMoth) | 返回此日期的副本与月更改日期。 |
String toString() | 输出该日期时间为字符串 |
4.1.2案例展示
LocalDate date = LocalDate.of(2022, 1, 1);
LocalDate date2 = LocalDate.of(2022, 2, 1);
//获取日期内容信息
System.out.println(date);
System.out.println(date.getYear()); = localDate.get(ChronoField.YEAR)
System.out.println(date.getMonthValue()); = localDate.get(ChronoField.MONTH_OF_YEAR)
System.out.println(date.getDayOfMonth()); = localDate.get(ChronoField.DAY_OF_MONTH)
System.out.println(date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
LocalDate parse = LocalDate
.parse("2023-01-19", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println(parse);
//日期比较
System.out.println(date.compareTo(date2));
System.out.println(date.isAfter(date2));
System.out.println(date.isBefore(date2));
System.out.println(date.equals(date2));
//日期加运算
System.out.println(date.plusYears(1)) = date.plus(1, ChronoUnit.YEARS)
System.out.println(date.plusMonths(1)) = date.plus(1, ChronoUnit.MONTHS)
System.out.println(date.plusDays(1)) = date.plus(1, ChronoUnit.DAYS)
//日期减运算
System.out.println(date.minusYears(1));
System.out.println(date.minusMonths(1));
System.out.println(date.minusDays(1));
//日期间隔运算,ChronoUnit枚举是TemporalUnit的实现类, 还可以计算时分秒等
System.out.println(date.until(date2, ChronoUnit.YEARS));
System.out.println(date.until(date2, ChronoUnit.MONTHS));
System.out.println(date.until(date2, ChronoUnit.DAYS));
//调整年份,月,日
LocalDate date = LocalDate.of(2015, 1, 1);
LocalDate newDate = localDate.with(ChronoField.YEAR, 2018) =>2018-01-01 和date.withYear是等价的
System.out.println(date.withYear(2018)); => 2018-01-01
System.out.println(date.withMonth(5)); => 2015-05-01
System.out.println(date.withDayOfMonth(2)); => 2015-01-02
System.out.println(date.withDayOfYear(35)); => 2015-02-04
4.1.3拓展使用
- 和Date之间的相互转换
public Date localDate2Date(LocalDate localDate){
ZonedDateTime zdt = localDate.atStartOfDay(ZoneId.systemDefault());
return Date.from(zdt.toInstant());
}
public LocalDate date2LocalDate(Date date) {
ZonedDateTime zdt = date.toInstant().atZone(ZoneId.systemDefault());
return zdt.toLocalDate();
}
- 调整日期
LocalDate with(TemporalAdjuster adjuster)
, 使用TemporalAdjusters类:
//获取这个月的第一天, 以及localDate获取第一天并转Date(其他类似)
System.out.println(localDate.with(TemporalAdjusters.firstDayOfMonth()));
Date startDate = Date.from(localDate.with(TemporalAdjusters.firstDayOfMonth())
.atStartOfDay(ZoneId.systemDefault()).toInstant());
//获取这个月最后一天
System.out.println(localDate.with(TemporalAdjusters.lastDayOfMonth()));
//获取上个月第一天获取上个月最后一天
LocalDate lastMonathLocalDate = localDate.minusMonths(1);
......
//获取今年第一天
System.out.println(localDate.with(TemporalAdjusters.firstDayOfYear()));
//获取今年最后一天
System.out.println(localDate.with(TemporalAdjusters.lastDayOfYear()));
4.2LocalTime
LocalTime是不变的日期时间对象代表一个时间,往往被视为小时分钟秒,方法使用借鉴LocalDate即可
4.3LocalDateTime
LocalDate是不变的日期时间对象代表一个日期时间,往往被视为年、月、日、时、分、秒。
4.3.1常用API
其实方法跟LocalDate差不多, 只是多了一些时分秒的操作,这里就列举一些LocalDateTime的API
方法 | 描述 |
static LocalDateTime now() | 从默认时区的系统时钟获取当前日期时间 |
of(int year, int month, int dayOfMonth, int hour, int minute, int second) | 获得LocalDateTime从年,月,日,小时,分钟和秒的实例,设置纳秒为零 |
atZone(ZoneId zone) | 结合时间与时区来创建一个ZonedDateTime |
int get(TemporalField field) | 从这个日期时间作为一个int获取指定字段的值, 一般使用实现类ChronoField |
int getYear() | 获取年度字段。 |
int getMonthValue() | 从1到12得到一个月的时间字段。 |
int getDayOfMonth() | 获取月字段的一天。 |
int getHour() | 获取小时字段 |
int getMinute() | 获取分钟字段 |
int getSecond() | 获取秒 |
boolean isAfter(ChronoLocalDateTime<?> other) | 检查此日期是否在指定日期之后 |
boolean isBefore(ChronoLocalDateTime<?> other) | 检查此日期是否在指定日期之前 |
boolean isEqual(ChronoLocalDateTime<?> other) | 检查此日期是否等于指定日期 |
LocalDateTime minus(long amountToSubtract, TemporalUnit unit) | 返回日期时间副本, 减少指定的单位数量 |
LocalDateTime minusHours(long Hours) | 返回此LocalDateTime的副本,以减少的小时数(年月日类似) |
LocalDateTime minusMinutes(long minutes) | 返回此LocalDateTime的副本,以减少的分钟数 |
LocalDateTime minusSeconds(long seconds) | 返回此LocalDateTime的副本,以减少的秒数 |
LocalDateTime plus(long amountToAdd, TemporalUnit unit) | 返回日期时间副本, 增加指定的单位数量 |
LocalDateTime plusHours(long Hours) | 返回此LocalDateTime的副本,以增加的小时(年月日等类似) |
LocalDateTime until(Temporal endExclusive, TemporalUnit unit) | 计算时间的量,直到指定单元的另一个日期时间 |
LocalDateTime with(TemporalField field, long newValue) | 将此日期时间的副本与指定的字段设置为一个新值,一般使用实现类ChronoField |
LocalDateTime with(TemporaAdjuster adjuster) | 返回此日期时间的调整副本 |
LocalDate toLocalDate() | 获取这个日期时间LocalDate的一部分 |
LocalTime toLocalTIme() | 获取这个日期时间LocalTime的一部分 |
4.3.2案例展示
//测试
LocalDateTime date = LocalDateTime.of(2010, 5, 5, 5, 5, 5);
LocalDateTime date2 = LocalDateTime.of(2010, 5, 5, 5, 5, 5);
System.out.println(date.getYear()); = date.get(ChronoField.YEAR)
System.out.println(date.getMonthValue());
System.out.println(date.getDayOfMonth());
System.out.println(date.getHour());
System.out.println(date.getMinute());
System.out.println(date.getSecond());
System.out.println(date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
LocalDate parse = LocalDate
.parse("2023-01-19", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println(parse);
//日期比较
System.out.println(date.compareTo(date2));
System.out.println(date.isAfter(date2));
System.out.println(date.isBefore(date2));
System.out.println(date.equals(date2));
//加运算
System.out.println(date.plusYears(1));
System.out.println(date.plusMonths(1));
System.out.println(date.plusDays(1));
System.out.println(date.plusHours(1));
System.out.println(date.plusMinutes(1));
System.out.println(date.plusSeconds(date.getSecond()));
//减运算
System.out.println(date.minusYears(1));
System.out.println(date.minusMonths(1));
System.out.println(date.minusDays(1));
System.out.println(date.minusHours(1));
System.out.println(date.minusMinutes(1));
System.out.println(date.minusSeconds(1));
//转换LocalDate,LocalTime
System.out.println(date.toLocalDate());
System.out.println(date.toLocalTime());
//日期间隔运算,ChronoUnit枚举是TemporalUnit的实现类
System.out.println(date.until(date2, ChronoUnit.YEARS));
System.out.println(date.until(date2, ChronoUnit.MONTHS));
System.out.println(date.until(date2, ChronoUnit.DAYS));
System.out.println(date.until(date2, ChronoUnit.HOURS));
System.out.println(date.until(date2, ChronoUnit.MINUTES));
System.out.println(date.until(date2, ChronoUnit.SECONDS));
//日期调整
date.with(ChronoField.YEAR, 2020)
.....
4.3.3拓展使用
- 和Date之间相互转换
public Date localDateTime2Date(LocalDateTime localDateTime){
ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
return Date.from(zdt.toInstant());
}
public LocalDateTime date2LocalDateTime(Date date) {
ZonedDateTime zdt = date.toInstant().atZone(ZoneId.systemDefault());
return zdt.toLocalDateTime();
}
- 调整日期,参考LocalDate
4.4Instant
4.4.1常用API
方法 | 描述 |
static Instant now() | 从系统时钟中获得当前时刻。 |
ZonedDateTime atZone(ZoneId zone) | 结合即时时区创建 |
long toEpochMilli() | 把这瞬间的毫秒数从1970-01-01t00:00:00z时代。 |
long getEpochSecond() | 从1970-01-01t00:00:00z java时代得到的秒数。 |
long until(Temporal endExclusive, TemporalUnit unit) | 计算时间的量,直到指定单元的另一个时刻为止。 |
4.4.2概念关系
计算机存储的当前时间,本质上是一个不断递增的整数。Java提供的System.currentTimeMillis()
返回的就是以毫秒表示的当前时间戳。这个时间戳在java.time中以Instant类型表示,我们用Instant.now()
获取当前时间戳,效果System.currentTimeMillis()
类似:
Instant now = Instant.now();
System.out.println(System.currentTimeMillis()); => 1617873014216
System.out.println(now.getEpochSecond());//秒 => 1617873014
System.out.println(now.toEpochMilli());//毫秒 => 1617873014216
实际上,Instant内部只有2个核心字段:
public final class Instant implements ... {
private final long seconds;
private final int nanos;
}
一个是以秒为单位的时间戳,一个是更精确的纳秒精度。它和System.currentTimeMillis()
返回的long
相比,只是多了更高精度的纳秒。既然Instant
就是时间戳,那么,给它附加上一个时区,就可以创建出ZonedDateTime
:
ZonedDateTime zonedDateTime = Instant.now().atZone(ZoneId.systemDefault());
System.out.println(zonedDateTime);
2020-04-08T17:34:00.825+08:00[Asia/Shanghai]
可见,对于某一个时间戳或者时间,给它关联上指定的ZoneId,就得到了ZonedDateTime
, 继而可以获得对应的LocalDateTime
。ZonedDateTime
可以作为一个转换的媒介
4.5Period
Period类用来度量两个日期之间年、月、日的间隔值
注意: 如果是指定某年,某月,某日相差总数,请使用LocalDate的until(Temporal endExclusive, TemporalUnit unit)方法
4.5.1常用API
方法 | 描述 |
static Period of(int years, int months, int days) | 获得Period代表数年、月、日 |
static Period between(LocalDate start, LocalDate end) | 获得由年数Period月,和两个日期之间的天数 |
int getYears() | 获取此期间的年数 |
int getMonths() | 获取此期间的月份 |
int getDays() | 获取此期间的天数 |
long toTotalMonths() | 获取此期间的总月数 |
boolean isNegative() | 检查这一时期的三个单位是否都是负的 |
Period minus(TemporalAmount temp) | 返回此期间的一个副本,与指定的周期减去 |
Period minusYears(long yearsToSubtract) | 返回此期间的一个副本,用指定的年份减去(月份和日类似) |
Period plusYears(long yearsToAdd) | 返回此期间的一个副本,用指定的年份加上(月份和日类似) |
Period withYears(int years) | 返回此期间的一个副本,指定年数 |
Perod withMonths(int months) | 返回此期间的一个副本,指定月份 |
Period withDays(int days) | 返回此期间的一个副本,指定日数 |
4.5.2案例使用
LocalDate startDate = LocalDate.of(2019, 2, 2);
LocalDate endDate = LocalDate.of(2020, 3, 28);
//日期间隔内容获取
Period period = Period.between(startDate, endDate);
System.out.println(period.getYears()); => 1
System.out.println(period.getMonths()); => 1
System.out.println(period.getDays()); => 26
System.out.println(period.toTotalMonths()); =>13
System.out.println(period.isNegative()); => false: endDate>startDate, true: endDate<startDate
//添加减少操作
Period period1 = period.minus(Period.of(1, 2, 5)); => 批量扣减: 0, -1, 21
System.out.println(period.plusYears(1));
System.out.println(period.plusMonths(1));
System.out.println(period.plusDays(1).getDays());
System.out.println(period.minusYears(1));
........
//指定操作
System.out.println(period.withYears(3).getYears()); => 3
........
4.6Duration
Duration类用来度量秒或纳秒时间间隔,适合处理较短的时间,需要更高的精确性
注意: 如果是指定某年,某月,某日相差总数,请使用LocalDate的until(Temporal endExclusive, TemporalUnit unit)方法
4.6.1常用API
方法 | 描述 |
static Duration of(long amount, TemporalUnit unit) | 获取Duratiion代表指定的单位数量,一般使用实现类ChronoUnit指定单位 |
static Duration between(Temporal start, Temporal end) | 获得Duration表示两个时间对象之间的时间 => 和LocalDate不同,参数是接口,除了LocalDateTime,还可以指定时间戳Instant等… |
int get(TemporalUnit unit) | 获取所请求单元的值,一般使用实现类ChronoUnit指定单位 |
long toDays() | 获取此期间的天数 |
long toHours() | 获取此期间的几个小时数 |
long toMinutes() | 获取此期间的分钟数 |
long getSeconds | 获取此期间的秒数 |
long toMillis() | 将此持续时间转换为毫秒内的总长度 |
long getNano | 得到的纳秒数 |
plus(Duration duration) | 返回此持续时间的副本,添加指定的持续时间。 |
plus(long amountToAdd, TemporalUnit unit) | 返回此持续时间的副本,添加指定的持续时间。 |
minus(Duration duration) | 返回此持续时间的副本,用指定的持续时间减去。 |
minus(long amountToAdd, TemporalUnit unit) | 返回此期间的一个副本,用指定的持续时间减去。 |
4.6.2案例展示
LocalDateTime localDateTime = LocalDateTime.of(2019, 2, 2, 10, 10, 10);
LocalDateTime localDateTime2 = LocalDateTime.of(2020, 3, 3, 20, 20, 20);
Duration between = Duration.between(localDateTime, localDateTime2);
//获取间隔时间
System.out.println(between.toDays());
System.out.println(between.toHours());
System.out.println(between.toMinutes());
System.out.println(between.getSeconds());
System.out.println(between.toMillis());
System.out.println(between.getNano());
//增加或者减少等操作
between.plus(1, ChronoUnit.Days)
...........
between.minus(1, ChronoUnit.Days)
.......
//结合Instant
Instant start = Instant.now();
try {
//代码..........
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Instant end = Instant.now();
Duration between = Duration.between(start, end);
//秒
System.out.println(between.getSeconds());
//毫秒
System.out.println(between.toMillis());
异常处理:
//间隔增加年抛出异常
betwueen.plus(1, ChronoUnit.YEARS)
java.time.temporal.UnsupportedTemporalTypeException: Unit must not have an estimated duration
进去了Duration的plus方法,这行出现了问题, 再进入到该方法中,发现有进行顺序对比
原来是isDurationEstimated方法ordinal< Days的ordinal才会通过,查看Enum类的ordinal属性, 就是枚举类中的排列顺序,从0开始
ChronoUnit中,我们指定在Days之前的枚举就行了
4.7DateTimeFormatter
日期时间对象格式化和解析
4.7.1常用API
方法 | 描述 |
static DateTimeFormatter ofPattern(String pattern) | 创建一个格式化程序使用指定的模式 |
static DateTimeFormatter ofPattern(String pattern,Locale locale) | 获得由年数Period月,和两个日期之间的天数 |
String format(TemporalAccessor temporal) | 使用格式化程序格式的日期时间对象 |
TemporalAccessor parse(CahrSequence text) | 充分分析文本产生的时空对象 |
TemporalAccessor parse(CahrSequence text, ParsePostion position) | 分析文本使用此格式化程序,提供对文本位置的控制 |
Strinig format(DateTimeFormatter formatter) | 使用指定的格式的日期格式(LocalDate, LocalDateTime) |
static LocalDate parse(CharSequence text, DateTimeFormatter formatter) | 获得LocalDate实例从使用特定格式的字符串 |
static LocalDateTime parse(CharSequence text, DateTimeFormatter formatter) | 获得LocalDateTime实例从使用特定格式的字符串 |
除了方法,DateTimeFormatter还初始化了很多静态字段对象, 比如ISO_LOCAL_DATE(yyyy-mm-dd)、BASIC_ISO_DATE等
4.7.2案例展示
//LocalDate
LocalDate localDate = LocalDate.of(2014, 2, 2);
String format = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
LocalDate parse = LocalDate.parse("2018-06-06", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
//LocalDateTime
LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.of(10, 10, 10));
String format1 = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
LocalDateTime parse1 = localDateTime.parse("2018-06-06 10:10:10", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
4.8ZoneId和ZonedDateTime
之前看到的日期和时间的种类都不包含时区信息,时区的处理是新版日期和时间API新增加的重要功能,使用新版日期和时间API被极大的简化了。新的java.time.ZoneId类是老板java.util.TimeZone的替代品。
时区是按照一定的规则将区域划分成的标准时间相同的区间。在ZoneRules这个类中包含了40个这样的实例。你可以简单地通过调用ZoneId的getRules()得到指定时区的规则。每个特定ZoneId对象都由一个地区ID标识,地区ID都为”{区域}/{城市}“的格式,比如:
ZoneId romeZone = ZoneId.of("Europe/Rome"); java
一旦得到一个ZoneId对象, 你就可以把LocalDate, LocalDateTime或者是Instant对象整合起来,构造为一个ZonedDateTime实例,它代表了相对于指定时区的时间点:
LocalDate date = LocalDate.of(2014, Month.MARCH, 18);
ZonedDateTime zdt1 = date.atStartOfDay(romeZone);
LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45);
ZonedDateTime zdt2 = dateTime.atZone(romeZone);
Instant instant = Instant.now();
ZonedDateTime zdt3 = instant.atZone(romeZone);
ZonedDateTIme的组成部分
:
通过ZoneId->下面的romeZone,你还可以将LocalDateTime转换为Instant:
LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45);
Instant instantFromDateTime = dateTime.toInstant(romeZone);
你也可以通过反向的方式得到LocalDateTime对象:
Instant instant = Instant.now();
LocalDateTime timeFromInstant = LocalDateTime.ofInstant(instant, romeZone);
参考:
https://www.liaoxuefeng.com/wiki/1252599548343744/1298613246361634 https://docs.oracle.com/javase/8/docs/api/index.html