Java8新特性(五)新日期时间的API

1、新时间日期API

  • java.time 包含值对象的基础包
  • java.time.chrono 提供对不同的日历系统的访问
  • java.time.format 格式化和解析时间和日期
  • java.time.temporal – 包括底层框架和扩展特性
  • java.time.zone – 包含时区支持的

说明:大多数开发者只会用到基础包和format包,也可能会用到temporal包。因此,尽管有68个新的公开类型,大多数开发者,大概将只会用到其中的三分之一。

2、LocalDateLocalTimeLocalDateTime

LocalDateLocalTimeLocalDateTime 类是其中较重要的几个类,它们的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。

 ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法,也就是公历。

方法

描述

now() / *  now(ZoneId zone)

静态方法根据当前时间创建对象/指定时区的对象

of()

静态方法,根据指定日期/时间创建对象

getDayOfMonth()/getDayOfYear()

获得月份天数(1-31) /获得年份天数(1-366)

getDayOfWeek()

获得星期几(返回一个 DayOfWeek 枚举值)

getMonth()

获得月份, 返回一个 Month 枚举值

getMonthValue() / getYear()

获得月份(1-12) /获得年份

getHour()/getMinute()/getSecond()

获得当前对象对应的小时、分钟、秒

withDayOfMonth()/withDayOfYear()/

withMonth()/withYear()

将月份天数、年份天数、月份、年份修改为指定的值并返回新的对象

plusDays(), plusWeeks(),

plusMonths(), plusYears(),plusHours()

当前对象添加几天、几周、几个月、几年、几小时

minusMonths() / minusWeeks()/

minusDays()/minusYears()/minusHours()

当前对象减去、几周、几年、几小时

2.1、LocalDateLocalTime

开始使用新的日期和时间API时,你最先碰到的可能是LocalDate类。该类的实例是一个不可变对象,它只提供了简单的日期,并不含当天的时间信息。另外,它也不附带任何与时区相关的信息。

你可以通过静态工厂方法of创建一个LocalDate实例。LocalDate实例提供了多种方法来 读取常用的值,比如年份、月份、星期几等,如下所示:

package java8;
 
import java.time.LocalDate;
 
public class DateTimeTest {
 
    public static void main(String[] a) {
        //获取当前日期
        LocalDate now = LocalDate.now();
        
        //获取指定年月日的localdate
        LocalDate date = LocalDate.of(2018, 12, 24);
        
        System.out.println("年:" + date.getYear());
        
        System.out.println("月:" + date.getMonthValue());
        
        System.out.println("几号:" + date.getDayOfMonth());
        
        System.out.println("星期几:" + date.getDayOfWeek().getValue());
        
        System.out.println("当年中的第几天:" + date.getDayOfYear());
        
        System.out.println("当月的天数:"+date.lengthOfMonth());
        
        System.out.println("当年的天数:"+date.lengthOfYear());
        
    }
}
 

类似地,一天中的时间,比如13:45:20,可以使用LocalTime类表示。你可以使用of重载的两个工厂方法创建LocalTime的实例。第一个重载函数接收小时和分钟,第二个重载函数同时还接收秒。同LocalDate一样,LocalTime类也提供了一些getter方法访问这些变量的值,如下所示。

//表示11:30分
LocalTime time=LocalTime.of(11,30);
 
//11:30:50
LocalTime time2=LocalTime.of(11,30,50);
 
System.out.println("时:"+time2.getHour());
System.out.println("分:"+time2.getMinute());
System.out.println("秒:"+time2.getSecond());    

LocalDate和LocalTime都可以通过解析代表它们的字符串创建。使用静态方法parse,你可以实现这一目的:

LocalDate date = LocalDate.parse("2018-12-24");
    
LocalTime time = LocalTime.parse("13:45:20");

你可以向parse方法传递一个DateTimeFormatter。该类的实例定义了如何格式化一个日期或者时间对象。

2.2、合并日期和时间

这个复合类名叫LocalDateTime,是LocalDate和LocalTime的合体。它同时表示了日期和时间,但不带有时区信息,你可以直接创建,也可以通过合并日期和时间对象构造。

 //2017-05-29 11:30:50
 LocalDateTime dateTime=LocalDateTime.of(2017,5,29,11,30,50);
 
 LocalDateTime dateTime2=LocalDateTime.of(date,time2);

可以通过它们各自的atTime或者atDate方法,向LocalDate传递一个时间对象,或者向LocalTime传递一个日期对象的方式,你可以创建一个LocalDateTime对象。你也可以使用toLocalDate或者toLocalTime方法,从LocalDateTime中提取LocalDate或LocalTime对象。

LocalDateTime ldt=time2.atDate(date);
 
LocalDateTime dateTime3=date.atTime(time2);
 
LocalDate localDate = dateTime3.toLocalDate();
 
LocalTime localTime=dateTime3.toLocalTime();

3、 Instant 时间戳

在处理时间和日期的时候,我们通常会想到,,,,,。然而,这只是时间的一个模型,是面向人类的。第二种通用模型是面向机器的,或者说是连续的。在此模型中,时间线中的一个点表示为一个很大的数,这有利于计算机处理。UNIX中,这个数从1970年开始,以秒为的单位;同样的,在Java中,也是从1970年开始,但以毫秒为单位。

