天天看點

Java8的日期API——joda time

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類,但他們同樣存在上述所有的問題。

Java8日期/時間API包含以下相應的包:

  • java.time包:這是新的Java日期/時間API的基礎包,所有的主要基礎類都是這個包的一部分,如:LocalDate,LocalTime,LocalDateTime,Instant,Period,Duration等等。所有這些類都是不可變的和線程安全的,在絕大多數情況下,這些類能夠有效地處理一些公共的需求。
  • java.time.chrono包:這個包為非ISO的月曆系統定義了一些泛化的API,我們可以擴充AbstractChronology類來建立自己的月曆系統。
  • java.time.format包:這個包包含能夠格式化和解析日期時間對象的類,在絕大多數情況下,我們不應該直接使用它們,因為java.time包中相應的類已經提供了格式化和解析的方法。
  • java.time.temporal包:這個包包含一些時态對象,我們可以用其找出關于日期/時間對象的某個特定日期或時間,比如說,可以找到某月的第一天或最後一天。你可以非常容易地認出這些方法,因為它們都具有“withXXX”的格式。
  • java.time.zone包:這個包包含支援不同時區以及相關規則的類。

Java8日期時間的預設格式如下:yyyy-MM-dd-HH-mm-ss.zzz

幾個主要的核心類:

  • LocalDate:日期類
  • LocalTime:時間類
  • LocalDateTime:日期時間類
  • ZonedDateTime:時區日期時間類
  • OffsetDateTime:按UTC時間偏移來得到日期時間
  • Instant:Unix時間
  • Duration:兩個時間之間
  • Period:兩個日期之間
  • ZoneId:時區
  • DateTimeFormatter:格式化輸出
  • TemporalAdjusters:獲得指定日期時間等,如當月的第一天、今年的最後一天等等
//相容老API,Instant類是橋梁
@Test
public void testCompatibility() {
	Date dt = Date.from(Instant.now()); 
	Instant timestamp = new Date().toInstant();
	LocalDateTime date = LocalDateTime.ofInstant(timestamp, ZoneId.of(ZoneId.SHORT_IDS.get("PST")));
	Instant time = Calendar.getInstance().toInstant();
	ZoneId defaultZone = TimeZone.getDefault().toZoneId();
	TimeZone tz = TimeZone.getTimeZone(defaultZone);
	ZonedDateTime gregorianCalendarDateTime = new GregorianCalendar().toZonedDateTime();
	System.out.println(gregorianCalendarDateTime);
}

@Ignore
@Test
public void testFormat() {
	LocalDate date = LocalDate.now();
	System.out.println(date.format(DateTimeFormatter.ofPattern("d::MMM::uuuu")));
	System.out.println(date.format(DateTimeFormatter.BASIC_ISO_DATE));

	LocalDateTime dateTime = LocalDateTime.now();
	System.out.println(dateTime.format(DateTimeFormatter.ofPattern("d::MMM::uuuu HH::mm::ss")));
	System.out.println(dateTime.format(DateTimeFormatter.BASIC_ISO_DATE));

	LocalDateTime dt = LocalDateTime.parse("27::4::2014 21::39::48",
			DateTimeFormatter.ofPattern("d::M::uuuu HH::mm::ss"));
	System.out.println("Default format after parsing = " + dt);
}

@Ignore
@Test
public void testDateApi() {
	LocalDate today = LocalDate.now();

	System.out.println("Year " + today.getYear() + " is Leap Year? " + today.isLeapYear());
	System.out.println("Today is before 01/01/2015? " + today.isBefore(LocalDate.of(, , )));
	System.out.println("Current Time=" + today.atTime(LocalTime.now()));

	System.out.println("10 days after today will be " + today.plusDays());
	System.out.println("3 weeks after today will be " + today.plusWeeks());
	System.out.println("20 months after today will be " + today.plusMonths());
	System.out.println("10 days before today will be " + today.minusDays());
	System.out.println("3 weeks before today will be " + today.minusWeeks());
	System.out.println("20 months before today will be " + today.minusMonths());

	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());
}

@Ignore
@Test
public void testInstant() {
	Instant timestamp = Instant.now();
	System.out.println("Current Timestamp = " + timestamp);
	System.out.println(timestamp.toEpochMilli());
	Instant specificTime = Instant.ofEpochMilli(timestamp.toEpochMilli());
	System.out.println("Specific Time = " + specificTime);

	Duration thirtyDay = Duration.ofDays();
	System.out.println(thirtyDay);
}

@Ignore
@Test
public void testDateTime() {
	LocalDateTime today = LocalDateTime.now();
	System.out.println("Current DateTime=" + today);

	today = LocalDateTime.of(LocalDate.now(), LocalTime.now());
	System.out.println("Current DateTime=" + today);

	LocalDateTime specificDate = LocalDateTime.of(, Month.JANUARY, , , , );
	System.out.println("Specific Date=" + specificDate);

	LocalDateTime todayKolkata = LocalDateTime.now(ZoneId.of("Asia/Kolkata"));
	System.out.println("Current Date in IST=" + todayKolkata);

	LocalDateTime dateFromBase = LocalDateTime.ofEpochSecond(, , ZoneOffset.UTC);
	System.out.println("10000th second time from 01/01/1970= " + dateFromBase);
}

@Ignore
@Test
public void testTime() {
	LocalTime time = LocalTime.now();
	System.out.println("Current Time=" + time);

	LocalTime specificTime = LocalTime.of(, , , );
	System.out.println("Specific Time of Day=" + specificTime);

	LocalTime timeKolkata = LocalTime.now(ZoneId.of("Asia/Kolkata"));
	System.out.println("Current Time in IST=" + timeKolkata);

	LocalTime specificSecondTime = LocalTime.ofSecondOfDay();
	System.out.println("10000th second time= " + specificSecondTime);
}

@Ignore
@Test
public void testDate() {
	LocalDate today = LocalDate.now();
	System.out.println("Current Date=" + today);

	LocalDate firstDay_2014 = LocalDate.of(, Month.JANUARY, );
	System.out.println("Specific Date=" + firstDay_2014);

	LocalDate todayKolkata = LocalDate.now(ZoneId.of("Asia/Kolkata"));
	System.out.println("Current Date in IST=" + todayKolkata);

	LocalDate dateFromBase = LocalDate.ofEpochDay();
	System.out.println("365th day from base date= " + dateFromBase);

	LocalDate hundredDay2014 = LocalDate.ofYearDay(, );
	System.out.println("100th day of 2014=" + hundredDay2014);
}