35.md 26.3 KB
Newer Older
W
init  
wizardforcel 已提交
1 2 3 4
# Qt5 中的日期和时间

> 原文: [http://zetcode.com/gui/qt5/datetime/](http://zetcode.com/gui/qt5/datetime/)

W
wizardforcel 已提交
5
在 Qt5 C++ 编程教程的这一部分中,我们将讨论时间和日期。
W
init  
wizardforcel 已提交
6 7 8

Qt5 具有`QDate``QTime``QDateTime`类以与日期和时间一起使用。 `QDate`是用于使用公历中的日历日期的类。 它具有确定日期,比较或操纵日期的方法。 `QTime`类使用时钟时间。 它提供了比较时间,确定时间的方法以及其他各种时间操纵方法。 `QDateTime`是将`QDate``QTime`对象结合为一个对象的类。

W
wizardforcel 已提交
9
## 初始化日期和时间对象
W
init  
wizardforcel 已提交
10 11 12 13 14

日期和时间对象可以通过两种基本方式进行初始化。 我们可以在对象构造函数中对其进行初始化,也可以创建空对象并在以后用数据填充它们。

`init.cpp`

W
wizardforcel 已提交
15
```cpp
W
init  
wizardforcel 已提交
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
#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;   
}

```

我们以两种方式初始化日期和时间对象。

W
wizardforcel 已提交
43
```cpp
W
init  
wizardforcel 已提交
44 45 46 47 48 49
QDate dt1(2015, 4, 12);

```

`QDate`对象构造函数采用三个参数:年,月和日。

W
wizardforcel 已提交
50
```cpp
W
init  
wizardforcel 已提交
51 52 53 54 55 56
out << "The date is " << dt1.toString() << endl;

```

日期将打印到控制台。 我们使用`toString()`方法将日期对象转换为字符串。

W
wizardforcel 已提交
57
```cpp
W
init  
wizardforcel 已提交
58 59 60 61 62 63 64
QTime tm2;
tm2.setHMS(13, 52, 45, 155);

```

空的`QTime`对象已创建。 我们使用`setHMS()`方法用数据填充对象。 参数是小时,分钟,秒和毫秒。

W
wizardforcel 已提交
65
```cpp
W
init  
wizardforcel 已提交
66 67 68 69 70 71
out << "The time is " << tm2.toString("hh:mm:ss.zzz") << endl;   

```

我们将`QTime`对象打印到控制台。 我们使用的特定格式还包括毫秒,默认情况下会省略毫秒。

W
wizardforcel 已提交
72
输出:
W
init  
wizardforcel 已提交
73

W
wizardforcel 已提交
74
```cpp
W
init  
wizardforcel 已提交
75 76 77 78 79 80 81 82
$ ./init 
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

```

W
wizardforcel 已提交
83
## 当前日期和时间
W
init  
wizardforcel 已提交
84 85 86 87 88

在以下示例中,我们将当前本地时间和日期打印到控制台。

`curdatetime.cpp`

W
wizardforcel 已提交
89
```cpp
W
init  
wizardforcel 已提交
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
#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;      
}

```

请注意,不得将文件命名为`time.cpp`

W
wizardforcel 已提交
109
```cpp
W
init  
wizardforcel 已提交
110 111 112 113 114 115
QDate cd = QDate::currentDate();

```

`QDate::currentDate()`静态函数返回当前日期。

W
wizardforcel 已提交
116
```cpp
W
init  
wizardforcel 已提交
117 118 119 120 121 122
QTime ct = QTime::currentTime();

```

`QTime::currentTime()`静态函数返回当前时间。

W
wizardforcel 已提交
123
```cpp
W
init  
wizardforcel 已提交
124 125 126 127 128 129 130
out << "Current date is: " << cd.toString() << endl;
out << "Current time is: " << ct.toString() << endl;

```

我们使用`toString()`方法将日期和时间对象转换为字符串。

W
wizardforcel 已提交
131
输出:
W
init  
wizardforcel 已提交
132

W
wizardforcel 已提交
133
```cpp
W
init  
wizardforcel 已提交
134 135 136 137 138 139 140 141 142 143 144 145
$ ./curdatetime 
Current date is: Fri Oct 30 2015
Current time is: 20:55:27

```

## 比较日期

关系运算符可用于比较日期。 我们可以比较他们在日历中的位置。

`comparedates.cpp`

W
wizardforcel 已提交
146
```cpp
W
init  
wizardforcel 已提交
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
#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;
   }   
}

```

该示例比较两个日期。

W
wizardforcel 已提交
170
```cpp
W
init  
wizardforcel 已提交
171 172 173 174 175 176 177
QDate dt1(2015, 4, 5);
QDate dt2(2014, 4, 5);

```

我们有两个不同的日期。

W
wizardforcel 已提交
178
```cpp
W
init  
wizardforcel 已提交
179 180 181 182 183 184 185 186 187 188 189 190
if (dt1 < dt2) {
    out << dt1.toString() << " comes before "
    << dt2.toString() << endl;
} else {
    out << dt1.toString() << " comes after "
    << dt2.toString() << endl;
}   

```

我们使用小于(&lt;)的比较运算符比较日期,并确定其中哪个位于日历的更早位置。

W
wizardforcel 已提交
191
输出:
W
init  
wizardforcel 已提交
192

W
wizardforcel 已提交
193
```cpp
W
init  
wizardforcel 已提交
194 195 196 197 198 199 200
$ ./comparedates 
Sun Apr 5 2015 comes after Sat Apr 5 2014

```

比较运算符也可以轻松用于`QTime``QDateTime`对象。

W
wizardforcel 已提交
201
## 确定闰年
W
init  
wizardforcel 已提交
202

W
wizardforcel 已提交
203
闰年是包含另一天的年份。 日历中额外一天的原因是天文日历年与日历年之间的差异。 日历年正好是 365 天,而天文学年(地球绕太阳公转的时间)是 365.25 天。 相差 6 个小时,这意味着在四年的时间里,我们一天中都没有。 因为我们希望日历与季节同步,所以每四年将 2 月增加一天。 (有例外。)在公历中,闰年的 2 月有 29 天,而不是通常的 28 天。该年持续 366 天,而不是通常的 365 天。
W
init  
wizardforcel 已提交
204

W
wizardforcel 已提交
205
`QDate::isLeapYear()`静态方法确定年份是否为闰年。
W
init  
wizardforcel 已提交
206 207 208

`leapyear.cpp`

W
wizardforcel 已提交
209
```cpp
W
init  
wizardforcel 已提交
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
#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;
       }
   }     
}

```

W
wizardforcel 已提交
230
在示例中,我们有一个年份列表。 我们每年检查是否是闰年。
W
init  
wizardforcel 已提交
231

W
wizardforcel 已提交
232
```cpp
W
init  
wizardforcel 已提交
233 234 235 236
QList<int> years({2010, 2011, 2012, 2013, 2014, 2015, 2016});  

```

W
wizardforcel 已提交
237
我们初始化一个年份列表。 这是 C++  11 构造,因此,我们需要启用 C++  11。 我们需要将`CONFIG += c++11``QMAKE_CXXFLAGS += -std=c++11``QMAKE_CXXFLAGS += -std=c++0x`添加到`.pro`文件。
W
init  
wizardforcel 已提交
238

W
wizardforcel 已提交
239
```cpp
W
init  
wizardforcel 已提交
240 241 242 243 244 245 246 247 248 249
foreach (int year, years) {
    if (QDate::isLeapYear(year)) {
        out << year << " is a leap year" << endl;
    } else {
        out << year << " is not a leap year" << endl;
    }
}    

```

W
wizardforcel 已提交
250
我们遍历列表,确定给定的年份是否为 a 年。 `QDate::isLeapYear()`返回布尔值`true``false`
W
init  
wizardforcel 已提交
251 252 253

`leapyear.pro`

W
wizardforcel 已提交
254
```cpp
W
init  
wizardforcel 已提交
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
######################################################################
# Automatically generated by qmake (3.0) Fri Oct 30 21:01:31 2015
######################################################################

TEMPLATE = app
TARGET = leapyear
INCLUDEPATH += .
CONFIG += c++11

# Input
SOURCES += leapyear.cpp

QT -= gui

```

W
wizardforcel 已提交
271
这是项目文件。 我们添加`CONFIG += c++11`声明以启用 C++  11。 我们用`QT -= gui`禁用了 Qt GUI 模块,因为命令行程序不需要它。
W
init  
wizardforcel 已提交
272

W
wizardforcel 已提交
273
输出:
W
init  
wizardforcel 已提交
274

W
wizardforcel 已提交
275
```cpp
W
init  
wizardforcel 已提交
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
$ ./leapyear 
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

```

## 预定义的日期格式

Qt5 具有一些内置的日期格式。 `QDate`对象的`toString()`方法采用日期格式作为参数。 Qt5 使用的默认日期格式为`Qt::TextDate`

`dateformats.cpp`

W
wizardforcel 已提交
293
```cpp
W
init  
wizardforcel 已提交
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
#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;   
}

```

在示例中,我们显示了当前日期的八种不同日期格式。

W
wizardforcel 已提交
317
```cpp
W
init  
wizardforcel 已提交
318 319 320 321 322 323
out << "Today is " << cd.toString(Qt::ISODate) << endl;

```

在这里,我们以`Qt::ISODate`格式打印当前日期,这是用于显示日期的国际标准。

W
wizardforcel 已提交
324
输出:
W
init  
wizardforcel 已提交
325

W
wizardforcel 已提交
326
```cpp
W
init  
wizardforcel 已提交
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
$ ./dateformats 
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

```

## 自定义日期格式

日期可以用多种其他格式表示。 在 Qt5 中,我们也可以创建自定义日期格式。 `toString()`方法的另一个版本采用格式字符串,我们可以在其中使用各种格式说明符。 例如,`d`指示符代表一天,而不是前导零。 `dd`指示符代表一天,前导零。 下表列出了可用的日期格式表达式:

W
wizardforcel 已提交
343
| 表达式 | 输出量 |
W
init  
wizardforcel 已提交
344
| --- | --- |
W
wizardforcel 已提交
345 346 347 348 349 350
| `d` | 一天中的数字,不带前导零(1 到 31) |
| `dd` | 以带前导零(01 到 31)的数字表示的日期 |
| `ddd` | 本地化日期的缩写(例如,“周一”到“周日”)。 使用`QDate::shortDayName()`。 |
| `dddd` | 本地化的长名称(例如,“星期一”到“星期日”)。 使用`QDate::longDayName()`。 |
| `M` | 以不带前导零(1 到 12)的数字表示的月份 |
| `MM` | 月份,以前导零(01 到 12)开头的数字 |
W
wizardforcel 已提交
351
| `MMM` | 本地化月份的缩写名称(例如,“`Jan`”到“`Dec`”)。 使用`QDate::shortMonthName()`。 |
W
wizardforcel 已提交
352 353 354
| `MMMM` | 本地化的长月份名称(例如,“一月”到“十二月”)。 使用`QDate::longMonthName()`。 |
| `y` | 年份为两位数(00 到 99) |
| `yyyy` | 年份为四位数。 如果年份为负数,则还会附加一个减号。 |
W
init  
wizardforcel 已提交
355 356 357 358 359

Table: Date format specifiers

`customdateformats.cpp`

W
wizardforcel 已提交
360
```cpp
W
init  
wizardforcel 已提交
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
#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; 
}

```

我们有四种自定义日期格式。

W
wizardforcel 已提交
380
```cpp
W
init  
wizardforcel 已提交
381 382 383 384 385 386
out << "Today is " << cd.toString("yyyy-MM-dd") << endl;

```

这是国际日期格式。 日期的各部分用破折号分隔。 `yyyy`是具有四个数字的年份。 `MM`是月份,前导零(01 到 12)。 `dd`是带前导零(01 到 31)的数字的日子。

W
wizardforcel 已提交
387
```cpp
W
init  
wizardforcel 已提交
388 389 390 391
out << "Today is " << cd.toString("yy/M/dd") << endl;

```

W
wizardforcel 已提交
392
这是另一种常见的日期格式。 零件之间用斜杠(`/`)字符分隔。 `M`指示符代表一个月,不带前导零(1 到 12)。
W
init  
wizardforcel 已提交
393

W
wizardforcel 已提交
394
```cpp
W
init  
wizardforcel 已提交
395 396 397 398 399 400
out << "Today is " << cd.toString("d. M. yyyy") << endl;

```

此日期格式在斯洛伐克使用。 零件由点字符分隔。 日和月没有前导零。 首先是日期,然后是月份,最后是年份。

W
wizardforcel 已提交
401
输出:
W
init  
wizardforcel 已提交
402

W
wizardforcel 已提交
403
```cpp
W
init  
wizardforcel 已提交
404 405 406 407 408 409 410 411 412 413 414 415 416 417
$ ./customdateformats 
Today is 2015-10-31
Today is 15/10/31
Today is 31\. 10\. 2015
Today is 31-October-2015

```

## 预定义的时间格式

时间具有一些预定义的格式。 标准格式说明符与日期格式中使用的说明符相同。 Qt5 使用的默认时间格式为`Qt::TextDate`

`timeformats.cpp`

W
wizardforcel 已提交
418
```cpp
W
init  
wizardforcel 已提交
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
#include <QTextStream>
#include <QTime>

int main(void) {

   QTextStream out(stdout);

   QTime ct = QTime::currentTime();

   out << "The time is " << ct.toString(Qt::TextDate) << endl;
   out << "The time is " << ct.toString(Qt::ISODate) << endl;
   out << "The time is " << ct.toString(Qt::SystemLocaleShortDate) << endl;
   out << "The time is " << ct.toString(Qt::SystemLocaleLongDate) << endl;
   out << "The time is " << ct.toString(Qt::DefaultLocaleShortDate) << endl;
   out << "The time is " << ct.toString(Qt::DefaultLocaleLongDate) << endl;
   out << "The time is " << ct.toString(Qt::SystemLocaleDate) << endl;
   out << "The time is " << ct.toString(Qt::LocaleDate) << endl;   
}

```

在示例中,我们显示了当前时间的八种不同时间格式。

W
wizardforcel 已提交
442
```cpp
W
init  
wizardforcel 已提交
443 444 445 446 447 448
out << "The time is " << ct.toString(Qt::ISODate) << endl;

```

在这里,我们以`Qt::ISODate`格式打印当前时间,这是用于显示时间的国际标准。

W
wizardforcel 已提交
449
输出:
W
init  
wizardforcel 已提交
450

W
wizardforcel 已提交
451
```cpp
W
init  
wizardforcel 已提交
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
$ ./timeformats 
The time is 15:58:26
The time is 15:58:26
The time is 3:58 PM
The time is 3:58:26 PM CET
The time is 3:58 PM
The time is 3:58:26 PM CET
The time is 3:58 PM
The time is 3:58 PM

```

## 自定义时间格式

我们可以创建其他时间格式。 我们在使用时间格式说明符的地方构建自定义时间格式。 下表列出了可用的格式表达式。

W
wizardforcel 已提交
468
| 表达式 | 输出量 |
W
init  
wizardforcel 已提交
469
| --- | --- |
W
wizardforcel 已提交
470 471 472 473
| `h` | 没有前导零的小时(如果显示 AM/PM,则为 0 到 23 或 1 到 12) |
| `hh` | 带前导零的小时(如果显示 AM/PM,则为 00 到 23 或 01 到 12) |
| `H` | 没有前导零的小时(0 到 23,即使有 AM/PM 显示) |
| `HH` | 带前导零的小时(00 到 23,即使有 AM/PM 显示) |
W
wizardforcel 已提交
474 475 476 477 478 479
| `m` | 没有前导零(0 到 59)的分钟 |
| `mm` | 分钟,前导零(00 到 59) |
| `s` | 秒,不带前导零(0 到 59) |
| `ss` | 秒,带有前导零(00 到 59) |
| `z` | 不带前导零的毫秒数(0 到 999) |
| `zz` | 以零开头的毫秒数(000 到 999) |
W
wizardforcel 已提交
480 481
| `AP``A` | 使用 AM/PM 显示。 `AP` 将被“`AM`”或“`PM`”替换。 |
| `ap``a` | 使用 am/pm 显示。 `ap` 将被“`am`”或“`pm`”替换。 |
W
wizardforcel 已提交
482
| `t` | 时区(例如“ CEST”) |
W
init  
wizardforcel 已提交
483 484 485 486 487

Table: Time format specifiers

`customtimeformats.cpp`

W
wizardforcel 已提交
488
```cpp
W
init  
wizardforcel 已提交
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
#include <QTextStream>
#include <QTime>

int main(void) {

   QTextStream out(stdout);

   QTime ct = QTime::currentTime();

   out << "The time is " << ct.toString("hh:mm:ss.zzz") << endl;
   out << "The time is " << ct.toString("h:m:s a") << endl;
   out << "The time is " << ct.toString("H:m:s A") << endl;
   out << "The time is " << ct.toString("h:m AP") << endl;  

   out << "The version of Qt5 is " << qVersion() << endl;
}

```

我们有四种自定义时间格式。

W
wizardforcel 已提交
510
```cpp
W
init  
wizardforcel 已提交
511 512 513 514 515 516
out << "The time is " << ct.toString("hh:mm:ss.zzz") << endl;

```

在这种格式下,我们具有小时,分钟和秒,前导零。 我们还以毫秒为单位加上前导零。

W
wizardforcel 已提交
517
```cpp
W
init  
wizardforcel 已提交
518 519 520 521
out << "The time is " << ct.toString("h:m:s a") << endl;

```

W
wizardforcel 已提交
522
此时间格式说明符使用小时,分钟和秒(不带前导零),并添加 AM/PM 周期标识符。
W
init  
wizardforcel 已提交
523

W
wizardforcel 已提交
524
输出:
W
init  
wizardforcel 已提交
525

W
wizardforcel 已提交
526
```cpp
W
init  
wizardforcel 已提交
527 528 529 530 531 532 533 534 535 536 537 538 539 540
$ ./customtimeformats 
The time is 16:23:43.542
The time is 4:23:43 pm
The time is 16:23:43 PM
The time is 4:23 PM

```

## 检索工作日

`dayOfWeek()`方法返回一个代表星期几的数字,其中 1 是星期一,7 是星期日。

`weekday.cpp`

W
wizardforcel 已提交
541
```cpp
W
init  
wizardforcel 已提交
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
#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;          
}

```

在示例中,我们打印当前工作日的简称和长名称。

W
wizardforcel 已提交
560
```cpp
W
init  
wizardforcel 已提交
561 562 563 564 565 566
QDate cd = QDate::currentDate();

```

我们得到当前日期。

W
wizardforcel 已提交
567
```cpp
W
init  
wizardforcel 已提交
568 569 570 571 572 573
int wd = cd.dayOfWeek();

```

从当前日期开始,我们得到星期几。

W
wizardforcel 已提交
574
```cpp
W
init  
wizardforcel 已提交
575 576 577 578 579 580
out << "Today is " << QDate::shortDayName(wd) << endl;

```

使用`QDate::shortDayName()`静态方法,我们得到工作日的简称。

W
wizardforcel 已提交
581
```cpp
W
init  
wizardforcel 已提交
582 583 584 585 586 587
out << "Today is " << QDate::longDayName(wd) << endl;    

```

使用`QDate::longDayName()`静态方法,我们获得了工作日的长名称。

W
wizardforcel 已提交
588
输出:
W
init  
wizardforcel 已提交
589

W
wizardforcel 已提交
590
```cpp
W
init  
wizardforcel 已提交
591 592 593 594 595 596 597 598 599 600 601 602
$ ./weekday 
Today is Sat
Today is Saturday

```

## 天数

我们可以使用`daysInMonth()`方法计算特定月份中的天数,并使用`daysInYear()`方法计算一年中的天数。

`nofdays.cpp`

W
wizardforcel 已提交
603
```cpp
W
init  
wizardforcel 已提交
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
#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;         
}

```

创建了五个日期对象。 我们计算这些月份和特定年份的天数。

W
wizardforcel 已提交
650
```cpp
W
init  
wizardforcel 已提交
651 652 653 654 655 656 657 658 659 660
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);

```

创建了五个`QDate`对象。 每个代表不同的日期。

W
wizardforcel 已提交
661
```cpp
W
init  
wizardforcel 已提交
662 663 664 665 666 667 668
out << "There are " << dt1.daysInMonth() << " days in " 
    << months.at(dt1.month()-1) << endl;   

```

我们使用`daysInMonth()`方法获取日期对象中的天数。

W
wizardforcel 已提交
669
```cpp
W
init  
wizardforcel 已提交
670 671 672 673 674 675 676
out << "There are " << dt1.daysInYear() << " days in year " 
    << QString::number(dt1.year()) << endl;      

```

在这里,我们使用日期对象的`daysInYear()`方法获得一年中的天数。

W
wizardforcel 已提交
677
输出:
W
init  
wizardforcel 已提交
678

W
wizardforcel 已提交
679
```cpp
W
init  
wizardforcel 已提交
680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695
$ ./nofdays 
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

```

## 检查日期的有效性

`isValid()`方法可以检查日期是否有效。

`validity.cpp`

W
wizardforcel 已提交
696
```cpp
W
init  
wizardforcel 已提交
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720
#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;
       }
    }
}

```

在示例中,我们检查了三天的有效性。

W
wizardforcel 已提交
721
```cpp
W
init  
wizardforcel 已提交
722 723 724 725 726 727 728
QList<QDate> dates({QDate(2015, 5, 11), QDate(2015, 8, 1),
    QDate(2015, 2, 30)});

```

前两天有效。 第三个无效。 2 月有 28 或 29 天。

W
wizardforcel 已提交
729
```cpp
W
init  
wizardforcel 已提交
730 731 732 733 734 735 736 737 738 739
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;
}

```

根据`isValid()`方法的结果,我们将有关日期有效性的消息打印到控制台。

W
wizardforcel 已提交
740
输出:
W
init  
wizardforcel 已提交
741

W
wizardforcel 已提交
742
```cpp
W
init  
wizardforcel 已提交
743 744 745 746 747 748 749
$ ./validity 
Date 1 is a valid date
Date 2 is a valid date
Date 3 is not a valid date

```

W
wizardforcel 已提交
750
## 到...的天数
W
init  
wizardforcel 已提交
751 752 753 754 755

我们可以轻松地从特定日期算起 n 天的日期。 我们使用`addDays()`方法。 `daysTo()`方法返回到选定日期的天数。

`daystofrom.cpp`

W
wizardforcel 已提交
756
```cpp
W
init  
wizardforcel 已提交
757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778
#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;       
}

```

从 2015 年 5 月 11 日起,我们将在 55 天后获得日期。我们还将获得圣诞节前的天数。

W
wizardforcel 已提交
779
```cpp
W
init  
wizardforcel 已提交
780 781 782 783 784 785 786
QDate dt(2015, 5, 11);  
QDate nd = dt.addDays(55);

```

`addDays()`方法返回给定日期之后 55 天的`QDate`

W
wizardforcel 已提交
787
```cpp
W
init  
wizardforcel 已提交
788 789 790 791 792 793 794 795 796
QDate xmas(2015, 12, 24);
...
out << "There are " << QDate::currentDate().daysTo(xmas) 
    << " days till Christmas" << endl; 

```

我们使用`daysTo()`方法来计算直到圣诞节的天数。

W
wizardforcel 已提交
797
输出:
W
init  
wizardforcel 已提交
798

W
wizardforcel 已提交
799
```cpp
W
init  
wizardforcel 已提交
800 801 802 803 804 805
$ ./daystofrom 
55 days from Mon May 11 2015 is Sun Jul 5 2015
There are 54 days till Christmas

```

W
wizardforcel 已提交
806
## `QDateTime`类
W
init  
wizardforcel 已提交
807 808 809 810 811

`QDateTime`对象包含日历日期和时钟时间。 它是`QDate``QTime`类的组合。 它有许多相似的方法,用法与这两类相同。

`datetime.cpp`

W
wizardforcel 已提交
812
```cpp
W
init  
wizardforcel 已提交
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829
#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;   
}

```

该示例检索当前日期时间。

W
wizardforcel 已提交
830
```cpp
W
init  
wizardforcel 已提交
831 832 833 834 835 836
out << "The current datetime is " << cdt.toString() << endl;

```

这行代码将当前日期时间打印到终端。

W
wizardforcel 已提交
837
```cpp
W
init  
wizardforcel 已提交
838 839 840 841
out << "The current date is " << cdt.date().toString() << endl;

```

W
wizardforcel 已提交
842
此行使用`date()`方法检索日期时间对象的日期部分。
W
init  
wizardforcel 已提交
843

W
wizardforcel 已提交
844
输出:
W
init  
wizardforcel 已提交
845

W
wizardforcel 已提交
846
```cpp
W
init  
wizardforcel 已提交
847 848 849 850 851 852 853 854 855
$ ./datetime 
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

```

## 朱利安日

W
wizardforcel 已提交
856
儒略日是指儒略时期开始以来的连续天数。 它主要由天文学家使用。 不应将其与朱利安历法相混淆。 朱利安纪元开始于公元前 4713 年。 朱利安天数 0 被指定为从公元前 4713 年 1 月 1 日正午开始的那一天。 朱利安天数(JDN)是自此时间段开始以来经过的天数。 任意时刻的儒略日期(JD)是前一个正午的儒略日编号加上该时刻以来的那一天的分数。 (Qt5 不会计算此分数。)除天文学外,军事和大型机程序经常使用儒略日期。
W
init  
wizardforcel 已提交
857 858 859

`julianday.cpp`

W
wizardforcel 已提交
860
```cpp
W
init  
wizardforcel 已提交
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877
#include <QTextStream>
#include <QDate>

int main(void) {

   QTextStream out(stdout);

   QDate cd = QDate::currentDate();

   out << "Gregorian date for today: " << cd.toString(Qt::ISODate) << endl;
   out << "Julian day for today: " << cd.toJulianDay() << endl;                
}

```

在示例中,我们计算了今天的公历日期和儒略日。

W
wizardforcel 已提交
878
```cpp
W
init  
wizardforcel 已提交
879 880 881 882 883 884
out << "Julian day for today: " << cd.toJulianDay() << endl;

```

使用`toJulianDay()`方法返回儒略日。

W
wizardforcel 已提交
885
输出:
W
init  
wizardforcel 已提交
886

W
wizardforcel 已提交
887
```cpp
W
init  
wizardforcel 已提交
888 889 890 891 892 893 894 895 896 897
$ ./julianday 
Gregorian date for today: 2015-10-31
Julian day for today: 2457327

```

使用儒略日期,很容易进行计算。

`battles.cpp`

W
wizardforcel 已提交
898
```cpp
W
init  
wizardforcel 已提交
899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
#include <QTextStream>
#include <QDate>

int main(void) {

   QTextStream out(stdout);

   QDate bordate(1812, 9, 7);
   QDate slavdate(1805, 12, 2);

   QDate cd = QDate::currentDate();

   int j_today = cd.toJulianDay();
   int j_borodino = bordate.toJulianDay();
   int j_slavkov = slavdate.toJulianDay();

   out << "Days since Slavkov battle: " << j_today - j_slavkov << endl;
   out << "Days since Borodino battle: " << j_today - j_borodino << endl;
}

```

该示例计算自两次历史事件以来经过的天数。

W
wizardforcel 已提交
923
```cpp
W
init  
wizardforcel 已提交
924 925 926 927 928
QDate bordate(1812, 9, 7);
QDate slavdate(1805, 12, 2);

```

W
wizardforcel 已提交
929
我们有拿破仑纪元的两次战斗。
W
init  
wizardforcel 已提交
930

W
wizardforcel 已提交
931
```cpp
W
init  
wizardforcel 已提交
932 933 934 935 936 937 938 939
int j_today = cd.toJulianDay();
int j_borodino = bordate.toJulianDay();
int j_slavkov = slavdate.toJulianDay();

```

我们计算了今天以及斯拉夫科夫和波罗底诺战役的儒略日。

W
wizardforcel 已提交
940
```cpp
W
init  
wizardforcel 已提交
941 942 943 944 945 946 947
out << "Days since Slavkov battle: " << j_today - j_slavkov << endl;
out << "Days since Borodino battle: " << j_today - j_borodino << endl; 

```

我们计算了两次战斗以来经过的天数。

W
wizardforcel 已提交
948
输出:
W
init  
wizardforcel 已提交
949

W
wizardforcel 已提交
950
```cpp
W
init  
wizardforcel 已提交
951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968
$ date
Sat Oct 31 20:07:32 CET 2015
$ ./battles 
Days since Slavkov battle: 76669
Days since Borodino battle: 74198

```

自 2015 年 10 月 31 日起,斯拉夫科夫战役已经过去了 76669 天,而波罗底诺战役已经过去了 74198 天。

## UTC 时间

我们的星球是一个球体。 它绕其轴旋转。 地球向东旋转。 因此,太阳在不同位置的不同时间升起。 地球大约每 24 小时旋转一次。 因此,世界被划分为 24 个时区。 在每个时区,都有一个不同的本地时间。 夏令时通常会进一步修改此本地时间。

实际需要一个全球时间。 全球时间可以避免时区和夏令时的混淆。 UTC(世界标准时间)被选为主要时间标准。 UTC 用于航空,天气预报,飞行计划,空中交通管制通关和地图。 与当地时间不同,UTC 不会随季节变化而变化。

`utclocal.cpp`

W
wizardforcel 已提交
969
```cpp
W
init  
wizardforcel 已提交
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
#include <QTextStream>
#include <QDateTime>

int main(void) {

  QTextStream out(stdout);

  QDateTime cdt = QDateTime::currentDateTime();   

  out << "Universal datetime: " << cdt.toUTC().toString() << endl;
  out << "Local datetime: " << cdt.toLocalTime().toString() << endl;
}

```

在示例中,我们计算当前日期时间。 我们用 UTC 日期时间和本地日期时间表示日期时间。

W
wizardforcel 已提交
987
```cpp
W
init  
wizardforcel 已提交
988 989 990 991 992 993
out << "Universal datetime" << cdt.toUTC().toString() << endl;

```

`toUTC()`方法用于获取 UTC 日期时间。

W
wizardforcel 已提交
994
```cpp
W
init  
wizardforcel 已提交
995 996 997 998 999 1000
out << "Local datetime" << cdt.toLocalTime().toString() << endl;

```

`toLocalTime()`用于获取本地日期时间。

W
wizardforcel 已提交
1001
输出:
W
init  
wizardforcel 已提交
1002

W
wizardforcel 已提交
1003
```cpp
W
init  
wizardforcel 已提交
1004 1005 1006 1007 1008 1009 1010 1011
$ ./utclocal 
Universal datetime: Sat Oct 31 19:09:44 2015 GMT
Local datetime: Sat Oct 31 20:09:44 2015

```

该示例在布拉迪斯拉发运行,该站点的中欧时间(CET)为 UTC + 1 小时。

W
wizardforcel 已提交
1012
## Unix 纪元
W
init  
wizardforcel 已提交
1013

W
wizardforcel 已提交
1014
纪元是选择作为特定纪元起源的时间瞬间。 例如,在西方基督教国家,时间从耶稣出生的第 0 天开始。 另一个例子是法国共和党日历,使用了十二年。 这个时期是 1792 年 9 月 22 日宣布的共和纪元的开始,即宣布成立第一共和国并废除君主制的那一天。
W
init  
wizardforcel 已提交
1015

W
wizardforcel 已提交
1016
电脑也有自己的纪元。 最受欢迎的版本之一是 Unix 纪元。 Unix 纪元是 1970 年 1 月 1 日 UTC 时间 00:00:00(或`1970-01-01T00:00:00Z ISO8601`)。 计算机中的日期和时间是根据自该计算机或平台的定义时期以来经过的秒数或时钟滴答数确定的。
W
init  
wizardforcel 已提交
1017

W
wizardforcel 已提交
1018
Unix 时间 是自 Unix 纪元以来经过的秒数。
W
init  
wizardforcel 已提交
1019

W
wizardforcel 已提交
1020
```cpp
W
init  
wizardforcel 已提交
1021 1022 1023 1024 1025
$ date +%s
1446318984

```

W
wizardforcel 已提交
1026
Unix date 命令可用于获取 Unix 时间。 在这个特定时刻,自 Unix 纪元以来已经过去了 1446318984 秒。
W
init  
wizardforcel 已提交
1027 1028 1029

`unixepoch.cpp`

W
wizardforcel 已提交
1030
```cpp
W
init  
wizardforcel 已提交
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
#include <QTextStream>
#include <QDateTime>
#include <ctime>

int main(void) {

  QTextStream out(stdout);

  time_t t = time(0);  
  out << t << endl;

  QDateTime dt;
  dt.setTime_t(t);
  out << dt.toString() << endl;

  QDateTime cd = QDateTime::currentDateTime();
  out << cd.toTime_t() << endl;       
}

```

在示例中,我们使用两个 Qt5 函数获取 Unix 时间并将其转换为人类可读的形式。

W
wizardforcel 已提交
1054
```cpp
W
init  
wizardforcel 已提交
1055 1056 1057 1058
#include <ctime>

```

W
wizardforcel 已提交
1059
我们包括标准的 C++ 时间头文件。
W
init  
wizardforcel 已提交
1060

W
wizardforcel 已提交
1061
```cpp
W
init  
wizardforcel 已提交
1062 1063 1064 1065 1066
time_t t = time(0);  
out << t << endl;

```

W
wizardforcel 已提交
1067
使用标准的 C++  `time()`命令,我们可以获得 Unix 时间。
W
init  
wizardforcel 已提交
1068

W
wizardforcel 已提交
1069
```cpp
W
init  
wizardforcel 已提交
1070 1071 1072 1073 1074 1075
QDateTime dt;
dt.setTime_t(t);
out << dt.toString() << endl;

```

W
wizardforcel 已提交
1076
`setTime_t()`方法用于将 Unix 时间转换为日期时间,并将其格式化为易于阅读的格式。
W
init  
wizardforcel 已提交
1077

W
wizardforcel 已提交
1078
```cpp
W
init  
wizardforcel 已提交
1079 1080 1081 1082 1083 1084 1085
QDateTime cd = QDateTime::currentDateTime();
out << cd.toTime_t() << endl; 

```

Qt5 的`toTime_t()`方法也可以用来获取 Unix 时间。

W
wizardforcel 已提交
1086
输出:
W
init  
wizardforcel 已提交
1087

W
wizardforcel 已提交
1088
```cpp
W
init  
wizardforcel 已提交
1089 1090 1091 1092 1093 1094 1095 1096
$ ./unixepoch 
1446319003
Sat Oct 31 20:16:43 2015
1446319003

```

在本章中,我们处理了时间和日期。