2013-03-27 111 views
2

给定一个输入日期和时间(以字符串格式),我试图用给出的time函数获得它的历元时间,如mktime。将time_t纪元时间转换回日期和时间会导致日期和时间比原始时间少一小时。我经历了一些讨论,说夏时制可能会有一小时的调整。下面是代码:应对夏令时 - C++

//sample strptime program. 

#include <iostream> 
#include <ctime> 
#include <string> 
using namespace std; 

long parseTime(string time) { 

    cout << "Time entered = " << time << endl; 

    long timeSinceEpoch; 

    struct tm t; 

    if(time.find("/") != string::npos) { 
    //format of date is mm/dd/yyyy. followed by clock in hh:mm (24 hour clock). 
    if(strptime(time.c_str(), "%m/%e/%Y %H:%M", &t) == NULL) { 
     cout << "Error. Check string for formatting." << endl; 
    } 
    } else if(time.find("-") != string::npos) { 
    //format of date is yyyy-mm-dd hh:mm:ss (hh in 24 hour clock format). 
    cout << "I am here." << endl; 
    if(strptime(time.c_str(), "%Y-%m-%e %H:%M:%S", &t) == NULL) { 
     cout << "Error. Check string for formatting of new date." << endl; 
    } 
    } 

    cout << "Details of the time structure:" << endl; 
    cout << "Years since 1900 = " << t.tm_year << endl; 
    cout << "Months since January = " << t.tm_mon << endl; 
    cout << "Day of the month = " << t.tm_mday << endl; 
    cout << "Hour = " << t.tm_hour << " Minute = " << t.tm_min << " second = " << t.tm_sec << endl; 

    timeSinceEpoch = mktime(&t); 
    time_t temp = mktime(&t); 
    cout << "Time since epoch = " << timeSinceEpoch << endl; 

    cout << "Reconverting to the time structure:" << endl; 
    struct tm* t2 = localtime(&temp); 
    cout << "Details of the time structure:" << endl; 
    cout << "Years since 1900 = " << t2->tm_year << endl; 
    cout << "Months since January = " << t2->tm_mon << endl; 
    cout << "Day of the month = " << t2->tm_mday << endl; 
    cout << "Hour = " << t2->tm_hour << " Minute = " << t2->tm_min << " second = " << t2->tm_sec << endl; 

    return timeSinceEpoch; 
} 

int main(int argc, char *argv[]) { 

    string date, t; 
    cout << "Enter date: " << endl; 
    cin >> date; 
    cout << "Enter time: " << endl; 
    cin >> t; 

    struct tm time; 
    string overall = date + " " + t; 

    long result = parseTime(overall); 
    cout << "Time in date + time = " << overall << " and since epoch = " << result << endl; 

return 0; 
} 

的麻烦的输入是: 日期:2013年3月11日 时间:4时41分53秒

我的问题(S):
1.检查tm_idst标志返回一个非零值,表示DST生效。但是,我怎么知道正在讨论什么时区?
2.上述时间戳可能没有被记录在同一时区,我在,有没有这样的tm_idst标志设置是否正确,指定时区的方法吗?
3.当我不确定时间戳记录在哪个时区时,我该如何处理DST?

+0

获取时区取决于您的操作系统和C语言库上,没有标准或平台无关的方式得到它。例如,在使用glibc的Linux上,'tm'结构中有一个名为'tm_zone'的额外成员字段,它是一个包含时区缩写的C风格字符串。 – 2013-03-27 19:09:36

+0

@Joachim:我试过'tm_zone'选项,但它似乎不在那里。所以基本上,我只是从时代开始就有时间,重新转换为'struct tm',并且如果有一个小时的差异,则增加3600秒?这是我处理DST的唯一选择吗? – Sriram 2013-03-27 19:22:26

+0

评论 - 如果你接受'ISO'类型的日期,那么正确的输入格式是YYYY-MM-DD(即4 + 2 + 2 **总是***) - 所以解析为'% Y-%m-%d',%e格式在理论上接受单位数字日期的前导空间,而[ISO总是期望两位数的月份和年份](http://en.wikipedia.org/wiki/ ISO_8601)。 – Petesh 2013-03-27 19:47:19

回答

2

Plain C++与时区数据相当稀疏,并且在格式化时没有时区规范,有几个时期您将得到不一致的结果 - 例如,重复的时间跟随时钟回来。这就是为什么它总是建议记录所有时间戳在UTC - 即从未应用时区所记录的时间戳,它在格林尼治标准时间记录,然后备份和反复与价值为显示变量,你必须总掌控。

的Linux/BSD具有可以被用来确定所述时区的一些附加的字段,并从UTC的偏移 - 例如在linux上它是__tm_gmtoff字段,而在BSD(/ Mac OS X)中,它被称为tm_gmtoff

还有一个标记时区的字段,它是linux上的__tm_zone和BSD(/ Mac OS X)中的tm_zone,但该字段仅在获得本地时间时填充。

我改变你的榜样略显不足,得到了以下的输出:

Time entered = 2013-04-05 15:00 
I am here. 
Error. Check string for formatting of new date. 
Details of the time structure: 
Years since 1900 = 113 
Months since January = 3 
Day of the month = 5 
Hour = 15 Minute = 0 second = 0 
gmtoff = 0 
Time since epoch = 1365174000 
Reconverting to the time structure: 
Details of the time structure: 
Years since 1900 = 113 
Months since January = 3 
Day of the month = 5 
Hour = 16 Minute = 0 second = 0 
gmtoff = 3600 
Zone = IST 
Time in date + time = 2013-04-05 15:00 and since epoch = 1365174000 

如果你正在使用Windows此结构中,你将不得不使用另一种机制,不过,因为它不”没有这两个额外的领域。

+0

我在cygwin上。我没有'tm_gmtoff'或'tm_zone'。我有什么选择?从历元时间重新转换成日期时间,并且如果存在原始和重新转换后的时间之间1小时的差异,因为历元添加3600秒的时间? – Sriram 2013-03-27 20:19:15

+0

您只处理UTC的建议很好,但我无法控制时间戳生成。我必须处理数据。我被告知时间戳记录在CST中。 – Sriram 2013-03-27 20:20:50

+0

@Sriram正如我在回答Windows不支持这些领域的末尾提到。我认为你的意思是时间是在CST/CDT,而不是严格的CST。 strptime的cygwin实现是有限的。我会建议使用这种提升 - 它将允许更合理的日期/时间处理。 – Petesh 2013-03-27 21:31:28