无涯教程-Java8 - Date/Time API

71 阅读5分钟

在Java8中,引入了一个新的Date-Time API来弥补旧Date-Time API的以下缺点。

  • Not thread safe                         - java.util.Date不是线程安全的。

  • Poor design                               - 默认日期从1900年开始,因此不一致。

  • Difficult time zone handling  - 开发人员必须编写大量代码来处理时区问题。

Java8在java.time包下引入了一个新的日期-时间API。下面是java.time包中引入的一些重要类。

  • Local(本地)   - 简化了日期时间的处理,没有时区的问题。

  • Zoned(时区) - 通过制定的时区处理日期时间。

本地化API

LocalDate/localtime和LocalDateTime类简化了不需要时区的开发。

使用您选择的任何编辑器创建以下Java程序,例如,C:\> JAVA.

Java8Tester.java

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
import java.time.Month;

public class Java8Tester {

public static void main(String args[]) { Java8Tester java8tester=new Java8Tester(); java8tester.testLocalDateTime(); }

public void testLocalDateTime() { //获取当前日期和时间 LocalDateTime currentTime=LocalDateTime.now(); System.out.println("Current DateTime: " + currentTime);

  </span><span class="typ">LocalDate</span><span class="pln"> date1</span><span class="pun">=</span><span class="pln">currentTime</span><span class="pun">.</span><span class="pln">toLocalDate</span><span class="pun">();</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"date1: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> date1</span><span class="pun">);</span><span class="pln">
	
  </span><span class="typ">Month</span><span class="pln"> month</span><span class="pun">=</span><span class="pln">currentTime</span><span class="pun">.</span><span class="pln">getMonth</span><span class="pun">();</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> day</span><span class="pun">=</span><span class="pln">currentTime</span><span class="pun">.</span><span class="pln">getDayOfMonth</span><span class="pun">();</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> seconds</span><span class="pun">=</span><span class="pln">currentTime</span><span class="pun">.</span><span class="pln">getSecond</span><span class="pun">();</span><span class="pln">
	
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Month: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> month </span><span class="pun">+</span><span class="str">"day: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> day </span><span class="pun">+</span><span class="str">"seconds: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> seconds</span><span class="pun">);</span><span class="pln">
	
