前言

由于Java Date的各种问题,Java8推出了新的日期API,很受一拨人的追捧。

为什么我们需要新的Java日期/时间API?

在开始研究Java 8日期/时间API之前,让我们先来看一下为什么我们需要这样一个新的API。在Java中,现有的与日期和时间相关的类存在诸多问题,其中有:

  • Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。
  • java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。

    对于时间、时间戳、格式化以及解析,并没有一些明确定义的类。对于格式化和解析的需求,我们有java.text.DateFormat抽象类,但通常情况下,SimpleDateFormat类被用于此类需求。
  • 所有的日期类都是可变的,因此他们都不是线程安全的,这是Java日期类最大的问题之一。
  • 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。

在现有的日期和日历类中定义的方法还存在一些其他的问题,但以上问题已经很清晰地表明:Java需要一个健壮的日期/时间类。这也是为什么Joda Time在Java日期/时间需求中扮演了高质量替换的重要角色。

Java 8日期/时间API

Java 8日期/时间API是JSR-310的实现,它的实现目标是克服旧的日期时间实现中所有的缺陷,新的日期/时间API的一些设计原则是:

不变性:新的日期/时间API中,所有的类都是不可变的,这对多线程环境有好处。

关注点分离:新的API将人可读的日期时间和机器时间(unix timestamp)明确分离,它为日期(Date)、时间(Time)、日期时间(DateTime)、时间戳(unix timestamp)以及时区定义了不同的类。

清晰:在所有的类中,方法都被明确定义用以完成相同的行为。举个例子,要拿到当前实例我们可以使用now()方法,在所有的类中都定义了format()和parse()方法,而不是像以前那样专门有一个独立的类。为了更好的处理问题,所有的类都使用了工厂模式和策略模式,一旦你使用了其中某个类的方法,与其他类协同工作并不困难。

实用操作:所有新的日期/时间API类都实现了一系列方法用以完成通用的任务,如:加、减、格式化、解析、从日期/时间中提取单独部分,等等。

可扩展性:新的日期/时间API是工作在ISO-8601日历系统上的,但我们也可以将其应用在非IOS的日历上。

Java日期/时间API包

Java日期/时间API包含以下相应的包。

  1. java.time包:这是新的Java日期/时间API的基础包,所有的主要基础类都是这个包的一部分,如:LocalDate, LocalTime, LocalDateTime, Instant, Period, Duration等等。所有这些类都是不可变的和线程安全的,在绝大多数情况下,这些类能够有效地处理一些公共的需求。
  2. java.time.chrono包:这个包为非ISO的日历系统定义了一些泛化的API,我们可以扩展AbstractChronology类来创建自己的日历系统。

    java.time.format包:这个包包含能够格式化和解析日期时间对象的类,在绝大多数情况下,我们不应该直接使用它们,因为java.time包中相应的类已经提供了格式化和解析的方法。
  3. java.time.temporal包:这个包包含一些时态对象,我们可以用其找出关于日期/时间对象的某个特定日期或时间,比如说,可以找到某月的第一天或最后一天。你可以非常容易地认出这些方法,因为它们都具有“withXXX”的格式。
  4. java.time.zone包:这个包包含支持不同时区以及相关规则的类。

Java日期/时间API示例

我们已经浏览了Java日期/时间API的大多数重要部分,现在是时候根据示例仔细看一下最重要的一些类了。

  1. java.time.LocalDate:LocalDate是一个不可变的类,它表示默认格式(yyyy-MM-dd)的日期,我们可以使用now()方法得到当前时间,也可以提供输入年份、月份和日期的输入参数来创建一个LocalDate实例。该类为now()方法提供了重载方法,我们可以传入ZoneId来获得指定时区的日期。该类提供与java.sql.Date相同的功能,对于如何使用该类,我们来看一个简单的例子。
@Test
public void testLocalDate() {
//Current Date
LocalDate today = LocalDate.now();
System.out.println("Current Date=" + today); //Creating LocalDate by providing input arguments
LocalDate firstDay_2014 = LocalDate.of(2014, Month.JANUARY, 1);
System.out.println("Specific Date=" + firstDay_2014); //Try creating date by providing invalid inputs
//LocalDate feb29_2014 = LocalDate.of(2014, Month.FEBRUARY, 29);
//Exception in thread "main" java.time.DateTimeException:
//Invalid date 'February 29' as '2014' is not a leap year //Current date in "Asia/Kolkata", you can get it from ZoneId javadoc
LocalDate todayKolkata = LocalDate.now(ZoneId.of("Asia/Kolkata"));
System.out.println("Current Date in IST=" + todayKolkata); //java.time.zone.ZoneRulesException: Unknown time-zone ID: IST
//LocalDate todayIST = LocalDate.now(ZoneId.of("IST")); //Getting date from the base date i.e 01/01/1970
LocalDate dateFromBase = LocalDate.ofEpochDay(365);
System.out.println("365th day from base date= " + dateFromBase); LocalDate hundredDay2014 = LocalDate.ofYearDay(2014, 100);
System.out.println("100th day of 2014=" + hundredDay2014);
}

