我有一个时间,表示为自1970年1月1日午夜( UTC )以来经过的秒数(先前调用time ()的结果)。我该如何增加一天的时间呢?
添加24 * 60 * 60在大多数情况下都有效,但如果夏令时在两者之间打开或关闭,则会失败。换句话说,我主要想增加24小时,但有时是23或25小时。
为了说明-该程序:
#include <time.h>
#include <iostream>
int main()
{
time_t base = 1142085600;
for(int i = 0; i < 4; ++i) {
time_t time = base + i * 24 * 60 * 60;
std::cout << ctime(&time);
}
return 0;
}
产生:
Sat Mar 11 08:00:00 2006
Sun Mar 12 09:00:00 2006
Mon Mar 13 09:00:00 2006
Tue Mar 14 09:00:00 2006
我想要3月12日,13日的《纽约时报》...也是上午8点
FigBug提供的答案给我指明了正确的方向。但我不得不使用localtime而不是gmtime。
int main()
{
time_t base = 1142085600;
for(int i = 0; i < 4; ++i) {
struct tm* tm = localtime(&base);
tm->tm_mday += i;
std::cout << asctime(tm);
}
return 0;
}
给我:
Sat Mar 11 08:00:00 2006
Sat Mar 12 08:00:00 2006
Sat Mar 13 08:00:00 2006
Sat Mar 14 08:00:00 2006
这就是我想要的。使用gmtime可以得到14:00:00的时间
但是,请注意,所有的日子都是星期六。如果我抛出mktime函数,我又回到了开始的地方:
#include <time.h>
#include <iostream>
int main()
{
time_t base = 1142085600;
for(int i = 0; i < 4; ++i) {
struct tm* tm = localtime(&base);
tm->tm_mday += i;
time_t time = mktime(tm);
std::cout << asctime(tm);
}
return 0;
}
给了我:
Sat Mar 11 08:00:00 2006
Sun Mar 12 09:00:00 2006
Mon Mar 13 09:00:00 2006
Tue Mar 14 09:00:00 2006
我错过了什么?
好的,我已经尝试了FigBug的最新建议,即使用:
std::cout << ctime(&time);
而不是递增时间,但我得到了相同的结果。所以我猜我的库和/或编译器搞得一团糟。我在cygwin上使用的是g++ 3.4.4。我将文件复制到Solaris5.8上,并在那里使用g++ 3.3进行编译。我在那里得到了正确的结果!实际上,无论我使用ctime还是asctime进行输出,我都会得到正确的结果:
Sat Mar 11 08:00:00 2006
Sun Mar 12 08:00:00 2006
Mon Mar 13 08:00:00 2006
Tue Mar 14 08:00:00 2006
在带有g++ 3.4.6的Red Hut Linux上,我也得到了正确的结果(使用两个输出函数)。
所以我猜我遇到了一个Cygwin bug。
感谢您的帮助和建议...
发布于 2008-11-21 22:13:38
只需添加24*60*60即可。它应该不会在DST期间失败,因为UTC永远不会使用DST。
如果它失败了,那么您在代码中的某个地方就没有使用UTC。删除时区依赖关系。
发布于 2008-11-21 22:06:28
当你想要显示值时,我总是有最好的结果,保持时间戳UTC,并将它们转换为指定的时区(包括夏令时)。
这就省去了很多这样的麻烦(并且使你的程序独立于时区。
发布于 2016-05-31 00:30:50
一个非常古老的问题的新答案。
新答案的理论基础:现在有更好的工具来解决这个问题,使结果更不容易出错,更容易阅读,并且通过最小化串行<->字段转换实际上更有效。
新的答案需要C++11/14、<chrono>
和这个free, open source, timezone library。
代码如下:
#include "tz.h"
#include <iostream>
int
main()
{
using namespace std::chrono;
using namespace date;
auto base = make_zoned("Pacific/Easter", sys_seconds{1142085600s});
for (int i = 0; i < 4; ++i)
{
std::cout << format("%a %b %d %T %Y %Z", base) << '\n';
base = base.get_local_time() + days{1};
}
}
首先创建一个zoned_time
,将所需的时区与Unix时间戳配对。
它被格式化为任何所需的格式。
1天的增加是在时区的本地时间系统中完成的,这将考虑到夏令时。输出为:
Sat Mar 11 09:00:00 2006 -05
Sun Mar 12 09:00:00 2006 -06
Mon Mar 13 09:00:00 2006 -06
Tue Mar 14 09:00:00 2006 -06
事实证明,这个输出并不完全是OP所说的他想要的(请求的输出是每天08:00:00 )。然而,我使用这个库来充分研究整个星球在这一日期的时间转换。只有一个时区在这一天发生了转换:太平洋/复活节。这个过渡是向后移动一个小时,而不是向前移动。这是智利使用的时区,在南半球,人们会回到三月份的时间范围内。
这可以通过使用UTC而不是本地时间进行算术来演示。这是对上面一行程序的微小调整:
base = base.get_sys_time() + days{1};
使用base.get_sys_time()
而不是base.get_local_time()
,会导致运算在“系统时间”内完成,即国际协调时忽略闰秒。现在,输出更改为:
Sat Mar 11 09:00:00 2006 -05
Sun Mar 12 08:00:00 2006 -06
Mon Mar 13 08:00:00 2006 -06
Tue Mar 14 08:00:00 2006 -06
https://stackoverflow.com/questions/310363
复制相似问题