C++ 日期和时间

日期和时间

<ctime> 库允许我们处理日期和时间。

要使用它,您必须导入 <ctime> 头文件:

实例

#include <ctime> // 导入ctime库

显示当前日期和时间

<ctime> 库具有多种用于测量日期和时间的函数。

time() 函数为我们提供了表示当前日期和时间的时间戳。我们可以使用 ctime() 函数来显示时间戳所代表的日期和时间:

实例

显示当前日期:

// 获取当前日期和时间的时间戳
time_t timestamp;
time(&timestamp);

// 显示时间戳所代表的日期和时间
cout << ctime(&timestamp);

亲自试一试

time() 函数的两种使用方式

time() 函数将时间戳写入由参数给定的内存位置,但它也返回时间戳的值。

使用 time() 函数的另一种方法是传入一个空指针并使用返回值。

time_t timestamp = time(NULL);

数据类型

有两种不同的数据类型用于存储日期和时间:time_t 用于时间戳struct tm 用于日期时间结构

时间戳以单个数字表示时刻,这使得计算机更容易进行计算。

日期时间结构是表示日期和时间的不同组件作为成员的结构。这使我们更容易指定日期。日期时间结构具有以下成员:

  • tm_sec - 分钟内的秒数
  • tm_min - 小时内的分钟数
  • tm_hour - 一天内的小时数(从 0 到 23)
  • tm_mday - 月份中的天数
  • tm_mon - 月份(从 0 到 11,从 1 月开始)
  • tm_year - 自 1900 年以来的年数
  • tm_wday - 一周中的天数(从 0 到 6,从周日开始)
  • tm_yday - 一年中的天数(从 0 到 365,0 代表 1 月 1 日)
  • tm_isdst - 夏令时有效时为正值,无效时为0,未知时为负值

请始终牢记日期组件的表示方式:

  • 小时采用 24 小时制。11pm 会表示为 23
  • 月份从 0 到 11。例如,12 月会表示为 11 而不是 12。
  • 年份是相对于 1900 年表示的。2024 年会表示为 124,因为自 1900 年以来已经过去了 124 年。

创建时间戳

time() 函数只能为当前日期创建时间戳,但我们可以使用 mktime() 函数为任何日期创建时间戳。

mktime() 函数将日期时间结构转换为时间戳。

实例

使用 mktime() 函数创建时间戳:

struct tm datetime;
time_t timestamp;

datetime.tm_year = 2023 - 1900; // 自 1900 年以来的年数
datetime.tm_mon = 12 - 1; // 自 1 月以来的月数
datetime.tm_mday = 17;
datetime.tm_hour = 12;
datetime.tm_min = 30;
datetime.tm_sec = 1;
// 必须指定夏令时
// -1 使用计算机的时区设置
datetime.tm_isdst = -1;

timestamp = mktime(&datetime);

cout << ctime(&timestamp);

亲自试一试

注意:mktime() 函数需要这些成员具有值:tm_yeartm_montm_mdaytm_hourtm_mintm_sectm_isdst

创建日期时间结构

mktime() 函数还会用正确的值填充日期时间结构的 tm_wdaytm_yday 成员,从而完成结构并给出有效的日期时间。例如,它可以用来查找给定日期的星期几:

实例

查找指定日期的星期几:

// 创建日期时间结构并使用 mktime 填充缺失的成员
struct tm datetime;
datetime.tm_year = 2023 - 1900; // 自 1900 年以来的年数
datetime.tm_mon = 12 - 1; // 自 1 月以来的月数
datetime.tm_mday = 17;
datetime.tm_hour = 0; datetime.tm_min = 0; datetime.tm_sec = 0;
datetime.tm_isdst = -1;
mktime(&datetime);