打印

Current Date=2018-05-29
Specific Date=2014-01-01
Current Date in IST=2018-05-29
365th day from base date= 1971-01-01
100th day of 2014=2014-04-10
  1. java.time.LocalTime:LocalTime是一个不可变的类,它的实例代表一个符合人类可读格式的时间,默认格式是hh:mm:ss.zzz。像LocalDate一样,该类也提供了时区支持,同时也可以传入小时、分钟和秒等输入参数创建实例,我们来看一个简单的程序,演示该类的使用方法。
@Test
public void testLocalTime() {
//Current Time
LocalTime time = LocalTime.now();
System.out.println("Current Time=" + time); //Creating LocalTime by providing input arguments
LocalTime specificTime = LocalTime.of(12, 20, 25, 40);
System.out.println("Specific Time of Day=" + specificTime); //Try creating time by providing invalid inputs
//LocalTime invalidTime = LocalTime.of(25,20);
//Exception in thread "main" java.time.DateTimeException:
//Invalid value for HourOfDay (valid values 0 - 23): 25 //Current date in "Asia/Kolkata", you can get it from ZoneId javadoc
LocalTime timeKolkata = LocalTime.now(ZoneId.of("Asia/Kolkata"));
System.out.println("Current Time in IST=" + timeKolkata); //java.time.zone.ZoneRulesException: Unknown time-zone ID: IST
//LocalTime todayIST = LocalTime.now(ZoneId.of("IST")); //Getting date from the base date i.e 01/01/1970
LocalTime specificSecondTime = LocalTime.ofSecondOfDay(10000);
System.out.println("10000th second time= " + specificSecondTime);
}

打印

Current Time=19:09:39.656
Specific Time of Day=12:20:25.000000040
Current Time in IST=16:39:39.657
10000th second time= 02:46:40
  1. java.time.LocalDateTime:LocalDateTime是一个不可变的日期-时间对象,它表示一组日期-时间,默认格式是yyyy-MM-dd-HH-mm-ss.zzz。它提供了一个工厂方法,接收LocalDate和LocalTime输入参数,创建LocalDateTime实例。我们来看一个简单的例子。
@Test
public void testLocalDateTime() {
//Current Date
LocalDateTime today = LocalDateTime.now();
System.out.println("Current DateTime=" + today); //Current Date using LocalDate and LocalTime
today = LocalDateTime.of(LocalDate.now(), LocalTime.now());
System.out.println("Current DateTime=" + today); //Creating LocalDateTime by providing input arguments
LocalDateTime specificDate = LocalDateTime.of(2014, Month.JANUARY, 1, 10, 10, 30);
System.out.println("Specific Date=" + specificDate); //Try creating date by providing invalid inputs
//LocalDateTime feb29_2014 = LocalDateTime.of(2014, Month.FEBRUARY, 28, 25,1,1);
//Exception in thread "main" java.time.DateTimeException:
//Invalid value for HourOfDay (valid values 0 - 23): 25 //Current date in "Asia/Kolkata", you can get it from ZoneId javadoc
LocalDateTime todayKolkata = LocalDateTime.now(ZoneId.of("Asia/Kolkata"));
System.out.println("Current Date in IST=" + todayKolkata); //java.time.zone.ZoneRulesException: Unknown time-zone ID: IST
//LocalDateTime todayIST = LocalDateTime.now(ZoneId.of("IST")); //Getting date from the base date i.e 01/01/1970
LocalDateTime dateFromBase = LocalDateTime.ofEpochSecond(10000, 0, ZoneOffset.UTC);
System.out.println("10000th second time from 01/01/1970= " + dateFromBase);
}

在所有这三个例子中,我们已经看到如果我们提供了无效的参数去创建日期/时间,那么系统会抛出java.time.DateTimeException,这是一种运行时异常,我们并不需要显式地捕获它。

