[Java] Java 8 DateTime ใหม่ ไฉไลกว่าเดิม

Hi, I'm Duke.

          Java 8 นอกจาก lambda expression ที่สร้างความโกลาหลให้กับชีวิต Java Programmer ที่เป็นมือใหม่ในวงการ functional language แล้ว ยังมีการปรับปรุง library เกี่ยวกับ Date, Time ด้วย

เปลี่ยน package ในการใช้งาน เพื่อป้องกันการสับสน

(ก่อนหน้านี้จะมี java.sql.Date กับ java.util.Date ให้งงเล่นๆ)
java.util.Date;
java.time.*;
เราเคยเจ็บปวดกับ date, time กันมาพอสมควร ถึงเวลาแล้วที่ Java จะช่วยให้ชีวิตเราดีขึ้น โดย... แยก class ซะเลย
LocalDate
LocalTime
LocalDateTime
ดูชื่อทั้ง 3 ตัวแล้วคงไม่ต้องเล่าอะไรมาก Date มีแค่วันที่ Time มีแค่เวลา ถ้าสนใจทั้งวันและเวลาก็เอา DateTime ไปใช้ ส่วนที่ต้อง Local เพราะมี Zoned อยู่ด้านล่างพร้อมคำอธิบายครับ

การดึงวันเวลาปัจจุบันก็ถูกทำให้เข้าใจมากขึ้น ไม่ใช่ new Date() อีกต่อไป
LocalDate.now() //2016-11-19
LocalTime.now() //20:00:01.635
LocalDateTime.now() //2016-11-19T20:00:01.635

การสร้าง object date,time โดยระบุค่าเอง

LocalDate.of(int year, Month month, int dayOfMonth);
LocalTime.of(int hour, int minute, int second, int nanoOfSecond);
LocalDateTime.of(int year, Month month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond);

Month เป็น enum ถูกสร้างมาเพื่อให้อ่านง่ายขึ้น แทน Calendar ที่เป็น zero-based ไม่ต้องมา +1 -1 อีกต่อไปแล้ว มาลองเข้าไปดูความแตกต่างของ code กัน
  //java.util.Calendar (Legacy way)
  public final static int JANUARY = 0;

  //java.time.Month (Java 8)
  public int getValue() {
    return ordinal() + 1;
  }
สังเกตว่า Month จะสามารถนำไปใช้ได้ make sense กว่า เพราะเดือนจะตรงกับรูปแบบที่เข้าใจได้จริง คือเป็น 1 - 12 ไม่ใช่ 0 - 11

java.time.DateTimeException
          นอกจากนี้ยังมีการทำ Exception มาให้ด้วย ซึ่งร่ำลือกันว่ามันทำให้อ่านได้รู้เรื่องกว่าเดิมมาก ของเก่าอาจแปลงค่าผิด หรือทำให้เกิด RuntimeException ไปเลย

Manipulating

          ผมคงไม่พูดถึงการยุ่งกับ object date,time แบบเก่า เพราะมันช่างวุ่นวายเหลือเกิน ไหน Calendar ไหนจะ Date แปลงไปแปลงมา วันนี้ Java 8 เตรียม method เกี่ยวกับการเพิ่มลบวันมาให้แล้ว และมันถูกออกแบบมาให้ทำ channing methods ได้ (Mutable)
  plusYears
  minusYears
  plusMonths
  minusMonths
  ....
  ..
  minusNanos


Period & Duration

          manipulating ไม่ได้ทำเพียงแค่จาก class ตัวเองเพียงอย่างเดียว ยังมี Period และ Duration มาช่วยอีก เพื่อเพิ่มความยืดหยุ่นให้กับการเล่น date, time

Period period = Period.between(LocalDate.now().plusDays(40), LocalDate.now());
System.out.println(period); //P-1Y-1M-5D
Duration duration = Duration.between(LocalDateTime.now().plusSeconds(70), LocalDateTime.now());

System.out.println(duration); //PT-1M-10S
          ทั้งสองตัวมีความแตกต่างกัน Period ใช้กับวัน Duration ใช้กับเวลา ซึ่งผลจากตัวอย่างด้านบนพอทำให้เห็นได้ว่าจะเป็นรูปย่อของวันเวลาที่ต่างกัน แล้วยังเอาไป plus/minus โดยใช้ Period ได้ด้วย แต่การเอาไปใช้ไม่ใช่ตัด String ตามที่ print ด้านบนแน่ ๆ

Formatting & Parsing

          การปรับปรุงเรื่อง Formatter จะใช้ class DateTimeFormatter เพียงอย่างเดียว และยังมี pattern style ที่เตรียมมาให้บ้าง

การแปลงการ date ให้เป็น string (Formatting)
//using prepared pattern
DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
DateTimeFormatter timeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM);
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
dateFormatter.format(LocalDate.now());
timeFormatter.format(LocalTime.now());
dateTimeFormatter.format(LocalDateTime.now());

//using pattern
DateTimeFormatter patternFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
System.out.println(patternFormatter.format(LocalDateTime.now()));
การแปลงจาก string ให้เป็น date (Parsing)
LocalDate date = LocalDate.parse("19/11/2016", formatter);
LocalTime time = LocalTime.parse("20:00");

นอกจากนี้ยังมี Chronology เพื่อให้เราสามารถเล่นกับปีพ.ศ. ปีค.ศ. ได้โดยที่ไม่ต้องเสี่ยงเจอบั๊กด้วยวิธี +543 อีกแล้ว
LocalDate date = LocalDate.of(2016,11,19);
DateTimeFormatter toThai = DateTimeFormatter.ofPattern("dd-MM-yyyy")
  .withChronology(ThaiBuddhistChronology.INSTANCE);

System.out.println(toThai.format(date)); //19-11-2559

          ZonedDateTime ยกมาพูดทีหลังเพราะ date,time library ใน Java 8 แนะนำให้หลีกเลี่ยงการเล่นกับ timezone ถ้าจำเป็นต้องใช้จริงๆ ZonedDateTime ตัวนี้คือทางออกที่ Java เตรียมไว้ให้ โดยที่ตัวอื่นๆ ด้านบนนั้นจะไม่มี method เกี่ยวกับ timezone เลย ตัวอย่างที่ชัดที่สุด คือ นาฬิการที่แสดงเวลาประเทศต่าง ๆ access_timeaccess_timeaccess_time


          ...จบแล้ว สำหรับ Date & Time ใน Java 8 อันที่จริงของเก่ายังไม่ deprecate ก็ยังใช้ต่อไปได้ไม่มีปัญหา(ไม่มีขีดฆ่า ณ ตอนนี้) มือใหม่มือเก่าอยากลองก็ไปลองใช้กัน ส่วนถ้าเขียนเว็บอย่าลืมเช็ค appserv ด้วยว่ารองรับหรือยังนะครับ

Facebook Comment

Popular post of 7 days

[Java] ความแตกต่างระหว่าง Overloading กับ Overriding

ลืมรหัสปลดล็อค Android เข้าเครื่องไม่ได้ มีทางออกครับ

[Android] เปิดเครื่องไม่ได้ โลโก้ค้าง (Boot Loop)