天天看点

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