同时我们也看到,能够通过传入ZoneId得到日期/时间数据,你可以从它的Javadoc中得到支持的Zoneid的列表,当运行以上类时,可以得到以下输出

打印

Current DateTime=2018-05-29T19:10:00.353
Current DateTime=2018-05-29T19:10:00.353
Specific Date=2014-01-01T10:10:30
Current Date in IST=2018-05-29T16:40:00.353
10000th second time from 01/01/1970= 1970-01-01T02:46:40
  1. java.time.Instant:Instant类是用在机器可读的时间格式上的,它以Unix时间戳的形式存储日期时间,我们来看一个简单的程序
@Test
public void testTimestampForInstant() {
//Current timestamp
Instant timestamp = Instant.now();
System.out.println("Current Timestamp = " + timestamp); //Instant from timestamp
Instant specificTime = Instant.ofEpochMilli(timestamp.toEpochMilli());
System.out.println("Specific Time = " + specificTime); //Duration example
Duration thirtyDay = Duration.ofDays(30);
System.out.println(thirtyDay);
}
  1. 日期API工具:我们早些时候提到过,大多数日期/时间API类都实现了一系列工具方法,如:加/减天数、周数、月份数,等等。还有其他的工具方法能够使用TemporalAdjuster调整日期,并计算两个日期间的周期。
@Test
public void testDateTool() {
LocalDate today = LocalDate.now(); //Get the Year, check if it's leap year
System.out.println("Year " + today.getYear() + " is Leap Year? " + today.isLeapYear()); //Compare two LocalDate for before and after
System.out
.println("Today is before 01/01/2015? " + today.isBefore(LocalDate.of(2015, 1, 1))); //Create LocalDateTime from LocalDate
System.out.println("Current Time=" + today.atTime(LocalTime.now())); //plus and minus operations
System.out.println("10 days after today will be " + today.plusDays(10));
System.out.println("3 weeks after today will be " + today.plusWeeks(3));
System.out.println("20 months after today will be " + today.plusMonths(20)); System.out.println("10 days before today will be " + today.minusDays(10));
System.out.println("3 weeks before today will be " + today.minusWeeks(3));
System.out.println("20 months before today will be " + today.minusMonths(20)); //Temporal adjusters for adjusting the dates
System.out.println(
"First date of this month= " + today.with(TemporalAdjusters.firstDayOfMonth()));
LocalDate lastDayOfYear = today.with(TemporalAdjusters.lastDayOfYear());
System.out.println("Last date of this year= " + lastDayOfYear); Period period = today.until(lastDayOfYear);
System.out.println("Period Format= " + period);
System.out.println("Months remaining in the year= " + period.getMonths());
}
  1. 解析和格式化:将一个日期格式转换为不同的格式,之后再解析一个字符串,得到日期时间对象,这些都是很常见的。我们来看一下简单的例子。
@Test
public void testFormat() {
//Format examples
LocalDate date = LocalDate.now();
//default format
System.out.println("Default format of LocalDate=" + date);
//specific format
System.out.println(date.format(DateTimeFormatter.ofPattern("d::MMM::uuuu")));
System.out.println(date.format(DateTimeFormatter.BASIC_ISO_DATE)); LocalDateTime dateTime = LocalDateTime.now();
//default format
System.out.println("Default format of LocalDateTime=" + dateTime);
//specific format
System.out.println(dateTime.format(DateTimeFormatter.ofPattern("d::MMM::uuuu HH::mm::ss")));
System.out.println(dateTime.format(DateTimeFormatter.BASIC_ISO_DATE)); Instant timestamp = Instant.now();
//default format
System.out.println("Default format of Instant=" + timestamp); //Parse examples
LocalDateTime dt = LocalDateTime.parse("27::五月::2014 21::39::48",
DateTimeFormatter.ofPattern("d::MMM::uuuu HH::mm::ss"));
System.out.println("Default format after parsing = " + dt);
}

参考

原文链接: journaldev 翻译: ImportNew.com - Justin Wu

译文链接: http://www.importnew.com/14140.html

