How to Display Dates Using QDate
When writing an application with Qt, do you need a way to represent dates? Do you want to be able to display dates in a variety of ways, say in a report? Or do you need to do calculations with dates — what date is three years, five months, and four days from now? All this and more can be handled by Qt’s QDate class. QDate represents a date in the proleptic Gregorian calendar and has a variety of useful functions for handling all your date-related needs.
An Example
To illustrate what you can do with QDate, I’ve written a simple program that demonstrates much of the class’s functionality. This program implements a widget that lets the user specify a date by choosing a month and day from combo box menus, and a year by typing it into an edit field. The widget is embedded in another widget that displays information about the date — its string representation in a format chosen by the user, various other attributes such as day of week and whether it is in a leap year. There is also an option to see what the date will be if it is modified by any number of days, months, or years.
We’ll go over selections of code from the example as we examine QDate. You can download the example project here Zip files for sample code of QDate
Creating QDates
QDates can be created in a number of ways. You can construct a QDate by specifying a day, month, and year number. An existing QDate can be modified using setDate(). You can also get the current date (based on your system clock) with the static function currentDate(). If you have a string representation of a date, you can use the static function fromString() to convert it to a QDate. What formats are supported for this conversion are covered in the next section.
In the example, a QDate is stored in the class DateSelectionWidget. When an object of that class is created, the QDate is initialized with currentDate():
m_date = QDate::currentDate();
// Later, when the user changes the day, month, or year, setDate() is used to modify the existing date.
void DateSelectionWidget::updateDate(int year, int month, int day)
{
if (m_date.year() != year ||
m_date.month() != month ||
m_date.day() != day)
{
m_date.setDate(year, month, day);
emit dateChanged(m_date);
}
}
String Representations of QDates
You can get a string representation of a QDate in a variety of formats using the toString() function. The format can be specified by a Qt::DateFormat. The supported formats are:
Qt::TextDate
Qt::ISODate
Qt::ISODateWithMs
Qt::SystemLocaleShortDate
Qt::SystemLocaleLongDate
Qt::DefaultLocaleShortDate
Qt::DefaultLocaleLongDate
Qt::RFC2822Date
(There are three other formats supported, but are deprecated: Qt::SystemLocaleDate, Qt::LocaleDate, Qt::LocalDate.)
More details on how the date formats work can be found at http://doc.qt.io/qt-5/qt.html#DateFormat-enum
You can also construct your own format and pass it to toString() as a QString or QStringView. The following expressions can be used in the string format:
Expression:Output
- d: Day number with no leading zero (e.g 1)
- dd: Day number with leading zero (e.g. 01)
- ddd: Abbreviated localized day name (e.g. “Mon”)
- dddd: Long localized day name (e.g. “Monday”)
- M: Month number with no leading zero (e.g. 1)
- MM:Month number with leading zero (e.g. 01)
- MMM:Abbreviated localized month name (e.g. “Jan”)
- MMMM:Long localized month name (e.g. “January”)
- yy:Year as two digit number (e.g. 99)
- yyyy: Year as four digit number (e.g. 1999). Can be a negative number for BCE years.
(Source: http://doc.qt.io/qt-5/qdate.html#toString-1)
In our example, a string format can be selected from a combo box. If the first option, “Use Format String:” is selected, the line editor next to the combo box becomes active, and a format string can be typed in it to be used to format the selected date.
QString DateInfoWidget::getDateString(QDate date) const
{
int index = m_dateFormatComboBox->currentIndex();
if (index == 0)
{
// Use string format specified in edit box
return date.toString(m_dateFormatStringEdit->text());
}
else
{
// Use format specified in combo box
int data = m_dateFormatComboBox->currentData().toInt();
Qt::DateFormat format = static_cast Qt::DateFormat(data);
return date.toString(format);
}
}
Getting Information About a QDate
You can get all sorts of useful information from a QDate. Of course, you can get a QDate’s day, month, or year with day(), month(), and year(). But you can also find out, for a given QDate, what day of the week it is with getDayOfWeek(). You can also find out what day of the year it is with dayOfYear(), and whether the year is a leap year with isLeapYear().
weekNumber() is used to find the week number as well as what year the week number is associated with -- January 1, 2000, for example, is actually in week 52 of 1999. Finally, you can obtain the Julian day, which has uses in applications such as astronomy, with toJulianDay().
In the example app, the QDate is obtained from the selection widget and the various informational functions are called with it. The resulting values are used to update the example app’s UI.
QDate date = m_dateSelectWidget->getDate();
// If invalid date then update the UI to reflect that
if (!date.isValid())
{
updateUIInvalidDate();
return;
}
// Get information about specified date
int yearNumber;
int weekNumber = date.weekNumber(&yearNumber);
QString dayOfWeek = getDayOfWeek(date.dayOfWeek());
int dayOfYear = date.dayOfYear();
qint64 julianDay = date.toJulianDay();
QString isLeapYear = QDate::isLeapYear(date.year()) ? "true" : "false";
m_weekNumberLabel->setText(QString("%1 of %2").arg(weekNumber).arg(yearNumber));
m_dayOfWeekLabel->setText(dayOfWeek);
m_dayOfYearLabel->setText(QString("%1").arg(dayOfYear));
m_julianDayLabel->setText(QString("%1").arg(julianDay));
m_isLeapYearLabel->setText(isLeapYear);
Modifying QDates
You can get new QDates by adding or subtracting a specified number of days, months, or years. The function addDays() can be used to return a QDate the specified number of days in the future. Or, if you want a date in the past, call addDays() with a negative number. There are similar functions in addMonths() and addYears().
The example app uses these functions to show an updated date based on the user’s input.
QString DateInfoWidget::getUpdatedDateString(QDate date)
const {
int delta = m_deltaEdit->text().toInt();
int intervalIndex = m_intervalTypeComboBox->currentIndex();
int beforeIndex = m_beforeAfterComboBox->currentIndex();
// If looking for a date before the current one, use a negative delta
if (beforeIndex == 0) delta = -delta;
// Get a new date QDate updatedDate; if (intervalIndex == 0) // days
updatedDate = date.addDays(delta); else if (intervalIndex == 1) // weeks
updatedDate = date.addDays(delta*7); else if (intervalIndex == 2) // months
updatedDate = date.addMonths(delta); else // years
updatedDate = date.addYears(delta); // Return string representation of new date return getDateString(updatedDate); }
QDate overloads all binary comparison functions (==, !=, >, <, >=, <=) so you can compare two QDates, earlier dates being considered the lesser. The example doesn’t use this functionality, but it can handy for applications where you need to sort dates. Finally, there is support to read or write QDates in QDataStreams.