[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

Recent Posts

Popular post of 7 days

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

Portal คืออะไรกันนะ???

Port Forwarding สำหรับคนใช้ AIS Fibre

Popular

Portal คืออะไรกันนะ???

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

มาตรฐานการตั้งชื่อตัวแปร (Naming Convention)

เรื่องของ ++i กับ i++

Port Forwarding สำหรับคนใช้ AIS Fibre

วิธีการสมัคร Apple Developer Program และ Enterprise Program ฉบับลงมือเอง

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

ทดสอบ Mobile App แบบ Automated ด้วย Appium ทำยังไงกันนะ

Deeplink, Universal Links คืออะไร ทำงานร่วมกับ Mobile App ได้ยังไง

Android Auto & Apple Carplay คืออะไร ใช้งานยังไง