将std :: string写入可比较的* time *解析器,这可能会失败

时间:2014-06-14 12:02:35

标签: c++ c++11 time-t

我知道size_t是无符号的,因此不允许使用负值,time_t是我所知道的最好的签名,因此我可以将-1分配给size_t。但是,对于time_t,我并不完全确定。如果我通过头文件遵循定义,我最终会在这里:

typedef __time_t time_t;

,然后在这里:

__STD_TYPE __TIME_T_TYPE __time_t;  /* Seconds since the Epoch.  */

最后

#define __TIME_T_TYPE       __SYSCALL_SLONG_TYPE

我不太确定 __ SYSCALL_SLONG_TYPE 是什么,但我猜这是签名长。不幸的是,即使在执行此跟踪之后,我也只能希望其他c ++ 11平台具有相同的实现。我仍然不确定这对所有人来说都是合法且明确的:

size_t foo = -1;

当然,将time_t签名是有意义的,因为可以有负时间偏移,例如模拟时区。但另一方面,让它无符号是有道理的,因为在1970年之后需要花费很多时间来计算。所以常识是两种方式:) googling on time_t返回了这个:

"由于历史原因,它通常被实现为表示自UTC时间1970年1月1日00:00(即,unix时间戳)以来经过的秒数的整数值。虽然库可以使用替代时间表示来实现此类型。"

来源:http://www.cplusplus.com/reference/ctime/time_t/

并在同一页面上:"便携式程序不应直接使用此类型的值,但始终依赖于对标准库元素的调用将它们转换为可移植类型。"

所以time_t在所有系统上都没有明确定义,但是,time()返回time_t:所以我不会是第一个在界面中导出它的人。我应该使用哪种其他类型?

我问这两个原因:

  • 速度:使用结构,如 struct tm 很慢,因为它有更多的字节,因此复制它或将它与另一个struct tm进行比较将比执行速度慢与长期相同。
  • 订购:我想拥有日期的快速数据类型,这样我就可以执行< b确定哪个日期a和b首先出现。

问题:由于time_t不是所有平台上明确定义的时间表示,因此我可以使用哪种数据类型(1)快速和(2)可比较便携?< / p>

例如,关于time_t的排序:

#include <iostream>
#include <ctime>
#include <cstring>

int main() {
    struct tm tm_a, tm_b;
    memset(&tm_a, 0, sizeof(struct tm));
    memset(&tm_b, 0, sizeof(struct tm));
    if(strptime("2014-01-01 12:00:00", "%Y-%m-%d %H:%M:%s", &tm_a) && strptime("2014-01-01 11:59:59", "%Y-%m-%d %H:%M:%s", &tm_b)) {
        if(mktime(&tm_a) > mktime(&tm_b)) std::cout << "time_t ordering OK." << std::endl;
        else std::cout << "time_t ordering tainted" << std::endl;
    } else std::cout << "failed to parse time" << std::endl;
    return 0;
}

所有平台上的time_t都会无污染吗?

3 个答案:

答案 0 :(得分:4)

(time_t)(-1)已经意味着“这不是一个有效的时间”,无论time_t实际是什么。标准函数mktime会在出错时返回此值,您也可以。

C和C ++标准对time_t中的时间编码没有任何说明。标准函数difftimedouble计算时间差,以time_t表示,两次表示为time_t,这是按时间顺序排序time_t值的唯一有福方式。但是,POSIX标准指定time_t是以秒为单位的时间,因此在POSIX系统上,可以直接将<time_t进行比较。

请注意,C和POSIX都允许{{1}}为任何算术类型(不仅仅是整数)。

答案 1 :(得分:1)

如果您需要保证在不同平台之间移植的时间表示,则需要使用或创建一个库来处理您使用的平台之间的差异。

例如Boost.Date_Time,您可以选择它支持的任何表示形式。您甚至可以以独立于平台的方式使用seconds elapsed since epoch(在boost支持的所有平台上)。

答案 2 :(得分:0)

我已经沉迷于optional(通过提升,或根据C ++ 1y tr工作文件推出自己的推文)。

optional<foo>foonullopt。您通过dereerence访问foo,但数据通过联合存储在optional中。我懒惰的实现使用了一个指针,它是foo还是不是&#34;因为这会使调试变得微不足道。

它比标志值更好地传达故障,并在我写的代码中替换了一堆基于指针的标记。