เราได้เคยรู้จักการจัดการวันที่และเวลาใน php ด้วย strtotime() ฟังก์ชั่นไปแล้วในบทความ
ก่อนหน้า เนื้อหานี้ เราจะมาเพิ่มเติมการจัดการวันที่และเวลาด้วยความสามารถของ DateTime
object ที่มีมาให้ใน php
การใช้งานรูปแบบข้อความวันที่และเวลา กับฟังก์ชั่น strtotime() ใน php http://niik.in/800
https://www.ninenik.com/content.php?arti_id=800 via @ninenik
โดยในเนื้อหานี้จะพยายามนำเอาความสามารถและประโยชน์ต่างๆ ที่จะได้รับเมื่อนำมาปรับใช้งาน
ดูเนื้อหาอ้างอิงได้ที่ https://www.php.net/manual/en/book.datetime.php
DateTime class เป็น class ที่เราสามารถใช้ในการจัดการวันที่และเวลา ไม่ว่าจะโดยการส่งค่า
ข้อความ หรือใช้ค่าจากระบบในการสร้างรูปแบบวันที่ขึ้นมาใช้งาน
การจัดการวันที่และเวลาบางกรณีเวลาของ server อาจจะไม่ตรง ซึ่งอาจจะเป็นเพราะการกำหนด
timezone ของระบบ ดังนั้นเราอาจจะต้องกำหนด ค่านี้ไว้ในส่วนบนสุดของไฟล์ php หรืออาจจะ
ตั้งค่าให้ server เพียงครั้งเดียวก็ได้
การกำหนด timezone ในไฟล์ php
<?php date_default_timezone_set('Asia/Bangkok'); echo date("Y-m-d H:i:s");
การกำหนด timezone ด้วยไฟล์ .htaccess
กรณีเราต้องการใช้งานทั้งหมดทุกไฟล์ ก็ให้กำหนดค่าด้านล่างนี้ในไฟล์ .htaccess ที่อยู่ root
public_html แต่กรณีต้องการใช้งานในบาง โฟลเดอร์ หรือ path ก็ให้สร้างไว้ในโฟลเดอร์ที่ต้องการ
php_value date.timezone 'Asia/Bangkok'
การสร้าง DateTime object ใหม่ด้วย DateTime และ DateTimeImmutable
เมื่อเราเริ่มต้นจะใช้งาน DateTime ใน php จะมี 2 รูปแบบให้เรียกใช้ คือแบบ ที่ค่าของตัวมันสามารถ
เปลี่ยนแปลงได้เมื่อถูกเปลี่ยนแปลง DateTime และแบบที่ค่าของมันไม่สามารถเปลี่ยนแปลงได้
DateTimeImmutable ซึ่งทั้งสองรูปแบบมีฟังก์ชั่นหรือ method การใช้งานที่ไม่แตกต่างกันมากนัก
ดูตัวอย่างเปรียบเทียบความแตกต่าง
// ถ้าวันนี้วันที่ 2022-12-27 $date = new DateTime(); echo $date->format('Y-m-d'); // 2022-12-27 $tomorrow = $date->modify('+1 day'); // เมื่อใช้คำสั่งเปลี่ยนแปลงค่า echo $date->format('Y-m-d'); // 2022-12-28 ** มีการเปลี่ยนแปลง echo $tomorrow->format('Y-m-d'); // 2022-12-28
สังเกตว่าตัวแปร $date ซึ่งเป็น DateTime object ที่ถูกสร้างด้วย DateTime() ค่าของมันมีการ
เปลี่ยนแปลงไปด้วย ทำให้หลังเปลี่ยนแปลงค่า $date เท่ากับ $tomorrow
แต่ถ้าเราใช้งาน DateTimeImmutable() จะไม่มีการเปลี่ยนแปลง ดังนี้
$date = new DateTimeImmutable(); echo $date->format('Y-m-d'); // 2022-12-27 $tomorrow = $date->modify('+1 day'); // เมื่อใช้คำสั่งเปลี่ยนแปลงค่า echo $date->format('Y-m-d'); // 2022-12-27 ** ไม่มีการเปลี่ยนแปลง echo $tomorrow->format('Y-m-d'); // 2022-12-28
ดังนั้นการที่เลือกใช้รูปแบบไหน เราต้องตัดสินใจว่า ตัวแปรเริ่มต้นนั้น สามารถเปลี่ยนแปลงได้หรือไม่
แต่ในรูปแบบลักษณะใช้งานในแบบสั้นหรือไม่ต่อเนื้องซับซ้อน รูปแบบธรรมดาก็เพียงพอต่อการใช้งาน
ดังนั้นในที่นี้เราจะใช้รูปแบบ DateTime() ประกอบการอธิบาย
การสร้าง DateTime object
การสร้าง DateTime object ค่าเริ่มต้นจะได้เวลา ณ ปัจจุบัน และ timezone ของระบบ
หากต้องการระบุ timezone เข้าไปด้วยสามารถใช้ค่าต่างๆ นี้แทนได้
ค่า timezone ต่างๆ ดูได้ที่ https://www.php.net/manual/en/timezones.php
$date = new DateTime(); echo $date->format('Y-m-d H:i:s'); // 2022-12-27 12:53:42 $date2 = new DateTime("now", new DateTimeZone("Asia/Shanghai")); echo $date2->format('Y-m-d H:i:s'); // 22022-12-27 13:53:42
ตัวอย่างข้างต้นจะเห็นว่าเวลาที่จีน เร็วกว่าไทย 1 ชั่วโมง
เราสามารถใช้งาน ข้อความ String เกี่ยวกับวันที่ต่างๆ ดูเพิ่ม http://niik.in/800
กำหนดในขั้นตอนการสร้าง DateTime object ได้ ตัวอย่างเช่าน
// ถ้าวันนี้วันที่ 2022-12-27 $date = new DateTime(); //2022-12-27 13:02:02 $date = new DateTime("now"); //2022-12-27 13:02:02 $date = new DateTime("noon +1 day"); //2022-12-28 12:00:00 $date = new DateTime("2022-12-29 +1 day"); //2022-12-30 00:00:00
การใช้งานระยะเวลา ช่วงเวลา ระยะห่างของเวลาด้วย DateInterval
ในการใช้งานเกี่ยวกับเวลา บางครั้งเราจำเป็นต้องมีระยะเวลา ช่วงเวลา หรือระยะห่างของเวลา
มาเกี่ยวข้อง เช่น ใช้ในการหาวันล่วงหน้า เวลาล่วงหน้า วันเวลาที่ผ่านมาแล้ว เหล่านี้ DateInterval
ก็จะเป็นค่าที่เราสามารถนำมาใช้งานได้ โดยจะใช้งานร่วมกับคำสั่งการเพิ่ม หรือการลบเกี่ยวกับวันที่
เช่น add() sub() รูปแบบการใช้งาน DateInterval
$date = new DateTime("2022-12-29"); //2022-12-29 00:00:00 $interval = new DateInterval("P1D"); $date->add($interval); // +1 วัน echo $date->format('Y-m-d H:i:s'); // 2022-12-30 00:00:00 // $date ค่าเปลี่ยนแปลงไปแล้ว ตอนนี้คือ 2022-12-30 $date->sub($interval); // -1 วัน echo $date->format('Y-m-d H:i:s'); // 2022-12-29 00:00:00
ในตัวอย่าง เรากำหนดวันที่เป็น 29 และกำหนดระยะเวลาเป็นรูปแบบ "P1D" (จะอธิบายการใช้งาน
รูปแบบด้านล่างเพิ่มเติม) ซึ่งก็คือ 1 วัน ดังนั้นเมื่อเราเพิ่มระยะเวลาเข้าไปในเวลาที่กำหนด 1 วัน
ด้วยคำสั่ง add() วันใหม่ก็เป็น 30 และเมื่อเราลบเวลาที่กำหนด 1 วัน ด้วยคำสั่ง sub() ก็จะได้
วันใหม่เป็น 29
รูปแบบข้อความที่กำหนดใน DateInterval() เราจะใช้รูปแบบอักษรย่อดังนี้
จะเริ่มต้นด้วยตัว P ตัวใหญ่เสมอ กรณีมีเวลาด้วย จะมีตัว T เพิ่มคั่นกับเวลา โดยมีรูปแบบย่อ ดังนี้
Y - years M - months D - days W - weeks. ก่อน PHP 8.0.0, จะไม่สามารถใช้ร่วมกับตัว D ได้. H - hours M - minutes S - seconds
ตัวอย่างเช่น
1 ปี 3 เดือน 2 วัน 30 นาที ก็จะได้เป็น
"P1Y3M2DT30M"
$date = new DateTime("2022-12-29"); //2022-12-29 00:00:00 $interval = new DateInterval("P1Y3M2DT30M"); $date->add($interval); // +1 ปี 3 เดือน 2 วัน 30 นาที echo $date->format('Y-m-d H:i:s'); // 2024-03-31 00:30:00
5 ชั่วโมง 45 นาที ก็จะได้เป็น
"PT5H45M"
$date = new DateTime("2022-12-29"); //2022-12-29 00:00:00 $interval = new DateInterval("PT5H45M"); $date->add($interval); // +5 ชั่วโมง 45 นาทีี echo $date->format('Y-m-d H:i:s'); // 2022-12-29 05:45:00
เราสามารถแปลงค่า ระยะเวลาของ DateInterval เป็นข้อความตัวเลขข้อมูลที่ต้องการได้ ดังนี้
$interval = new DateInterval("P2YT5H45M"); echo $interval->format("%y ปี %h ชั่วโมง %i นาที"); // 2 ปี 5 ชั่วโมง 45 นาที
การเปลี่ยนแปลงแก้ไขวันที่
การเปลี่ยนแปลงแก้ไขวันที่ไม่ว่าจะเป็นการเพิ่มหรือการลบ นอกจากจะใช้งาน DateInterval ร่วม
กับคำสั่ง add() หรือ sub() แล้ว เรายังสามารถใช้งานคำสั่ง modify() โดยส่งรูปแบบข้อความ
ที่ต้องการเข้าไป เพื่อกำหนดระยะเวลาที่ต้องการได้
$date = new DateTime("2022-12-29"); //2022-12-29 00:00:00 $date->modify("+1 year +3 month +2 day +30 minute"); echo $date->format('Y-m-d H:i:s'); // 2024-03-31 00:30:00
จะเห็นว่าเราสามารถกำหนด เครื่องหมาย + สำหรับการเพิ่ม และเครื่องหมาย - สำหรับการลบเวลา
ข้อความ String เกี่ยวกับวันที่ต่างๆ ดูเพิ่ม http://niik.in/800
การจัดการวันที่ 2 วันที่ หรือ ระหว่างวันที่ ด้วย DateTime
ใน DateTime object เราสามารถหาระยะห่างของเวลา 2 เวลาด้วยคำสั่ง diff()
$originalTime = new DateTime(); $targedTime = new DateTime("1999-07-20"); echo $originalTime->format('Y-m-d H:i:s'); // 2022-12-27 15:06:33 echo $targedTime->format('Y-m-d H:i:s'); // 1999-07-20 00:00:00 $interval = $originalTime->diff($targedTime); echo $interval->format("%R %y %m %d %h %i %s %a"); // - 23 5 7 15 8 37 8561 // %R สำหรับหาว่าค่าในคำสั่ง diff() หรือค่า target เป็น + หรือ - ถ้า - คือน้อยกว่าอีกค่า // ถ้าเป็น + คือมากกว่าอีกค่า สามารถใช้ %r แทนก็ได้กรณีค่ามากกว่าไม่ต้องแสดงเครื่องหมาย + // สำหรับ %a จะหมายถึงค่าระยะเวลาทั้งหมด คิดเป็นวัน อย่างข้างต้นก็คือ 8561 วัน // ส่วนค่าอื่นๆ ก็จะเป็น ปี เดือน วัน ชั่วโมง นาที วินาที ที่ต่างกัน
เราลองมาทดสอบหาค่าง่ายๆ เช่น ห่างกันแค่ 1 วันดูว่าจะเป็นในลักษณะใด
$originalTime = new DateTime("2022-12-27"); $targedTime = new DateTime("2022-12-28"); echo $originalTime->format('Y-m-d H:i:s'); // 2022-12-27 00:00:00 echo $targedTime->format('Y-m-d H:i:s'); // 2022-12-28 00:00:00 $interval = $originalTime->diff($targedTime); echo $interval->format("%R %y %m %d %h %i %s %a"); //+ 0 0 1 0 0 0 1 // ค่า target มากกว่า 1 วัน
เราสามารถประยุกต์หาอายุ อย่างง่ายได้ดังนี้
$originalTime = new DateTime("now midnight"); $targedTime = new DateTime("1999-07-20 midnight"); echo $originalTime->format('Y-m-d H:i:s'); // 2022-12-27 00:00:00 echo $targedTime->format('Y-m-d H:i:s'); // 1999-07-20 00:00:00 $interval = $originalTime->diff($targedTime); echo $interval->format("อายุ %y ปี %m เดือน %d วัน"); //อายุ 23 ปี 5 เดือน 7 วัน
การสร้างชุดข้อมูลช่วงวันที่หรือเวลาด้วย DatePeriod
กรณีที่เราต้องการชุดข้อมูลช่วงเวลาสำหรับไปใช้งานหรือแสดง เช่น สร้างเป็นลิสรายการวันที่
ของเดือนใดๆ ก็สามารถใช้ DatePeriod ได้ดังนี้
$start = new DateTime('first day of this month midnight'); $end = new DateTime('first day of next month midnight'); echo $start->format('Y-m-d H:i:s'); // 2022-12-01 00:00:00 echo $end->format('Y-m-d H:i:s'); // 2023-01-01 00:00:00 $interval = new DateInterval('P1D'); // ระยะเวลาห่างกัน 1 วัน $period = new DatePeriod($start, $interval, $end); foreach ($period as $dt) { echo $dt->format("Y-m-d")."<br>"; } // วนลูปแสดงวันที่ 1 ถึงวันสิ้นเดือนของเดือนปัจจุบัน // เนื่องจากรูปแบบการใช้งานข้างต้นใน PHP ที่ไม่ใช่เวอร์ชั่นที่ 8.2 จะไม่มี // DatePeriod::INCLUDE_END_DATE หรือไม่รวมวันที่สุดท้ายในค่าเริ่มต้น // การกำหนดวันสุดท้ายของเดือน จึงใช้เป็นการกำหนดวันแรกของเดือนถัดไปแทน เพื่อ // ให้รวมวันสุดท้ายของเดือนเข้ามาด้วย // กรณีเป็น PHP เวอร์ชั่น 8.2 เราสามารถกำหนดแบบนี้แทนได้ $start = new DateTime('first day of this month midnight'); $end = new DateTime('last day of this month midnight'); echo $start->format('Y-m-d H:i:s'); // 2022-12-01 00:00:00 echo $end->format('Y-m-d H:i:s'); // 2022-12-31 00:00:00 $interval = new DateInterval('P1D'); // ระยะเวลาห่างกัน 1 วัน $period = new DatePeriod($start, $interval, $end, DatePeriod::INCLUDE_END_DATE);
เราสามารถใช้งาน DatePeriod โดยแทนที่จะกำหนด วันสิ้นสุดหรือ $end ก็กำหนดเป็นจำนวนครั้งของ
การทำซ้ำ หรือที่เรียกว่า recurrences แทนได้ สมมติเช่น เราต้องการแสดงเดือน ทุกเดือนในปีนี้ หรือก็
คือต้องการแสดงวันที่ 1 ของทุกเดือน ให้เลือก ก็กำหนดวันเริ่มต้นเป็นวันที่ 1 และเป็นค่าวันที่ที่เราจะใช้
จากนั้นเรากำหนดระยะเวลาทำซ้ำเป็น ทุกๆ 1 เดือน และสุดท้ายกำหนดจำนวนที่ทำซ้ำ เนื่องจาก เรามีค่า
แรกแล้วดังนั้น 12 เดือน เราต้องทำซ้ำอีกทั้งหมด 11 ครั้ง ก็จะได้เป็นดังนี้
$start = new DateTime('first day of january midnight'); echo $start->format('Y-m-d H:i:s'); // 2022-01-01 00:00:00 $interval = new DateInterval('P1M'); // ระยะเวลา 1 เดือน $recurrences = 11; // ทำซ้ำ 11 ครั้ง $period = new DatePeriod($start, $interval, $recurrences); foreach ($period as $dt) { echo $dt->format("Y-m")."<br>"; } // ผลลัพธ์เราก็ไจะได้วันที่ 1 ของแต่ละเดือน ในปีนั้นๆ มาใช้งานได้ // ถ้าต้องการแสดงแค่ 3 เดือน 6 เดือน 9 เดือน ก็แค่เปลี่ยนตัวเลขจำนวนการทำซ้ำ ตามต้องการ // ข้อสังเกต ระยะเวลาที่กำหนดด้วย "P1M" ระบบจะพิจารณาตามวันที่จริง เพราะข้อมูลช่วงของ // วันที่จะต้องเป็นช่วงเวลาจริงๆ แต่ถ้าเราต้องการ วันที่ตามจำนวนวัน เช่น กรณี กำหนดผ่อนชำระ // ทุกๆ 30 วัน และกำหนดเป็น "P30D" ค่าที่ได้จะนับเป็นวัน บางเดือนอาจจะมี 2 ค่าก็ได้ เช่น // วันที่ 1 และอีก 30 วันก็เป็นวันที่ 31 ดูตัวอย่างด้านล่าง $start = new DateTime('first day of january midnight'); echo $start->format('Y-m-d H:i:s'); // 2022-01-01 00:00:00 $interval = new DateInterval('P30D'); // ทุกๆ 30 วัน $recurrences = 12; // รวม 12 รอบบิล // เราไม่รวมวันที่แรกหรือวันที่ 1 กำหนด้วย DatePeriod::EXCLUDE_START_DATE $period = new DatePeriod($start, $interval, $recurrences, DatePeriod::EXCLUDE_START_DATE); foreach ($period as $dt) { echo $dt->format("Y-m-d")."<br>"; }
ผลลัพธ์ที่ได้ สังเกตว่าเดือน 5 จะมี 2วันคือวันที่ 1 กับวันที่ 31 ซึ่งห่างกัน 30 วัน
2022-01-31 2022-03-02 2022-04-01 2022-05-01 2022-05-31 2022-06-30 2022-07-30 2022-08-29 2022-09-28 2022-10-28 2022-11-27 2022-12-27
เนื้อหาในบทความนี้ เราได้รู้เพิ่มเติมเกี่ยวกับการใช้งานวันที่และเวลาใน PHP สามารถเอาไปใช้
เป็นแนวทางประยุกต์เพิ่มเติมได้ หรือนำไปใช้งานร่วมกับคำสั่งอื่นๆ เกี่ยวกับเวลาแทนได้ หวังว่าจะ
เป็นประโยชน์ไม่มากก็น้อย *บทความแรกของปีนี้