文章目录

  • 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)

结合即时时区创建 ZonedDateTime

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, 继而可以获得对应的LocalDateTimeZonedDateTime可以作为一个转换的媒介

java项目new date时区问题_编程语言

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

java项目new date时区问题_java项目new date时区问题_02


进去了Duration的plus方法,这行出现了问题, 再进入到该方法中,发现有进行顺序对比

java项目new date时区问题_API_03


java项目new date时区问题_java项目new date时区问题_04


原来是isDurationEstimated方法ordinal< Days的ordinal才会通过,查看Enum类的ordinal属性, 就是枚举类中的排列顺序,从0开始

java项目new date时区问题_API_05


ChronoUnit中,我们指定在Days之前的枚举就行了

java项目new date时区问题_java项目new date时区问题_06

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的组成部分:

java项目new date时区问题_System_07

通过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