  </span><span class="typ">LocalDateTime</span><span class="pln"> date2</span><span class="pun">=</span><span class="pln">currentTime</span><span class="pun">.</span><span class="pln">withDayOfMonth</span><span class="pun">(</span><span class="lit">10</span><span class="pun">).</span><span class="pln">withYear</span><span class="pun">(</span><span class="lit">2012</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"date2: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> date2</span><span class="pun">);</span><span class="pln">
	
  </span><span class="com">//2014年12月12日</span><span class="pln">
  </span><span class="typ">LocalDate</span><span class="pln"> date3</span><span class="pun">=</span><span class="typ">LocalDate</span><span class="pun">.</span><span class="kwd">of</span><span class="pun">(</span><span class="lit">2014</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Month</span><span class="pun">.</span><span class="pln">DECEMBER</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"date3: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> date3</span><span class="pun">);</span><span class="pln">
	
  </span><span class="com">//22小时15分钟</span><span class="pln">
  </span><span class="typ">LocalTime</span><span class="pln"> date4</span><span class="pun">=</span><span class="typ">LocalTime</span><span class="pun">.</span><span class="kwd">of</span><span class="pun">(</span><span class="lit">22</span><span class="pun">,</span><span class="pln"> </span><span class="lit">15</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"date4: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> date4</span><span class="pun">);</span><span class="pln">
	
  </span><span class="com">//解析一个字符串</span><span class="pln">
  </span><span class="typ">LocalTime</span><span class="pln"> date5</span><span class="pun">=</span><span class="typ">LocalTime</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="str">"20:15:30"</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"date5: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> date5</span><span class="pun">);</span><span class="pln">

} }

使用javac编译器编译类,如下所示-

C:\JAVA>javac Java8Tester.java

现在运行Java8Tester,如下所示-

C:\JAVA>java Java8Tester

它应该生成以下输出-

Current DateTime: 2014-12-09T11:00:45.457
date1: 2014-12-09
Month: DECEMBERday: 9seconds: 45
date2: 2012-12-10T11:00:45.457
date3: 2014-12-12
date4: 22:15
date5: 20:15:30

时区API

如果无涯教程需要考虑到时区,就可以使用时区的日期时间API:

Java8Tester.java

import java.time.ZonedDateTime;
import java.time.ZoneId;

public class Java8Tester {

public static void main(String args[]) { Java8Tester java8tester=new Java8Tester(); java8tester.testZonedDateTime(); }

public void testZonedDateTime() { //获取当前日期和时间 ZonedDateTime date1=ZonedDateTime.parse("2007-12-03T10:15:30+05:30[Asia/Karachi]"); System.out.println("date1: " + date1);

  </span><span class="typ">ZoneId</span><span class="pln"> id</span><span class="pun">=</span><span class="typ">ZoneId</span><span class="pun">.</span><span class="kwd">of</span><span class="pun">(</span><span class="str">"Europe/Paris"</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"ZoneId: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> id</span><span class="pun">);</span><span class="pln">
	
  </span><span class="typ">ZoneId</span><span class="pln"> currentZone</span><span class="pun">=</span><span class="typ">ZoneId</span><span class="pun">.</span><span class="pln">systemDefault</span><span class="pun">();</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"CurrentZone: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> currentZone</span><span class="pun">);</span><span class="pln">

} }

使用javac编译器编译类,如下所示-

C:\JAVA>javac Java8Tester.java

现在运行Java8Tester,如下所示-

C:\JAVA>java Java8Tester

它应该生成以下输出-

date1: 2007-12-03T10:15:30+05:00[Asia/Karachi]
ZoneId: Europe/Paris
CurrentZone: Etc/UTC

ChronoUnits枚举

在Java8中添加了java.time.Temporal.ChronoUnit枚举,以替换旧API中使用的整数值,以表示日、月等。让无涯教程看看它们的实际效果。

使用您选择的任何编辑器创建以下Java程序,例如, C:\> JAVA.

Java8Tester.java

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

public class Java8Tester {

public static void main(String args[]) { Java8Tester java8tester=new Java8Tester(); java8tester.testChromoUnits(); }

public void testChromoUnits() { //获取当前日期 LocalDate today=LocalDate.now(); System.out.println("Current date: " + today);

  </span><span class="com">//往后增加1周的日期</span><span class="pln">
  </span><span class="typ">LocalDate</span><span class="pln"> nextWeek</span><span class="pun">=</span><span class="pln">today</span><span class="pun">.</span><span class="pln">plus</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="typ">ChronoUnit</span><span class="pun">.</span><span class="pln">WEEKS</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Next week: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> nextWeek</span><span class="pun">);</span><span class="pln">
	
  </span><span class="com">//往后增加1个月的日期</span><span class="pln">
  </span><span class="typ">LocalDate</span><span class="pln"> nextMonth</span><span class="pun">=</span><span class="pln">today</span><span class="pun">.</span><span class="pln">plus</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="typ">ChronoUnit</span><span class="pun">.</span><span class="pln">MONTHS</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Next month: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> nextMonth</span><span class="pun">);</span><span class="pln">
	
  </span><span class="com">//往后增加1年的日期</span><span class="pln">
  </span><span class="typ">LocalDate</span><span class="pln"> nextYear</span><span class="pun">=</span><span class="pln">today</span><span class="pun">.</span><span class="pln">plus</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="typ">ChronoUnit</span><span class="pun">.</span><span class="pln">YEARS</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Next year: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> nextYear</span><span class="pun">);</span><span class="pln">
	
  </span><span class="com">//增加10年的日期</span><span class="pln">
  </span><span class="typ">LocalDate</span><span class="pln"> nextDecade</span><span class="pun">=</span><span class="pln">today</span><span class="pun">.</span><span class="pln">plus</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="typ">ChronoUnit</span><span class="pun">.</span><span class="pln">DECADES</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Date after ten year: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> nextDecade</span><span class="pun">);</span><span class="pln">

} }