(转载)Java8新的日期API LocalDate, LocalTime的更多相关文章

  1. JAVA 8 主要新特性 ----------------(七)新时间日期 API -----LocalDate

    一.改版原因 1.老板的Date和Calander存在问题,日期操作名称混乱,有的在text下,有的在util下,包名混乱         2.Simple包混乱,致命错误线程不安全.        ...

  2. Java8新特性(三)——Optional类、接口方法与新时间日期API

    一.Optional容器类 这是一个可以为null的容器对象.如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象. 查看结构图可以看到有如下常用方法: of(T)—— ...

  3. Java--8--新特性--新的日期API

    LocalDate.LocalTime.LocalDateTime 类的实 例是不可变的对象,分别表示使用 ISO-8601日 历系统的日期.时间.日期和时间. Instant 时间戳, 用于“时间戳 ...

  4. Java8简明学习之新时间日期API

    由于历史原因,在之前的版本里无论Date还是Calendar都非常难用,尤其在涉及到日期计算方面,而且其中日期转换的类DateForamt还是非线程安全的.也正因为难用,一般项目里面都引入第三方的类库 ...

  5. Java8新特性--日期和时间API

    如何正确处理时间 现实生活的世界里,时间是不断向前的,如果向前追溯时间的起点,可能是宇宙出生时,又或是是宇宙出现之前, 但肯定是我们目前无法找到的,我们不知道现在距离时间原点的精确距离.所以我们要表示 ...

  6. Java8 新的日期和时间API(笔记)

    LocalDate LocalTime Instant duration以及Period 使用LocalDate和LocalTime //2017-03-20 LocalDate date = Loc ...

  7. 夯实Java基础(十四)——Java8新的日期处理类

    1.前言 Java8之前处理日期一直是Java程序员比较头疼的问题,从Java 8之后,Java里面添加了许多的新特性,其中一个最常见也是最实用的便是日期处理的类——LocalDate.LocalDa ...

  8. 对Java8新的日期时间类的学习(一)

    引用自Java译站http://it.deepinmind.com/java/2015/03/17/20-examples-of-date-and-time-api-from-Java8.html 除 ...

  9. Java8 新特性 Stream() API

    新特性里面为什么要加入流Steam() 集合是Java中使用最多的API,几乎每一个Java程序都会制造和处理集合.集合对于很多程序都是必须的,但是如果一个集合进行,分组,排序,筛选,过滤...这些操 ...

随机推荐

  1. 解决浏览器抛出乱码,(HTML、PHP等的乱码问题)

    在Windows上编写html或php代码的时候,本地编辑器设置的文件编码格式是utf-8保存,但是浏览器打开页面的时候经常出现乱码,而且浏览器自动检测到的页面编码为GBK格式,这时候我就开始纳闷了? ...

  2. 你的java/c/c++程序崩溃了?揭秘段错误(Segmentation fault)(3)

    前言 接上两篇: 你的C/C++程序为什么无法运行?揭秘Segmentation fault (1) 你的C/C++程序为什么无法运行?揭秘Segmentation fault (2) 写到这里,越跟 ...

  3. 2018 dnc .NET Core、.NET开发的大型网站列表、各大公司.NET职位精选,C#王者归来

    简洁.优雅.高效的C#语言,神一样的C#创始人Anders Hejlsberg,async/await编译器级异步语法,N年前就有的lambda表达式,.NET Native媲美C++的原生编译性能, ...

  4. Bugzilla Error message: couldn't create child process: 720003: index.cgi

    two steps is try to fix this issue. 1. Turn off the windowns firewall 2. Register the perl to the sy ...

  5. tomcat点击startup.bat一闪而退的方法

    摘要 在摸索tomcat的配置的时候,发现在启动tomcat服务器的时候,点击startup一闪而退. 解决办法 分析闪退原因,简单做法,右键编辑startup.bat文件,在最后一行添加“pause ...

  6. read(10, "NTP0 13690\n", 64) 数据库登录缓慢

    初步怀疑:下面两个參数引起: SQL> conn / as sysdba Connected. SQL> show parameter lock NAME ---------------- ...

  7. 一个button导致的慘案

    Win8名存实亡,Win9未出已亡.Win10会如何呢? 微软于2014年北京时间10月1日凌晨在旧金山召开新品公布会,之前盛传所谓的"windows 9"变成了"Win ...

  8. Bootstrap碎语

    这里记录下某段时间Bootstrap的零散碎片. 1.有关Bootstrap的参考网站: ● 官方:http://getbootstrap.com/● 主题:http://bootswatch.com ...

  9. 在ASP.NET MVC中使用Castle Windsor

    平常用Inject比较多,今天接触到了Castle Windsor.本篇就来体验其在ASP.NET MVC中的应用过程. Visual Studio 2012创建一个ASP.NET MVC 4网站. ...

  10. 完美.PCK文件不完全详解

    building.pck:建筑物 configs.pck:配置文件interface.pck:玩过魔兽的都晓得这个是什么~interface顾名思义·facedata.pck,人物脸型,细节.不要改, ...