บันทึกวิธีการใช้งาน DateTime class ที่ใช้งานกันบ่อย ๆ
ตัว DateTime เมื่อสร้างขึ้นมาแล้ว จะไม่สามารถเปลี่ยนแปลงค่าภายใน object ที่สร้างขึ้นมาได้อีก
DateTime มีตัว constructor ที่มีให้ใช้งานจะมีดังนี้
DateTime()
เวลาที่สร้างขึ้นจะอ้างอิงจาก local time zoneDateTime.now()
เวลา ณ ปัจจุบันอ้างอิงจาก local time zoneDateTime.utc()
เวลาที่สร้างขึ้นจะอ้างอิงจาก UTC time zoneDateTime.fromMicrosecondsSinceEpoch()
จะใช้ค่าไมโครวินาที (1 ใน ล้านวินาที) ที่นับตั้งแต่ปี ค.ศ.1970DateTime.fromMillisecondsSinceEpoch()
จะใช้ค่ามิลลิวินาที (1 ใน พันวินาที) ที่นับตั้งแต่ปี ค.ศ.1970local time zone = คือเวลาพื้นที่ของเครื่องที่ใช้งาน เช่น ถ้าประเทศไทย จะเป็น UTC+07:00 ส่วน UTC time zone หรือ เวลาสากลเชิงพิกัด (Coordinated Universal Time) ที่จุดอ้างอิงของเวลาสากลเชิงพิกัดคือที่ลองจิจูด ที่ 0° ซึ่งจะคือตำแหน่งเมืองลอนดอน ประเทศอังกฤษ
void main() {
var local = DateTime.now();
var utc = local.toUtc();
print(local);// output → 2024-08-24 16:43:33.011088
print(utc);// output → 2024-08-24 09:43:33.011088Z
}
จากตัวอย่าง เครื่องที่ใช้อยู่ประเทศไทย UTC+07:00 เมื่อทำการขอค่าเวลาเป็น UTC จึงได้เวลาที่น้อยกว่า 7 ชั่วโมง (16:43 กับ 09:43)
แผนที่ Time zone จาก Wikipedia
DateTime()
constructor จะต้องระบุตัวเลขของเวลาที่ต้องการสร้าง โดยอย่างน้อยสุดต้องระบุปี ซึ่งผลที่ได้จะเป็นวันและเวลาเริ่มต้นของปีดังกล่าว
DateTime(
int year, [
int month = 1,
int day = 1,
int hour = 0,
int minute = 0,
int second = 0,
int millisecond = 0,
int microsecond = 0,
])
ส่วน DateTime.utc()
constructor จะมี parameters เหมือนกัน แต่ตัวเวลาที่ระบุจะเป็นเวลาที่ UTC+0
void main() {
// first date and time in year 2024
var year2024 = DateTime(2024); // local time is UTC+7
var year2024utc = DateTime.utc(2024);
print(year2024); // output → 2024-01-01 00:00:00.000
print(year2024.toUtc()); // output → 2023-12-31 17:00:00.000Z
print(year2024utc); // output → 2024-01-01 00:00:00.000Z
// last day on year 2024
var endOf2024 = DateTime(2024, 12, 31);
print(endOf2024); // output → 2024-12-31 00:00:00.000
// before new year
var before2025 = DateTime(2024, 12, 31, 23, 59, 59, 999);
print(before2025); // output → 2024-12-31 23:59:59.999
}
ในระบบคอมพิวเตอร์จะใช้ Unix Epoch เป็นช่วงเวลาในการอ้างอิงจุดเริ่มนับเวลาเป็น 0 คือ วันที่ 1 มกราคา ปี ค.ศ.1970 เวลา 00:00น. โดยในเซิร์ฟเวอร์มันจะใช้ค่าผลต่างเวลาดังกล่าวในการอ้างอิงถึงเวลาปัจจุบัน หรืออ้างอิงเวลา ณ จุดที่ต้องการ โดยหน่วยที่ Dart รองรับคือ มิลลิวินาที (ms.) และ ไมโครวินาที (µs.)
// first UTC date and time in year 2024 AD
var year1970utc = DateTime.utc(1970);
print(year1970utc); // output → 1970-01-01 00:00:00.000Z
print(year1970utc.millisecondsSinceEpoch); // output → 0
print(year1970utc.microsecondsSinceEpoch); // output → 0
// 1 day has 24*60*60*1000 = 86400000 ms.
var day1utc = DateTime.fromMillisecondsSinceEpoch(86400000, isUtc: true);
print(day1utc); // output → 1970-01-02 00:00:00.000Z
// year 9999 AD
var year2999utc = DateTime.utc(9999);
print(year2999utc); // output → 9999-01-01 00:00:00.000Z
print(year2999utc.millisecondsSinceEpoch); // output → 253370764800000
print(year2999utc.microsecondsSinceEpoch); // output → 253370764800000000
ปกติในการใช้งานทั่วไป การแสดงและคำนวณเวลาในแอป ไม่ค่อยได้ใช้หน่วย ms. และ µs. ในการสร้างเวลาเพื่อใช้งาน แต่มันจะเป็นการเอาค่าที่คืนมาจากเซิร์ฟเวอร์ ที่มักรองรับการคืนค่ากลับมาเป็น ms.
สำหรับข้อมูลเวลาหากใช้งานด้วยคอมพิวเตอร์ 64-bit จะสามารถอ้างเวลาได้เกินปี ค.ศ. 9999 ไปอีกเป็นพันล้านปีเลย ซึ่งตัวคนเขียนคงไม่มีโอกาศในใช้งานขนาดนั้น 😂
นอกจาก constructor ที่มีให้แล้ว ตัว DateTime ยังมี static method ที่ช่วยแปลง String เป็นข้อมูล DateTime ได้ ข้อความที่เป็นวันที่ ตัว DateTime รองรับรูปแบบย่อยต่าง ๆ ใน ISO 8601 โดยใช้ผ่านคำสั่ง DateTime.parse()
และ DateTime.tryParse()
โดยความแตกต่างของ 2 คำสั่งนี้คือ DateTime.parse()
ถ้าทำไม่สำเร็จจะ throw FormatException กลับมา แต่ DateTime.tryParse()
ถ้าทำไม่สำเร็จจะคืนค่ากลับมาเป็น null
ตัวอย่างรูปแบบข้อความที่สามารถแปลงเป็น DateTime ได้
// local time
var onlyDate = DateTime.parse("20240101");
print(onlyDate); // output → 2024-01-01 00:00:00.000
var dateAndTime = DateTime.parse("20240101 120000");
print(dateAndTime); // output → 2024-01-01 12:00:00.000
var dateAndTime2 = DateTime.parse("2024-01-01 12:00:00");
print(dateAndTime2); // output → 2024-01-01 12:00:00.000
print(dateAndTime2.isUtc); // output → false
// utc+0 time
var testUtc = DateTime.parse("2024-01-01 12:00:00Z"); // same as 2024-01-01 12:00:00+00:00
print(testUtc); // output → 2024-01-01 12:00:00.000Z
print(testUtc.isUtc); // output → true
// utc+7 time
var bkkTime = DateTime.parse("2024-01-01 12:00:00+07:00");
print(bkkTime); // output → 2024-01-01 05:00:00.000Z
print(bkkTime.isUtc); // output → true
print(bkkTime.toUtc()); // output → 2024-01-01 05:00:00.000Z
print(bkkTime.toLocal()); // output → 2024-01-01 12:00:00.000
หากต้องการทราบว่าแอปที่ทำงานอยู่ ใช้ time zone อะไร สามารถใช้คำสั่ง .timeZoneName
และ .timeZoneOffset
ได้ โดย .timeZoneOffset
จะคืนค่ากลับมาเป็น Duration class
var localTime = DateTime(2000, 1, 5);
print(localTime.timeZoneName); // output → SE Asia Standard Time
print(localTime.timeZoneOffset); // output → 7:00:00.000000
var utcTime = localTime.toUtc();
print(utcTime.timeZoneName); // output → UTC
print(utcTime.timeZoneOffset); // output → 0:00:00.000000
ข้อมูลวันที่
.day
วันที่ 1 - 31.month
เดือน 1 - 12.year
ปี ค.ศ..weekday
วันในสัปดาห์ monday - sunday (เป็นค่า int คือ 1 - 7)ข้อมูลเวลา
.hour
ชั่วโมง 0 - 23.minute
นาที 0 - 59.second
วินาที 0 - 59.millisecond
มิลลิวินาที 0 - 999.microsecond
ไมโครวินาที 0 - 999var localTime = DateTime(2000, 1, 5, 10, 30, 0, 500, 100);
print(localTime); //output → 2000-01-05 10:30:00.500100
print(localTime.day); //output → 5
print(localTime.month); //output → 1
print(localTime.year); //output → 2000
print(localTime.weekday); //output → 3
print(localTime.hour); //output → 10
print(localTime.minute); //output → 30
print(localTime.second); //output → 0
print(localTime.millisecond); //output → 500
print(localTime.microsecond); //output → 100
การบวก เพิ่มค่าเข้าไปใน DateTime สามารถทำได้โดยใช้คำสั่ง .add()
โดยส่งผ่านค่า Duration class ที่ต้องการเพิ่มเข้าไป
var year2000 = DateTime(2000);
print(year2000); // output → 2000-01-01 00:00:00.000
print(year2000.add(Duration(days: 10))); // output → 2000-01-11 00:00:00.000
print(year2000.add(Duration(hours: 12))); // output → 2000-01-01 12:00:00.000
print(year2000.add(Duration(days: 1, hours: 12, minutes: 30))); // output → 2000-01-02 12:30:00.000
การลบ เพิ่มค่าเข้าไปใน DateTime สามารถทำได้โดยใช้คำสั่ง .subtract()
โดยส่งผ่านค่า Duration class ที่ต้องการเพิ่มเข้าไป
var year2000 = DateTime(2000);
print(year2000); // output → 2000-01-01 00:00:00.000
print(year2000.subtract(Duration(days: 10))); // output → 1999-12-22 00:00:00.000
print(year2000.subtract(Duration(hours: 12))); // output → 1999-12-31 12:00:00.000
print(year2000.subtract(Duration(days: 1, hours: 12, minutes: 30))); // output → 1999-12-30 11:30:00.000
ผลต่างของ 2 เวลา สามารถใช้คำสั่ง .difference()
ผลที่ได้จะออกมาเป็น Duration class
var date15 = DateTime(2000, 1, 15);
var date10 = DateTime(2000, 1, 10);
var diff_15_10 = date15.difference(date10);
print(diff_15_10.inDays); // output → 5
print(diff_15_10.inHours); // output → 120
print(diff_15_10); // output → 120:00:00.000000
var diff_10_15 = date10.difference(date15);
print(diff_10_15.inDays); // output → -5
print(diff_10_15.inHours); // output → -120
print(diff_10_15); // output → -120:00:00.000000
var time15 = DateTime(2000, 1, 1, 15, 0);
var time10 = DateTime(2000, 1, 1, 10, 0);
var diff2 = time15.difference(time10);
print(diff2.inDays); // output → 0
print(diff2.inHours); // output → 5
print(diff2); // output → 5:00:00.000000
การเปรียบเทียบเวลาว่ามากกว่าเวลา หรืออยู่หลังที่กำหนดหรือไม่ ให้ใช้คำสั่ง .isAfter()
ในการตรวจสอบ
var date10 = DateTime(2000, 1, 10);
var date15 = date10.add(Duration(days: 5));
print(date10.isAfter(date15)); // output → false
print(date15.isAfter(date10)); // output → true
การเปรียบเทียบเวลาว่าอยู่ก่อน หรือน้อยกว่าเวลาที่กำหนดหรือไม่ ให้ใช้คำสั่ง .isBefore()
ในการตรวจสอบ
var date10 = DateTime(2000, 1, 10);
var date15 = date10.add(Duration(days: 5));
print(date10.isBefore(date15)); // output → true
print(date15.isBefore(date10)); // output → false
หรือหากใครที่ถนัดคำสั่ง .compareTo()
ก็ใช้คำสั่งนี้เปรียบเทียบได้เหมือนกัน โดยจะให้ผลออกมาเป็น
final now = DateTime.now();
final future = now.add(const Duration(days: 2));
final past = now.subtract(const Duration(days: 2));
final newDate = now.toUtc();
print(now.compareTo(future)); // -1
print(now.compareTo(past)); // 1
print(now.compareTo(newDate)); // 0
เพื่อไม่ให้สับสน การเปรียบเทียบเวลาในที่นี่คือ วันและเวลามีค่าเดียวกัน โดยจะใช้หลักว่าเมื่อเวลาทั้งสองอยู่ใน time zone เดียวกัน จะเท่ากันหรือไม่ ใช้คำสั่ง .isAtSameMomentAs()
var localTime = DateTime.parse("2000-01-01 12:00:00");
var utcTime = localTime.toUtc();
print(localTime.isAtSameMomentAs(utcTime)); // output → true
print(localTime.difference(utcTime)); // output → 0:00:00.000000
print(localTime.compareTo(utcTime)); // output → 0
print(localTime.isUtc); // output → false
print(utcTime.isUtc); // output → true
// don't use == to compare time value
print(localTime == utcTime); // output → false
var utcTime2 = utcTime.toUtc(); // returns this DateTime if it is already in UTC
print(utcTime == utcTime2); // output → true
เมื่อต้องการแปลงเวลาออกมาเป็นข้อความ สามารถใช้คำสั่ง .toString()
กับ .toIso8601String()
โดยรูปแบบจะเป็นแบบตายตัว
var localTime = DateTime.now();
print(localTime.toString()); // → 2024-08-24 22:10:43.770278
print(localTime.toIso8601String()); // → 2024-08-24T22:10:43.770278
หากต้องการจัดรูปแบบวันที่และเวลา ในแบบที่ต้องการ วิธีที่ง่ายและสะดวกโดยไม่ต้องมาเขียนเพิ่มเองคือใช้ DateFormat class ใน intl package
import 'package:intl/intl.dart';
void main() {
final DateTime now = DateTime(2000, 1, 5);
final DateFormat formatter = DateFormat('d/M/yyyy');
final String formatted = formatter.format(now);
print(formatted); // output → 5/1/2000
}
หรือถ้าจะเขียนเองโดยไม่ใช่ intl package ก็สามารถทำได้ เนื่องจากตัว DateTime มีคำสั่งในการเข้าถึงข้อมูลวันที่และเวลาอยู่แล้ว ก็นำมาแปลงให้อยู่ในรูปแบบที่ต้องการได้ผ่านคำสั่งใน String class เป็นต้น
var today = DateTime(2000, 1, 5);
print('${today.day}/${today.month}/${today.year}'); // output → 5/1/2000
// date and month with 2 digit
var dd = today.day.toString().padLeft(2, '0');
var mm = today.month.toString().padLeft(2, '0');
print('$dd/$mm/${today.year}'); // output → 05/01/2000