date('Y-m-d') trả về ngày hôm nay dưới dạng chuỗi, ví dụ 2026-03-14. Đối số đầu tiên là chuỗi định dạng, trong đó mỗi chữ cái đại diện cho một phần của ngày (Y là năm, m là tháng, d là ngày, H:i:s là giờ), còn đối số thứ hai (không bắt buộc) là một Unix timestamp để định dạng thay cho thời điểm hiện tại.
Kết quả thay đổi mỗi lần bạn nhấn Chạy, vì đó là ngày giờ hiện tại theo UTC. Mọi chữ cái của chuỗi định dạng, và cách chèn chữ thường vào giữa chúng, có ở trang định dạng ngày PHP.
Timestamp: time(), mktime() và strtotime()
Unix timestamp là số giây tính từ nửa đêm ngày 1 tháng 1 năm 1970 theo giờ UTC. time() trả về timestamp hiện tại, mktime(hour, minute, second, month, day, year) tạo timestamp từ từng phần, còn strtotime() đọc một ngày viết bằng tiếng Anh ('2026-03-14', '+1 week', 'next monday'). Bạn có thể truyền bất kỳ timestamp nào làm đối số thứ hai của date(). Đối số thứ hai của strtotime() là thời điểm mà cụm từ tương đối được tính từ đó; nếu bỏ trống, nó tính từ bây giờ.
Đầu ra:
1773480600
Sat, 14 Mar 2026 09:30
2027-01-01
tomorrow Sun 2026-03-15
+1 week Sat 2026-03-21
next monday Mon 2026-03-16
last day of this month Tue 2026-03-31
first monday of next month Mon 2026-04-06
bool(false)
Việc mktime() tự tràn sang đơn vị kế tiếp rất có ích: ngày 0 của một tháng là ngày cuối của tháng trước, nên mktime(0, 0, 0, 3, 0, 2026) là ngày 28 tháng 2. Luôn so sánh kết quả với false trước khi dùng tiếp: date('Y-m-d', false) lặng lẽ in ra 1970-01-01, một ngày không ai mong muốn.
Cộng ngày vào một ngày
Với mọi việc ngoài in ra màn hình, hãy dùng DateTimeImmutable. Phương thức modify() của nó nhận cùng các cụm từ như strtotime() và trả về một ngày mới, còn add() nhận một DateInterval như P7D (khoảng 7 ngày) hoặc PT90M (90 phút).
Đầu ra:
2026-03-21
2026-03-13
2026-04-14
11:00
2025-03-14
2026-03-03
2026-02-28
Ngày 31 tháng 2 không tồn tại, nên +1 month từ ngày 31 tháng 1 rơi vào ngày 3 tháng 3. Khi ý bạn là "cuối tháng sau", hãy nói rõ bằng last day of next month.
DateTime và DateTimeImmutable
DateTime tự thay đổi chính nó khi bạn gọi modify(), add() hoặc setDate(), và trả về cùng một đối tượng. Điều này khiến nhiều người bất ngờ khi giữ ngày ban đầu trong một biến:
Đầu ra:
2026-03-21
2026-03-21
bool(true)
2026-03-14
2026-03-21
Trong code mới, hãy ưu tiên DateTimeImmutable. Hai lớp có cùng các phương thức và đều triển khai DateTimeInterface, nên một hàm có thể nhận cả hai.
Khoảng cách giữa hai ngày
diff() trả về một DateInterval. Thuộc tính days của nó là tổng số ngày giữa hai ngày, còn y, m và d chia khoảng đó thành năm, tháng và ngày, đúng thứ mà việc tính tuổi cần. Hãy đổi ngày rồi chạy lại:
Đầu ra:
Age: 35
Exactly: 35 years, 7 months, 22 days
Days alive: 13021
286 days to go
9 months and 11 days
-286 days
Trong format(), %a là tổng số ngày còn %d chỉ là phần ngày, nên %a mới là thứ cần dùng cho "còn bao nhiêu ngày". Để so sánh hai ngày mà không cần tính khoảng cách, các toán tử thông thường dùng được trên đối tượng ngày: $today < $christmas là true.
Múi giờ
date() và new DateTimeImmutable() dùng múi giờ mặc định, lấy từ date.timezone trong php.ini (UTC nếu chưa đặt). Đặt múi giờ cho cả script bằng date_default_timezone_set(), hoặc gán cho một ngày riêng DateTimeZone của nó rồi chuyển đổi bằng setTimezone():
Đầu ra:
Asia/Tokyo 2026-03-14 18:30 JST +09:00
Europe/Berlin 2026-03-14 10:30 CET +01:00
America/New_York 2026-03-14 05:30 EDT -04:00
Asia/Tokyo
2026-03-14 18:30
Timestamp là cùng một con số ở mọi nơi; múi giờ chỉ thay đổi cách nó được viết ra. Đó là lý do lời khuyên thường gặp là lưu ngày theo UTC và chỉ chuyển đổi khi hiển thị.
Hiển thị lịch trên trang web
Ngày tháng thường được in vào HTML. Khối này vẽ tháng hiện tại thành một tờ lịch và tô sáng ngày hôm nay. Hãy chạy nó, rồi nhấn Previous hoặc Next: cùng script đó chạy lại với $_GET['m'] lấy từ liên kết, ví dụ ?m=2026-04.
format('N') cho thứ trong tuần từ 1 (Thứ Hai) đến 7 (Chủ Nhật), cũng chính là số ô trống cần đặt trước ngày mùng 1, còn format('t') cho số ngày trong tháng. Dấu ! trong '!Y-m' đặt lại mọi trường mà định dạng không nhắc tới, nên ngày là mùng 1 và giờ là nửa đêm.
Lỗi thường gặp với date()
Đối số thứ hai của date() phải là một timestamp, không phải chuỗi ngày. Dòng này:
<?php
echo date('d/m/Y', '2026-03-14');
dừng script với một TypeError:
PHP Fatal error: Uncaught TypeError: date(): Argument #2 ($timestamp) must be of type ?int, string given in /home/index.php:2
Hãy chuyển chuỗi trước, bằng strtotime() hoặc một đối tượng:
Đầu ra:
14/03/2026
14/03/2026
bool(false)
bool(true)
Còn hai lỗi nữa cần để ý: m là tháng còn i là phút, nên 'H:m' in ra tháng ở chỗ bạn muốn phút; và new DateTimeImmutable('garbage') ném ra ngoại lệ thay vì trả về false, nên hãy bọc dữ liệu người dùng nhập trong try/catch, hoặc phân tích bằng DateTimeImmutable::createFromFormat(), hàm trả về false khi không khớp.
Câu hỏi thường gặp
Làm sao lấy ngày hiện tại trong PHP?
Gọi date() với một chuỗi định dạng: echo date('Y-m-d'); in ra ngày hôm nay dạng 2026-03-14, còn date('Y-m-d H:i:s') thêm cả giờ. Phiên bản dùng đối tượng là (new DateTimeImmutable())->format('Y-m-d').
Làm sao cộng thêm ngày vào một ngày trong PHP?
Dùng modify() trên một DateTimeImmutable: (new DateTimeImmutable('2026-03-14'))->modify('+7 days')->format('Y-m-d') cho ra 2026-03-21. Với timestamp, date('Y-m-d', strtotime('+7 days', $timestamp)) cũng làm được điều tương tự.
Làm sao tính khoảng cách giữa hai ngày trong PHP?
Gọi diff() trên một ngày với ngày còn lại: $a->diff($b) trả về một DateInterval. Thuộc tính days của nó là tổng số ngày, còn y, m, d chứa số năm, tháng và ngày, đó cũng là cách tính tuổi của một người.
Làm sao chuyển Unix timestamp thành ngày trong PHP?
Truyền nó làm đối số thứ hai của date(): date('Y-m-d H:i:s', 1773479107) trả về 2026-03-14 09:05:07 theo giờ UTC. Nếu cần đối tượng, dùng new DateTimeImmutable('@1773479107').
Vì sao date() trong PHP hiện sai giờ?
date() dùng múi giờ mặc định, lấy từ date.timezone trong php.ini và thường là UTC. Đặt múi giờ của bạn bằng date_default_timezone_set('Europe/Berlin') ở đầu script, hoặc truyền một DateTimeZone vào DateTimeImmutable.