使用javac编译器编译类,如下所示-

C:\JAVA>javac Java8Tester.java

现在运行Java8Tester,如下所示-

C:\JAVA>java Java8Tester

它应该产生以下输出-

Current date: 2014-12-10
Next week: 2014-12-17
Next month: 2015-01-10
Next year: 2015-12-10
Date after ten year: 2024-12-10

Period和Duration

在Java8中,引入了两个专门的类来处理时间差异。

  • Period      - 它处理基于日期的时间。

  • Duration  - 它处理基于时间的时间。

使用您选择的任何编辑器创建以下Java程序,例如, C:\> JAVA.

Java8Tester.java

import java.time.temporal.ChronoUnit;

import java.time.LocalDate; import java.time.LocalTime; import java.time.Duration; import java.time.Period;

public class Java8Tester {

public static void main(String args[]) { Java8Tester java8tester=new Java8Tester(); java8tester.testPeriod(); java8tester.testDuration(); }

public void testPeriod() { //获取当前日期 LocalDate date1=LocalDate.now(); System.out.println("Current date: " + date1);

  </span><span class="com">//往后增加1个月的日期</span><span class="pln">
  </span><span class="typ">LocalDate</span><span class="pln"> date2</span><span class="pun">=</span><span class="pln">date1</span><span class="pun">.</span><span class="pln">plus</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="typ">ChronoUnit</span><span class="pun">.</span><span class="pln">MONTHS</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Next month: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> date2</span><span class="pun">);</span><span class="pln">
  
  </span><span class="typ">Period</span><span class="pln"> period</span><span class="pun">=</span><span class="typ">Period</span><span class="pun">.</span><span class="pln">between</span><span class="pun">(</span><span class="pln">date2</span><span class="pun">,</span><span class="pln"> date1</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Period: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> period</span><span class="pun">);</span><span class="pln">

}

public void testDuration() { LocalTime time1=LocalTime.now(); Duration twoHours=Duration.ofHours(2);

  </span><span class="typ">LocalTime</span><span class="pln"> time2</span><span class="pun">=</span><span class="pln">time1</span><span class="pun">.</span><span class="pln">plus</span><span class="pun">(</span><span class="pln">twoHours</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">Duration</span><span class="pln"> duration</span><span class="pun">=</span><span class="typ">Duration</span><span class="pun">.</span><span class="pln">between</span><span class="pun">(</span><span class="pln">time1</span><span class="pun">,</span><span class="pln"> time2</span><span class="pun">);</span><span class="pln">
	
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Duration: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> duration</span><span class="pun">);</span><span class="pln">

} }

使用javac编译器编译类,如下所示-

C:\JAVA>javac Java8Tester.java

现在运行Java8Tester,如下所示-

C:\JAVA>java Java8Tester

它应该生成以下输出-

Current date: 2014-12-10
Next month: 2015-01-10
Period: P-1M
Duration: PT2H

时间调节器

使用您选择的任何编辑器创建以下Java程序,例如, C:\> JAVA.

Java8Tester.java

import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.time.DayOfWeek;