java.time包通过值类型Instant提供机器视图,不提供处理人类意义上的时间单位。Instant表示时间线上的一点,而不需要任何上下文信息,例如,时区。概念上讲,它只是简单的表示自197011000秒(UTC)开始的秒数。因为java.time包是基于纳秒计算的,所以Instant的精度可以达到纳秒级(1 ns = 10-9 s)   1= 1000毫秒 =10^6微秒=10^9纳秒。

方法

描述

now()

静态方法返回默认UTC时区的Instant类的对象

ofEpochMilli(long epochMilli)

静态方法返回在1970-01-01 00:00:00基础上加上指定毫秒数之后的Instant类的对象

atOffset(ZoneOffset offset)

结合即时的偏移来创建一个 OffsetDateTime

toEpochMilli()

返回1970-01-01 00:00:00到当前时间的毫秒数,即为时间戳

  • 时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间19700101080000)起至现在的总秒数。

作为人,我们习惯于以星期几、几号、几点、几分这样的方式理解日期和时间。毫无疑问, 这种方式对于计算机而言并不容易理解。新的java.time.Instant类是以Unix元年时间(传统的设定为UTC时区1970年1月1日午夜时分)开始所经历的秒数来表示时间。可以通过向静态工厂方法ofEpochSecond传递一个代表秒数的值创建一个该类的实例。静态工厂方法ofEpochSecond还有一个增强的重载版本,它接收第二个以纳秒为单位的参数值,对传入作为秒数的参数进行调整。一旦得到Instant对象,你就可以像之前的LocalDate和LocalTime一样获取该时间的各个信息。

        //获取当前时间的instant
        Instant now_instant=Instant.now();
        
        //传入秒得到instant
        Instant instant=Instant.ofEpochSecond(100);
        
        //传入毫秒
        Instant instant2=Instant.ofEpochMilli(100000);
 
        now.getDayOfMonth();
        
        now.getDayOfYear();
        
        now.getMonthValue();
        
        now.getYear();
        
        now.lengthOfYear();

4、Duration  和 Period

  • Duration:用于计算两个“时间”间隔
  • Period:用于计算两个“日期”间隔

Duration类主要用于以秒和纳秒衡量时长。Duration类的静态工厂方法between用于创建两个时间之间的时长。

你可以创建两个LocalTime对象、两个LocalDateTime或者两个Instant对象之间的duration。

        //创建两个localTime之间的时长对象
        Duration duration = Duration.between(LocalTime.of(19, 20), LocalTime.of(19, 30));
        
        //获取相差多少秒      
      System.out.println(duration.getSeconds());
 
        //创建两个LocalDateTime之间的时长对象
        Duration duration2 = Duration.between(LocalDateTime.of(2017, 5, 29, 19, 20), LocalDateTime.of(2017, 5, 29, 19, 30));
      
        //获取相差多少秒
        System.out.println(duration2.getSeconds());
     
        //获取相差多少秒的绝对值
        System.out.println(duration2.abs().getSeconds());
       
        //相差多少天
        System.out.println(duration2.toDays());
        
        //相差多少时
        System.out.println(duration2.toHours());
       
        //相差多少分钟
        System.out.println(duration2.toMinutes());
       
        //相差多少毫秒
        System.out.println(duration2.toMillis());
 

由于LocalDateTime和Instant是为不同的目的而设计的,一个是为了便于人阅读使用, 另一个是为了便于机器处理,所以你不能将二者混用。如果你试图在这两类对象之间创建 duration,会触发一个DateTimeException异常。此外,由于Duration类主要用于以秒和纳秒衡量时间的长短,你不能仅向between方法传递一个LocalDate对象做参数。

如果你需要以年、月或者日的方式对多个时间单位建模,可以使用Period类。使用该类的 工厂方法between,你可以使用得到两个LocalDate之间的时长,如下所示:

Period tenDays = Period.between(LocalDate.of(2017, 3, 8),                         LocalDate.of(2017, 3, 18));

Duration和Period类都提供了很多非常方便的工厂类,用于直接创建对应的实例。

       //1天的时长转成小时
        System.out.println(Duration.ofDays(1).toHours());
 
        //1小时的时长转成分钟
        System.out.println(Duration.ofHours(1).toMinutes());
 
        //10天的时长
        System.out.println(Period.ofDays(10).getDays());

5、日期的操纵

  • TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整到“下个周日”等操作。
  • TemporalAdjusters : 该类通过静态方法提供了大量的常用 TemporalAdjuster 的实现。

例如获取下个周日:

6、格式化与解析日期时间

java.time.format.DateTimeFormatter 类:该类提供了三种格式化方法:

  • 预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE
  • 本地化相关的格式。如:ofLocalizedDate(FormatStyle.FULL)
  • 自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss E”)

方法

描述

ofPattern(String pattern)

静态方法,返回一个指定字符串格式的DateTimeFormatter

format(TemporalAccessor t)

格式化一个日期、时间,返回字符串

parse(CharSequence text)

将指定格式的字符序列解析为一个日期、时间

7、时区的处理

Java8 中加入了对时区的支持,带时区的时间为分别为:
ZonedDate、ZonedTime、ZonedDateTime
其中每个时区都对应着 ID,地区ID都为 “{区域}/{城市}”的格式
例如 :Asia/Shanghai 等

  • ZoneId:该类中包含了所有的时区信息
  • getAvailableZoneIds() : 可以获取所有时区时区信息
  • of(id) : 用指定的时区信息获取 ZoneId 对象

8、与传统日期处理的转换

猜你喜欢

转载自blog.csdn.net/MyronCham/article/details/85232437