Viblo Learning
+1

Java 8 Date and Time API

Chào mọi người hôm nay mình chia sẻ với mọi người vài điều cơ bản về Java 8 Date and Time API, một vài so sánh so với Date API hiện tại. Từ đó phân tích thấy được những lợi ích của Java 8 Date/Time APIs.

I. Date/Time API hiện tại

Đầu tiên là một ví dụ đơn giản như thế này :

		System.out.println(new Date(12, 12, 12));

Vấn đề ở đây là gì:

  • Số 12 nào ở đây là ngày/tháng/năm?
  • 12 có phải là tháng 12 ko? Ko, nó là tháng 1
  • Vậy 12 là năm thứ 12? Ko, nó lại là nằm 1913
  • Đây có phải là time trong 1 ngày?

Chúng ta có thể thấy API Date cũ có 1 vài vấn đề khá rõ ràng như:

  • Date thực ra là DateTime
  • Input param có random offset
    • Month/Hour bắt đầu từ 0
    • Ngày bắt đầu từ 1
    • Năm được cộng với 1900
  • Mutable, not thread-safe
  • Không phản ánh được UTC, cũng như timezone
  • Mặc dù đã có thêm Calendar nhưng thực tế vẫn còn tồn đọng nhiều vấn đề vẫn chưa thể giải quyết được như: các operation giữa year/month/day khá khó khăn, khó để convert qua lại giữa Date, Calendar, GregorianCalendar,...

Phần kế tiếp ta sẽ cùng tìm hiểu về Java 8 Date/Time ,để kết luận xem APIs mới này có giải quyết được những thiếu sót của Date hiện tại hay không.

II. Java 8 Date and Time API

**1.**Được phát triển dựa trên joda-time library, release vào package java.time của Java 8. Quay trở lại với ví dụ đơn giản như ở Date API, với Java 8 ta sẽ dùng như sau:

System.out.println(LocalDate.of(12, 12, 12));

Kết quả trả về của ví dụ trên sẽ là như sau :

0012-12-12

=> API clearly, ngày tháng năm rất rõ ràng, ko time components, ko time-zone

**2.**Giới thiệu một vài class hay dùng của Java 8 Date/Time:

  • LocalDate:
    • Tạo ra 1 instance của date theo tiêu chuẩn ISO 8601, ko time, ko timezone.
    • Thường được dùng khi tạo birthday, employee's hire date, ...
  • LocalTime:
    • Tạo ra 1 instance của time theo tiêu chuẩn ISO 8601, ko date, ko timezone.
    • Thường dùng cho alarm, cron job, ...
  • LocalDateTime: Nó bao gồm cả 2 API trên, tạo ra instance chứa cả date, time và ko có timezone.

Ngoài ra còn khá nhiều class phù hợp cho từng case khi sử dụng, chi tiết và ví dụ về output như hình dưới:

Untitled.jpg

**3.**Một vài ví dụ:

**a) New instance các kiểu date/time: ** Java8 support nhiều khái niệm để ta có thể dễ dàng tạo Date/Time/DateTime có hoặc không có timezone, phân loại theo mục đích sử dụng.

System.out.println(LocalDate.of(2016, 12, 12));
System.out.println(LocalTime.of(12, 12, 12));
System.out.println(LocalDateTime.of(2016, 12, 12, 12, 12, 12));
System.out.println(ZonedDateTime.of(LocalDate.of(2016, 12, 12),
LocalTime.of(12, 12, 12), ZoneId.of("Asia/Tokyo")));

Output
2016-12-12
12:12:12
2016-12-12T12:12:12
2016-12-12T12:12:12+09:00[Asia/Tokyo]

**b) Check same date: ** Kiểm tra 2 ngày có bằng nhau hay không rất đơn giản như thế này:

 LocalDate today = LocalDate.now();
    LocalDate date1 = LocalDate.of(2016, 10, 15);
    if(date1.equals(today)){
        System.out.printf("Today %s and date1 %s are same date %n", today, date1);
    }
    Output
    Today 2016-10-15 and date1 2016-10-15 are same date

**c) Add hour: ** Ví dụ về add hour(s), tương tự cho add day(s), month(s), year(s)

LocalTime time = LocalTime.now(); LocalTime newTime = time.plusHours(2);
System.out.println("Time after 2 hours : " + newTime);
Output : Time after 2 hours : 18:33:33.369

**d) Check if a date is before or after another date: **

Rất đơn giản và dễ dàng với Java8 phải ko mọi người 😃


LocalDate tomorrow = LocalDate.of(2014, 1, 15); if(tommorow.isAfter(today)){
    System.out.println("Tomorrow comes after today");
}
LocalDate yesterday = today.minus(1, DAYS);
if(yesterday.isBefore(today)){
    System.out.println("Yesterday is day before today");
}

Output:
Tomorrow comes after today
Yesterday is day before today

**e) Check a leap year: ** Bạn đã từng khổ sở khi kiểm tra năm nhuần trước đây? Giờ mọi việc đơn giản hơn với API này nhé.

LocalDate today = LocalDate.now();
if(today.isLeapYear()){
    System.out.println("This year is Leap year");
}else {
    System.out.println("2016 is not a Leap year");
}

Output: This year is Leap year

**f) Parsing/Format examples: **

Parsing Date từ String

String dayAfterTommorrow = "20161016";
LocalDate formatted = LocalDate.parse(dayAfterTommorrow, DateTimeFormatter.BASIC_ISO_DATE);
System.out.printf("Date generated from String %s is %s %n", dayAfterTommorrow, formatted);

Output : Date generated from String 20161016 is 2016-10-16

Parsing Date từ một String theo format khác

String goodFriday = "Oct 14 2016";
try {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd yyyy");
    LocalDate holiday = LocalDate.parse(goodFriday, formatter);
    System.out.printf("Successfully parsed String %s, date is %s%n", goodFriday, holiday);
} catch (DateTimeParseException ex) {
    System.out.printf("%s is not parsable!%n", goodFriday);
    ex.printStackTrace();
}

Output : Successfully parsed String Oct 14 2016, date is 2016-10-14

Format từ chuẩn Date này sang chuẩn Date khác

LocalDateTime arrivalDate = LocalDateTime.now();
try {
    DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy hh:mm a");
    String landing = arrivalDate.format(format);
    System.out.printf("Arriving at : %s %n", landing);
} catch (DateTimeException ex) {
    System.out.printf("%s can't be formatted!%n", arrivalDate);
    ex.printStackTrace();
}

Output : Arriving at : Oct 15 2016 04:33 PM

Tóm lại: Java8 Date/Time API rất dễ sử dụng, phù hợp cho nhiều mục đích khác nhau, khá nhiều API hữu dụng. Nếu là một Java dev và đang sử dụng những API này, keep going on nhé 😉, nếu chưa bạn nên học cách sử dụng ngay từ bây giờ.


All Rights Reserved