string weekdays[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

cout << "The date is on a " << weekdays[datetime.tm_wday];

亲自试一试

localtime()gmtime() 函数可以将时间戳转换为日期时间结构。

localtime() 函数返回指向表示计算机时区时间的结构的指针。

gmtime() 函数返回指向表示GMT时区时间的结构的指针。

这些函数返回指向日期时间结构的指针。如果我们想确保其值不会意外更改,我们应该通过解引用指针来复制它。如需了解解引用,请参阅 C++ 解引用教程

实例

获取日期时间结构并输出当前小时:

time_t timestamp = time(&timestamp);
struct tm datetime = *localtime(&timestamp);

cout << datetime.tm_hour;

亲自试一试

显示日期

到目前为止,我们一直在使用 ctime() 函数来显示时间戳中包含的日期。为了从日期时间结构中显示日期,我们可以使用 asctime() 函数。

实例

显示日期时间结构所代表的日期:

time_t timestamp = time(NULL);
struct tm datetime = *localtime(&timestamp);

cout << asctime(&datetime);

亲自试一试

注意:asctime() 函数不会校正无效的日期。例如,如果您将月份中的天数设置为 32,它将显示 32。mktime() 函数可以校正这类错误:

实例

在显示之前校正日期:

// 创建日期时间结构并使用 mktime 校正错误
struct tm datetime;
datetime.tm_year = 2022 - 1900; // 自1900年以来的年数
datetime.tm_mon = 0; // 0是1月
datetime.tm_mday = 32;
datetime.tm_hour = 0; datetime.tm_min = 0; datetime.tm_sec = 0;
datetime.tm_isdst = -1;
mktime(&datetime);

cout << asctime(&datetime);

亲自试一试

ctime()asctime() 函数允许我们显示日期,但它们不允许我们选择显示方式。

为了选择日期的显示方式,我们可以使用 strftime() 函数。

实例

以不同的方式表示当前日期:

time_t timestamp = time(NULL);
struct tm datetime = *localtime(&timestamp);

char output[50];

strftime(output, 50, "%B %e, %Y", &datetime);
cout << output << "\n";

strftime(output, 50, "%I:%M:%S %p", &datetime);
cout << output << "\n";

strftime(output, 50, "%m/%d/%y", &datetime);
cout << output << "\n";

strftime(output, 50, "%a %b %e %H:%M:%S %Y", &datetime);
cout << output << "\n";

亲自试一试

strftime() 函数格式化日期并将其作为 C 风格字符串写入字符数组。它有四个参数:

  1. 第一个参数指向将写入格式化日期的字符数组。
  2. 第二个参数指定数组中可用的空间。
  3. 第三个参数允许我们使用格式说明符选择日期的格式化方式。
  4. 最后一个参数是指向包含我们要显示的日期的日期时间结构的指针。

下表包含一些有用的格式说明符。有关更完整的列表,请查看 strftime() 参考页面

格式说明符 描述 例子
%a 星期几的简短表示 Fri
%b 月份名称的简短表示 Dec
%B 月份名称的完整表示 December
%d 月份中的天数,前面补零 09
%e 月份中的天数,前面补空格 9
%H 24 小时制的小时 14
%I 12 小时制的小时 02
%M 小时内的分钟数 30
%p AM 或 PM PM
%S 分钟内的秒数 01
%y 2 位数的年份表示 23
%Y 4 位数的年份表示 2023

时间测量

有两种不同的函数可用于测量时间差异。

difftime() 函数

该函数用于测量两个不同时间戳之间经过的秒数。在测量日期之间的时间差时,此函数非常有用。

实例

测量两个时间戳之间的时间差:

time_t now;  
time_t nextyear;  
struct tm datetime;  
  
now = time(NULL);  // 获取当前时间  
datetime = *localtime(&now);  // 将当前时间转换为本地时间结构  
datetime.tm_year = datetime.tm_year + 1;  // 将年份增加一年  
datetime.tm_mon = 0;  // 设置月份为1月(注意:tm_mon从0开始)  
datetime.tm_mday = 1;  // 设置日期为1日  
datetime.tm_hour = 0;  // 设置小时为0点  
datetime.tm_min = 0;  // 设置分钟为0分  
datetime.tm_sec = 0;  // 设置秒数为0秒  
datetime.is_dst = -1;  // 自动调整夏令时  
nextyear = mktime(&datetime);  // 将时间结构转换为时间戳  
  
int diff = difftime(nextyear, now);  // 计算时间差  
  
cout << diff << " seconds until next year";  // 输出到下一年的时间差(秒)

亲自试一试

clock() 函数

该函数在程序运行时用于测量短时间段,比 difftime() 函数更精确。

每次调用 clock 函数时,都会返回一个特殊的时间戳,以时钟周期(一种取决于库实现方式的时间单位)为单位,其数据类型为 clock_t。为了测量时间差,需要在两个不同的时间点存储时间戳,然后相减。时间差以时钟周期为单位测量,但可以通过除以 CLOCKS_PER_SEC 常量将其转换为秒。

实例

测量程序运行所需的时间:

clock_t before = clock();  // 记录开始时间  
int k = 0;  
for(int i = 0; i < 100000; i++) {  
  k += i;  // 执行一些操作  
}  
clock_t duration = clock() - before;  // 计算时间差  
cout << "Duration: " << (float)duration / CLOCKS_PER_SEC << " seconds";  // 输出运行时间(秒)

亲自试一试

注意:在除法运算之前,请确保将值转换为 floatdouble 类型,否则可能会导致整数除法,从而截断小数部分。

完整的 <ctime> 参考手册

如需获取 <ctime> 函数的完整参考,请访问我们的 C++ <ctime> 参考手册