C++中是否有一个标准的日期/时间类?

36
C++ STL是否有标准时间类?还是我需要在写入流之前将其转换为c字符串?例如,我想将当前日期/时间输出到字符串流中:
time_t tm();
ostringstream sout;
sout << tm << ends;
在这种情况下,我得到的当前日期/时间以数字形式输出,没有任何格式。 我可以使用C运行时函数strftime先格式化tm,但是如果STL具有可以从time_t值实例化的时间类,似乎不应该需要这样做。

3
现在委员会有一个全面、现代化的 C++ 日期/时间/时区提案:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0355r1.html 。这个提案基于这个 Github 存储库:https://github.com/HowardHinnant/date,它拥有完整的实现,完备的文档和活跃的用户社区。 - Howard Hinnant
2
上面评论中提到的库现在已经成为了C++20规范草案的一部分。 - Howard Hinnant
8个回答

24

19

编辑

C++11标准中的“datetime”类是std::chrono::time_point。该问题中的代码应该大致相当于:

const auto now = std::chrono::system_clock::now();
const auto t_c = std::chrono::system_clock::to_time_t(now);
std::cout << std::put_time(std::localtime(&t_c), "%F %T.\n");

旧回答

挑剔一点:STL(标准模板库)处理通用容器和算法等,未来也不太可能包含日期处理和计算类……

C++标准库本身包括STL和先前的C标准库版本。后者通过# include <ctime>提供了一些与日期和时间相关的函数,如上所述。

如果包装(或仅使用)这些功能足够(而且更快),则可以使用它们,而不是引入boost。它们没有任何问题。


1
这个答案不太适用了。 - WBuck
@WBuck 嗯,是的……这确实很“老”。 - mkluwe

8

6

在 <iomanip> 头文件中有 get_timeput_time 两个函数(我猜这些是 C++11 中新增的),它们可以有效地执行字符串格式化或解析任务。


4

嗯,这个问题已经被问了十二年了。现在(在C++20中)它终于有了更好的答案。

是的,在C++20中有几个标准的日期/时间类(不止一个)。每个类在强类型系统中都有不同的用途。例如,std::chrono::zoned_time表示一个std::chrono::time_zone和一个std::chrono::time_point<system_clock, SomeDuration>的配对,表示某个地理区域的本地时间。下面是如何创建并打印您当前时区的本地时间,以最精确的亚秒精度。

cout << zoned_time{current_zone(), system_clock::now()} << '\n';

如果您需要其他地方的当地时间,同样可以轻松获得:
cout << zoned_time{"Africa/Casablanca", system_clock::now()} << '\n';

与以前的C++标准不同,基于system_clocktime_point现在被保证表示UTC时间,忽略闰秒(也称为Unix Time)。因此,要获取当前的UTC时间,只需:

cout << system_clock::now() << '\n';

尽管如果你真的想使用一个zoned_time(例如代码可能是通用的),这也可以工作:

cout << zoned_time{"UTC", system_clock::now()} << '\n';

请参阅https://en.cppreference.com/w/cpp/chrono以了解更多标准日期/时间类。它们都是线程安全的,而且您不再受到秒精度的限制。

关于第一个变量,cl.exe 给我报错 C2679:二进制 '<<':没有找到接受右操作数类型为 'std::chrono::zoned_time<std::chrono::durationstd::chrono::system_clock::rep,std::chrono::system_clock::period,const std::chrono::time_zone *>' 的运算符(或者没有可接受的转换)。 - Stepan Pavlov
1
那看起来像是 MSVC 编译器的错误信息。您需要一个 V19 以及选项:/std:c++latest。示例: https://gcc.godbolt.org/z/8efx6dqrr - Howard Hinnant

4

好的,这是我找到的关于直接将时间写入流的最接近的内容:

time_t t(time(NULL));   // current time
tm tm(*localtime(&t));  

std::locale loc("");    // current user locale
ostringstream sout;
const std::time_put<TCHAR> &tput =
    std::use_facet<std::time_put<TCHAR> >(loc);
tput.put(sout.rdbuf(), sout, _T('\0'), &tm, _T('x'));
sout << ends;

CString sTest(sout.str().c_str());

一个非常有帮助的指南是Apache C++标准库参考手册。 http://stdcxx.apache.org/doc/stdlibref/time-put.html#sec13


4

还有一个ctime(&time_t)方法,它输出字符串(char*)。


1
除非你确实需要那种日期/时间格式,否则这并没有什么帮助。尽管看到它只会让我打哆嗦,我不认为我会想在应用程序中看到它。 - Joey

0
这个线程始于对“可以从time_t值实例化的时间类”的问题。我搜索了一下,看了一下“chrono”。到目前为止,我不能确定是否有一个代表时间的对象。有“system_clock”,“steady_clock”,“clock_time_conversion”,“zoned_time”,... 嗯,这对我来说太令人困惑了,我怀疑Farid Z是否在寻找这样一个复杂的类世界。下面是一个计算当前时间24小时后的日期的示例:
    using namespace std::literals; // enables literal suffixes, e.g. 24h, 1ms, 1s.
 
    const std::chrono::time_point<std::chrono::system_clock> now =
        std::chrono::system_clock::now();
 
    const std::time_t t_c = std::chrono::system_clock::to_time_t(now - 24h);
    std::cout << "24 hours ago, the time was "
              << std::put_time(std::localtime(&t_c), "%F %T.\n") << std::flush;

24小时前,时间是2021-02-15 18:28:52。
这是简化时间使用的解决方案吗?我对“mkluwe”的观点表示同情:“如果使用这些函数[ctime]进行封装(或简单使用)足够(而且更快),而不是引入boost库,那就使用这些函数。它们没有任何问题。”是的,但是在哪里可以找到一个代表时间并封装这些'ctime'函数的C++类呢?我没有成功找到这样的类。因此,我花了一些时间来做这件事,也许现在有人会很高兴找到它。这个类在命名空间'LibCpp'中被命名为'cTime'。
using namespace LibCpp;

cTime timeNow = cTime::now();
stDuration duration24 = stDuration_Ini;
duration24.hours = 24;
cTime duration = cTime::set(duration24);
cTime timeTomorrow = timeNow + duration;
printf("24 hours ago, the time was %s", timeTomorrow.toString().c_str());

有兴趣的话,可以查看https://github.com/OlafSimon/cTime,这是一个代表Unix时间并封装了'ctime'函数的类'cTime'。是的,你可以从一个名为'myTimeT'的'time_t'变量实例化它。
cTime myTime = cTime::set(myTimeT);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接