Trong phần này chúng ta sẽ bàn về hệ thống ngày giờ trong Qt 5
Qt5 có các lớp QDate
, QTime
và QDateTime
chuyên dùng để làm việc với ngày giờ. Lớp QDate
là lớp dùng cho ngày tháng trong dương lịch, lớp này có các phương thức dùng để xác định ngày, so sánh hay chỉnh sửa ngày. Lớp QTime
dùng cho giờ, có các phương thức dùng để so sánh giờ, xác định giờ và các phương thức khác để làm việc với giờ. Lớp QDateTime
là lớp vừa làm việc được với ngày, vừa làm việc với giờ, lớp này là gộp chung của lớp QDate
và QTime
.
Khởi tạo các đối tượng ngày và giờ
Chúng ta có thể khởi tạo bằng cách dùng các constructor để tạo dữ liệu hoặc tạo đối tượng rỗng rồi đưa dữ liệu vào sau cũng được.
#include <QTextStream> #include <QDate> #include <QTime> int main(void) { QTextStream out(stdout); QDate dt1(2015, 4, 12); out << "The date is " << dt1.toString() << endl; QDate dt2; dt2.setDate(2015, 3, 3); out << "The date is " << dt2.toString() << endl; QTime tm1(17, 30, 12, 55); out << "The time is " << tm1.toString("hh:mm:ss.zzz") << endl; QTime tm2; tm2.setHMS(13, 52, 45, 155); out << "The time is " << tm2.toString("hh:mm:ss.zzz") << endl; }
Ở trên chúng ta khởi tạo các đối tượng bằng cả hai cách.
QDate dt1(2015, 4, 12);
Hàm khởi tạo đối tượng QDate nhận 3 tham số đầu vào: year, month và day.
out << "The date is " << dt1.toString() << endl;
Ta in ngày tháng ra màn hình, sử dụng phương thức toString()
để chuyển một đối tượng thành một chuỗi.
QTime tm2; tm2.setHMS(13, 52, 45, 155);
Ở đây ta tạo ra một đối tượng rỗng, sau đó đưa dữ liệu vào thông qua phương thức setHMS()
. Tham số gồm có hour, minute, second và milisecond.
out << "The time is " << tm2.toString("hh:mm:ss.zzz") << endl;
Sau đó ta lại in giờ ra màn hình. Bên trong phương thức toString()
bạn có thể dịnh dạng cho output cần hiển thị theo ý muốn của bạn. Ở trên mình dùng định dạng hh:mm:ss.zz, đây cũng là định dạng mặc định của hệ thống.
The date is Sun Apr 12 2015 The date is Tue Mar 3 2015 The time is 17:30:12.055 The time is 13:52:45.155
Ngày giờ hiện tại
Trong ví dụ dưới đây, chúng ta sẽ in ra ngày giờ hiện tại của hệ thống.
#include <QTextStream> #include <QTime> #include <QDate> int main(void) { QTextStream out(stdout); QDate cd = QDate::currentDate(); QTime ct = QTime::currentTime(); out << "Current date is: " << cd.toString() << endl; out << "Current time is: " << ct.toString() << endl; }
QDate cd = QDate::currentDate();
Phương thức tĩnh QDate::currentDate() sẽ trả về ngày hiện tại.
QTime ct = QTime::currentTime();
Phương thức tĩnh QTime::currentTime()
trả về giờ hiện tại.
Current date is: Fri Oct 30 2015 Current time is: 20:55:27
So sánh ngày
Ta có thể dùng các toán tử so sánh để so sánh ngày. Xem ví dụ.
#include <QTextStream> #include <QDate> int main(void) { QTextStream out(stdout); QDate dt1(2015, 4, 5); QDate dt2(2014, 4, 5); if (dt1 < dt2) { out << dt1.toString() << " comes before " << dt2.toString() << endl; } else { out << dt1.toString() << " comes after " << dt2.toString() << endl; } }
Đoạn code ví dụ trên so sánh 2 ngày.
if (dt1 < dt2) { out << dt1.toString() << " comes before " << dt2.toString() << endl; } else { out << dt1.toString() << " comes after " << dt2.toString() << endl; }
Ta dùng toán tử bé hơn “<” để biết ngày nào xuất hiện trước trong lịch.
Sun Apr 5 2015 comes after Sat Apr 5 2014
Ta có thể dùng các toán tử so sánh này với cả lớp QTime
và QDateTime
.
Tìm năm nhuận
Một năm có 365 ngày, năm nhuận là năm có 366 ngày. Lý do tại sao có năm nhuận là vì một năm hay một vòng quay của Trái đất quanh mặt trời không phải là mất chính xác 365 ngày, mà là 365.25 ngày (hay 365 ngày và 6 giờ). Do vậy, để lịch của chúng ta trùng khớp với tự nhiên, cứ 4 năm ta lại thêm 1 ngày vào tháng 2. Tức là năm thường tháng 2 có 28 ngày, năm nhuận tháng 2 có 29 ngày.
Thường thì trong các ngôn ngữ thường dùng như C++, Java không có sẵn hàm tính năm nhuận, bạn phải code lại từ đầu. Qt có phương thức QDate::isLeapYear()
dùng để xác định xem một năm có phải là năm nhuận hay không.
#include <QTextStream> #include <QDate> int main() { QTextStream out(stdout); QList<int> years({2010, 2011, 2012, 2013, 2014, 2015, 2016}); foreach (int year, years) { if (QDate::isLeapYear(year)) { out << year << " is a leap year" << endl; } else { out << year << " is not a leap year" << endl; } } }
Trong ví dụ trên chúng ta có một danh sách các năm. Chúng ta sẽ xem thử có năm nào là năm nhuận không.
QList<int> years({2010, 2011, 2012, 2013, 2014, 2015, 2016});
Dòng trên chúng ta khởi tạo một list các năm. Đây là cách khởi tạo trong C++11. Vì thế nên bạn cần khai báo C++11 trong file project bằng cách thêm một trong các dòng sau:
CONFIG += c++11
QMAKE_CXXFLAGS += -std=c++11
QMAKE_CXXFLAGS += -std=c++0x
.
foreach (int year, years) { if (QDate::isLeapYear(year)) { out << year << " is a leap year" << endl; } else { out << year << " is not a leap year" << endl; } }
Chúng ta duyệt qua hết các năm trong list và dùng phương thức QDate::isLeapYear()
để biết năm nào là năm nhuận, phương thức này trả về kiểu bool.
TEMPLATE = app TARGET = leapyear INCLUDEPATH += . CONFIG += c++11 # Input SOURCES += leapyear.cpp QT -= gui
Đây là file project. Chúng ta thêm dòng khai báo CONFIG += c++11
để kích hoạt C++11. Ngoài ra chúng ta cũng tắt module gui đi bằng dòng QT -= gui
vì ở đây chúng ta đang viết ứng dụng dòng lệnh nên gui cũng không cần thiết lắm.
2010 is not a leap year 2011 is not a leap year 2012 is a leap year 2013 is not a leap year 2014 is not a leap year 2015 is not a leap year 2016 is a leap year
Các định dạng ngày tháng có sẵn
Qt5 có một số định dạng ngày tháng có sắn. Ở trên mình đã nói trong phương thức toString()
bạn có thể thêm một chuỗi định dạng vô để in ra kết quả như ý muốn. Ngoài ra bạn có thể sử dụng một số hằng có sẵn trong Qt5. Mặc định nếu bạn không dùng thì hệ thống sẽ sử dụng định dạng Qt::TextDate
. Xem ví dụ.
#include <QTextStream> #include <QDate> int main(void) { QTextStream out(stdout); QDate cd = QDate::currentDate(); out << "Today is " << cd.toString(Qt::TextDate) << endl; out << "Today is " << cd.toString(Qt::ISODate) << endl; out << "Today is " << cd.toString(Qt::SystemLocaleShortDate) << endl; out << "Today is " << cd.toString(Qt::SystemLocaleLongDate) << endl; out << "Today is " << cd.toString(Qt::DefaultLocaleShortDate) << endl; out << "Today is " << cd.toString(Qt::DefaultLocaleLongDate) << endl; out << "Today is " << cd.toString(Qt::SystemLocaleDate) << endl; out << "Today is " << cd.toString(Qt::LocaleDate) << endl; }
Trong ví dụ trên, mình in ra 8 định dạng ngày tháng khác nhau.
out << "Today is " << cd.toString(Qt::ISODate) << endl;
Định dạng Qt::ISODate
là định dạng tiêu chuẩn quốc tế.
Today is Sat Oct 31 2015 Today is 2015-10-31 Today is 10/31/15 Today is Saturday, October 31, 2015 Today is 10/31/15 Today is Saturday, October 31, 2015 Today is 10/31/15 Today is 10/31/15
Tùy chỉnh định dạng ngày tháng
Như đã nói ở trên, ngoài các định có sẵn trong Qt thì các bạn có thể tự tùy chỉnh định dạng ngày tháng cho hợp với ý mình. Bảng dưới đây mô tả các đặc tả về định dạng ngày tháng:
ĐẶC TẢ | KẾT QUẢ |
---|---|
d | In ra ngày mà không có số 0 dẫn đầu (1 → 31) |
dd | In ra ngày có một số 0 dẫn đầu (01 → 31) |
ddd | In ra tên viết tắt của ngày trong tuần (vd Mon → Sun). Sử dụng QDate::shortDayName(). |
dddd | In ra tên đầy đủ của ngày trong tuần (vd Monday → Sunday). Sử dụng QDate::longDayName(). |
M | In ra tháng không có số 0 dẫn đầu (1 → 12) |
MM | In ra tháng có một số 0 dẫn đầu (01 → 12) |
MMM | In ra tên viết tắt của tháng (vd Jan → Dec). Sử dụng QDate::shortMonthName(). |
MMMM | In ra tên đầy đủ của tháng (vd January → December). Sử dụng QDate::longMonthName(). |
yy | In ra hai số cuối của năm (00 → 99) |
yyyy | In ra đầy đủ bốn số của năm. |
#include <QTextStream> #include <QDate> int main(void) { QTextStream out(stdout); QDate cd = QDate::currentDate(); out << "Today is " << cd.toString("yyyy-MM-dd") << endl; out << "Today is " << cd.toString("yy/M/dd") << endl; out << "Today is " << cd.toString("d. M. yyyy") << endl; out << "Today is " << cd.toString("d-MMMM-yyyy") << endl; }
Trong code ví dụ trên mình in ra bốn kiểu định dạng khác nhau.
out << "Today is " << cd.toString("yyyy-MM-dd") << endl;
Đây là định dạng tiêu chuẩn quốc tế. Năm được ghi ra đủ 4 chữ số, ngày tháng ngăn cách nhau bởi dấu gạch ngang “-“. Tháng và ngày được in ra 2 chữ số, bao gồm cả chữ số 0 dẫn đầu (nếu có).
out << "Today is " << cd.toString("yy/M/dd") << endl;
Đây cũng là một định dạng phổ biến. Ngày tháng được ngăn cách bởi dấu “/”. Tháng được in một chữ số (không có số 0 dẫn đầu).
Today is 2015-10-31 Today is 15/10/31 Today is 31. 10. 2015 Today is 31-October-2015
Lấy thứ trong tuần
Phương thức dayOfWeek()
trả về một con số từ 1 đến 7 đại diện cho Thứ Hai (Monday) đến Chủ Nhật (Sunday).
#include <QTextStream> #include <QDate> int main(void) { QTextStream out(stdout); QDate cd = QDate::currentDate(); int wd = cd.dayOfWeek(); out << "Today is " << QDate::shortDayName(wd) << endl; out << "Today is " << QDate::longDayName(wd) << endl; }
Trong ví dụ trên ta in ra thứ trong tuần theo hai dạng viết tắt và viết đầy đủ.
QDate cd = QDate::currentDate();
Lấy ngày hiện tại
int wd = cd.dayOfWeek();
Lấy thứ trong tuần.
out << "Today is " << QDate::shortDayName(wd) << endl;
Lấy tên viết tắt của thứ
bằng phương thức QDate::shortDayName()
.
out << "Today is " << QDate::longDayName(wd) << endl;
Lấy tên đầy đủ của thứ bằng phương thức QDate::longDayName()
.
Today is Sat Today is Saturday
Lấy số ngày trong tháng và năm
Ta có thể biết trong tháng hay trong năm có bao nhiêu ngày bằng phương thức daysInMonth()
và phương thức daysInYear().
#include <QTextStream> #include <QDate> int main(void) { QTextStream out(stdout); QList<QString>months; months.append("January"); months.append("February"); months.append("March"); months.append("April"); months.append("May"); months.append("June"); months.append("July"); months.append("August"); months.append("September"); months.append("October"); months.append("November"); months.append("December"); QDate dt1(2015, 9, 18); QDate dt2(2015, 2, 11); QDate dt3(2015, 5, 1); QDate dt4(2015, 12, 11); QDate dt5(2015, 1, 21); out << "There are " << dt1.daysInMonth() << " days in " << months.at(dt1.month()-1) << endl; out << "There are " << dt2.daysInMonth() << " days in " << months.at(dt2.month()-1) << endl; out << "There are " << dt3.daysInMonth() << " days in " << months.at(dt3.month()-1) << endl; out << "There are " << dt4.daysInMonth() << " days in " << months.at(dt4.month()-1) << endl; out << "There are " << dt5.daysInMonth() << " days in " << months.at(dt5.month()-1) << endl; out << "There are " << dt1.daysInYear() << " days in year " << QString::number(dt1.year()) << endl; }
Chúng ta tạo năm đối tượng QDate
và tính số ngày trong tháng và trong năm.
out << "There are " << dt1.daysInMonth() << " days in " << months.at(dt1.month()-1) << endl;
Chúng ta sử dụng phương thức daysInMonth()
để lấy số ngày trong đối tượng này.
out << "There are " << dt1.daysInYear() << " days in year " << QString::number(dt1.year()) << endl;
Ở đây chúng ta lấy số ngày trong năm bằng phương thức daysInYear()
.
There are 30 days in September There are 28 days in February There are 31 days in May There are 31 days in December There are 31 days in January There are 365 days in year 2015
Kiểm tra tính hợp lệ của ngày tháng
Phương thức isValid()
được dùng để làm việc này. Xem ví dụ
#include <QTextStream> #include <QDate> int main(void) { QTextStream out(stdout); QList<QDate> dates({QDate(2015, 5, 11), QDate(2015, 8, 1), QDate(2015, 2, 30)}); for (int i=0; i < dates.size(); i++) { if (dates.at(i).isValid()) { out << "Date " << i+1 << " is a valid date" << endl; } else { out << "Date " << i+1 << " is not a valid date" << endl; } } }
Chúng ta kiểm tra sự hợp lệ của ba đối tượng ngày tháng.
QList<QDate> dates({QDate(2015, 5, 11), QDate(2015, 8, 1), QDate(2015, 2, 30)});
Hai ngày đầu tiên là hợp lệ. Cái cuối cùng không hợp lệ vì tháng hai chỉ có 28 hoặc 29 ngày.
Date 1 is a valid date Date 2 is a valid date Date 3 is not a valid date
Tính số ngày từ một ngày cụ thể
Chúng ta có thể tính số ngày từ một ngày cụ thể sử dụng phương thức addDays()
và
daysTo()
.
#include <QTextStream> #include <QDate> int main(void) { QTextStream out(stdout); QDate dt(2015, 5, 11); QDate nd = dt.addDays(55); QDate xmas(2015, 12, 24); out << "55 days from " << dt.toString() << " is " << nd.toString() << endl; out << "There are " << QDate::currentDate().daysTo(xmas) << " days till Christmas" << endl; }
Chúng ta cộng thêm 55 ngày từ ngày 11/5/2015 và tính số ngày từ ngày hiện tại đến ngày giáng sinh năm 2015.
QDate dt(2015, 5, 11); QDate nd = dt.addDays(55);
Phương thức addDays()
trả về một QDate.
QDate xmas(2015, 12, 24); ... out << "There are " << QDate::currentDate().daysTo(xmas) << " days till Christmas" << endl;
Dùng phương thúc daysTo()
để tính số ngày từ đây đến giáng sinh.
55 days from Mon May 11 2015 is Sun Jul 5 2015 There are 54 days till Christmas
Lớp QDateTime
Lớp QDateTime
chứa cả lớp QDate
và lớp QTime
. Các phương thức của lớp QDateTime
cũng giống như của hai lớp kia. Xem ví dụ.
#include <QTextStream> #include <QDateTime> int main(void) { QTextStream out(stdout); QDateTime cdt = QDateTime::currentDateTime(); out << "The current datetime is " << cdt.toString() << endl; out << "The current date is " << cdt.date().toString() << endl; out << "The current time is " << cdt.time().toString() << endl; }
Ví dụ trên lấy ngày giờ của ngày hiện tại.
The current datetime is Sat Oct 31 17:10:50 2015 The current date is Sat Oct 31 2015 The current time is 17:10:50