public class Java8Tester {

public static void main(String args[]) { Java8Tester java8tester=new Java8Tester(); java8tester.testAdjusters(); }

public void testAdjusters() { //获取当前日期 LocalDate date1=LocalDate.now(); System.out.println("Current date: " + date1);

  </span><span class="com">//得到下一个星期二</span><span class="pln">
  </span><span class="typ">LocalDate</span><span class="pln"> nextTuesday</span><span class="pun">=</span><span class="pln">date1</span><span class="pun">.</span><span class="kwd">with</span><span class="pun">(</span><span class="typ">TemporalAdjusters</span><span class="pun">.</span><span class="kwd">next</span><span class="pun">(</span><span class="typ">DayOfWeek</span><span class="pun">.</span><span class="pln">TUESDAY</span><span class="pun">));</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Next Tuesday on : "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> nextTuesday</span><span class="pun">);</span><span class="pln">
	
  </span><span class="com">//获得下个月的第二个星期六</span><span class="pln">
  </span><span class="typ">LocalDate</span><span class="pln"> firstInYear</span><span class="pun">=</span><span class="typ">LocalDate</span><span class="pun">.</span><span class="kwd">of</span><span class="pun">(</span><span class="pln">date1</span><span class="pun">.</span><span class="pln">getYear</span><span class="pun">(),</span><span class="pln">date1</span><span class="pun">.</span><span class="pln">getMonth</span><span class="pun">(),</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">LocalDate</span><span class="pln"> secondSaturday</span><span class="pun">=</span><span class="pln">firstInYear</span><span class="pun">.</span><span class="kwd">with</span><span class="pun">(</span><span class="typ">TemporalAdjusters</span><span class="pun">.</span><span class="pln">nextOrSame</span><span class="pun">(</span><span class="pln">
     </span><span class="typ">DayOfWeek</span><span class="pun">.</span><span class="pln">SATURDAY</span><span class="pun">)).</span><span class="kwd">with</span><span class="pun">(</span><span class="typ">TemporalAdjusters</span><span class="pun">.</span><span class="kwd">next</span><span class="pun">(</span><span class="typ">DayOfWeek</span><span class="pun">.</span><span class="pln">SATURDAY</span><span class="pun">));</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Second Saturday on : "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> secondSaturday</span><span class="pun">);</span><span class="pln">

} }

使用javac编译器编译类,如下所示-

C:\JAVA>javac Java8Tester.java

现在运行Java8Tester,如下所示-

C:\JAVA>java Java8Tester

它应该产生以下输出-

Current date: 2014-12-10
Next Tuesday on : 2014-12-16
Second Saturday on : 2014-12-13

向后兼容性

TemporalAdjuster用于执行日期数学。 例如,获取“每月的第二个星期六”或“下一个星期二”。 

Java8Tester.java

import java.time.LocalDateTime;
import java.time.ZonedDateTime;

import java.util.Date;

import java.time.Instant; import java.time.ZoneId;

public class Java8Tester {

public static void main(String args[]) { Java8Tester java8tester=new Java8Tester(); java8tester.testBackwardCompatability(); }

public void testBackwardCompatability() { //获取当前日期 Date currentDate=new Date(); System.out.println("Current date: " + currentDate);

  </span><span class="com">//根据毫秒获取当前日期的即时</span><span class="pln">
  </span><span class="typ">Instant</span><span class="pln"> now</span><span class="pun">=</span><span class="pln">currentDate</span><span class="pun">.</span><span class="pln">toInstant</span><span class="pun">();</span><span class="pln">
  </span><span class="typ">ZoneId</span><span class="pln"> currentZone</span><span class="pun">=</span><span class="typ">ZoneId</span><span class="pun">.</span><span class="pln">systemDefault</span><span class="pun">();</span><span class="pln">
	
  </span><span class="typ">LocalDateTime</span><span class="pln"> localDateTime</span><span class="pun">=</span><span class="typ">LocalDateTime</span><span class="pun">.</span><span class="pln">ofInstant</span><span class="pun">(</span><span class="pln">now</span><span class="pun">,</span><span class="pln"> currentZone</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Local date: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> localDateTime</span><span class="pun">);</span><span class="pln">
	
  </span><span class="typ">ZonedDateTime</span><span class="pln"> zonedDateTime</span><span class="pun">=</span><span class="typ">ZonedDateTime</span><span class="pun">.</span><span class="pln">ofInstant</span><span class="pun">(</span><span class="pln">now</span><span class="pun">,</span><span class="pln"> currentZone</span><span class="pun">);</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Zoned date: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> zonedDateTime</span><span class="pun">);</span><span class="pln">

} }

使用javac编译器编译类,如下所示-

C:\JAVA>javac Java8Tester.java

现在运行Java8Tester,如下所示-

C:\JAVA>java Java8Tester

它应该生成以下输出-

Current date: Wed Dec 10 05:44:06 UTC 2014
Local date: 2014-12-10T05:44:06.635
Zoned date: 2014-12-10T05:44:06.635Z[Etc/UTC]

参考链接

www.learnfk.com/java/java8-…