将时间(以秒为单位)从大纪元转换为一年中的某一天?
Convert time in seconds from the Epoch to day of the year?
我有一个充满数据的文件,其中一列是从大纪元算起的秒数。作为参考,示例值如下所示:
1498493536984926976
我需要将其转换为一年中的某一天。到目前为止,我所拥有的是这段代码,它使用 this reference 将日期转换为正常的可读结构,然后使用 strftime 从结构中提取年份:
time_t rawtime = stol(exploded_line[2]);
std::cout << rawtime << std::endl;
struct tm date;
date = *localtime( &rawtime );
char *buffer;
std::cout << 2 << std::endl;
strftime (buffer,sizeof(buffer),"%j",&date);
但是,这段代码SegFaults
放在了strftime
行!我不知道是什么原因造成的。我尝试将 buffer
初始化为
char buffer[80];
和各种其他声明,但似乎没有任何效果。我也试过完全放弃缓冲区,只使用 std::string
;那也没有用。
另外,我也不偏爱这种方法。如果其他人有更好的方法从 Epoch 时间获取一年中的某一天,我将完全实现它。
如有任何帮助,我们将不胜感激!
你这里的实际问题是 localtime( &rawtime )
无法转换 rawtime
。当函数失败时,它 returns 一个空指针。取消引用该指针并尝试复制其值会导致段错误。
最有可能的问题是您的值太大了。如果你这样做
std::time_t t = std::time(nullptr);
std::cout << t << std::endl;
你得到
1499367157
这使得 1498493536984926976
成为遥远未来的日期。
这些行是你的问题:
char *buffer;
strftime (buffer,sizeof(buffer),"%j",&date);
您已经分配了一个 char *
但它没有指向任何东西。它只是一个随机值,因此您将一个野指针传递给 strftime()
。此外,sizeof(buffer)
将是指针的大小(4 或 8 个字节,具体取决于您的体系结构),而不是缓冲区应该指向的数组的大小。
将 char * buffer
更改为 char buffer[32];
或类似的东西。
这是一个可能的解决方案:
#include <string>
#include <iostream>
#include <ctime>
int main() {
// Original value is a 64-bit unsigned integer representing the time in nanoseconds
long long rawtime = 1498493536984926976LL;
std::cout << rawtime << std::endl;
// To convert from nanoseconds to seconds divide by a billion
time_t epochtime = rawtime / 1000000000LL;
std::cout << epochtime << std::endl;
struct tm date;
date = *std::localtime(&epochtime);
// Uses a fixed-length buffer for `strtftime`
char buffer[256];
std::cout << 2 << std::endl;
strftime(buffer,sizeof(buffer),"%j",&date);
std::cout << buffer << std::endl;
}
基于它们应该是纪元时间这一事实,您的时间戳以纳秒为单位。
1498493536984926976s = 4.749E10 years
.
1498493536984926976ns = 47.49 years
.
除非你的时间戳真的是 340 亿年后的未来,否则你应该将它们转换为秒,然后再将它们发送到 localtime
以获得 struct tm
。
这里使用的是Howard Hinnant's free, open source date/time library:
#include "date.h"
#include <iostream>
#include <sstream>
int
main()
{
using namespace std::chrono;
using namespace date;
std::istringstream file{"1498493536984926976"};
std::int64_t i;
file >> i;
std::cout << format("%j\n", sys_time<nanoseconds>{nanoseconds{i}});
}
输出:
177
备注:
您没有指定,但我假设 "seconds from the Epoch" 表示 UTC。一旦开始调用 localtime
之类的东西,您就会将计算机的本地时区偏移量带入计算中。我上面的代码将所有内容都保存在 UTC 中。
从文件中解析 int
后,格式为一行,没有明确的转换因子。
如果你需要一年中的第几天作为int
,而不是流出,那也很容易实现:
>
#include "date.h"
#include <iostream>
#include <sstream>
int
main()
{
using namespace std::chrono;
using namespace date;
std::istringstream file{"1498493536984926976"};
std::int64_t i;
file >> i;
auto sd = floor<days>(sys_time<nanoseconds>{nanoseconds{i}});
auto y = year_month_day{sd}.year();
int doy = (sd - sys_days{y/jan/1}).count() + 1;
std::cout << doy << '\n';
}
在后一种情况下,纳秒级精度 time_point
被截断为精度为 days
的 time_point
。然后将截断的 time_point
转换为 year_month_day
对象,以提取当前的 year
(使用 UTC)。最后,从截断的 time_point
中减去那年的第一天,得到精度为 days
的 chrono::duration
。将 1 添加到结果中,因为 %j
指定 1 月 1 日是第 1 天。
输出又是:
177
我有一个充满数据的文件,其中一列是从大纪元算起的秒数。作为参考,示例值如下所示:
1498493536984926976
我需要将其转换为一年中的某一天。到目前为止,我所拥有的是这段代码,它使用 this reference 将日期转换为正常的可读结构,然后使用 strftime 从结构中提取年份:
time_t rawtime = stol(exploded_line[2]);
std::cout << rawtime << std::endl;
struct tm date;
date = *localtime( &rawtime );
char *buffer;
std::cout << 2 << std::endl;
strftime (buffer,sizeof(buffer),"%j",&date);
但是,这段代码SegFaults
放在了strftime
行!我不知道是什么原因造成的。我尝试将 buffer
初始化为
char buffer[80];
和各种其他声明,但似乎没有任何效果。我也试过完全放弃缓冲区,只使用 std::string
;那也没有用。
另外,我也不偏爱这种方法。如果其他人有更好的方法从 Epoch 时间获取一年中的某一天,我将完全实现它。
如有任何帮助,我们将不胜感激!
你这里的实际问题是 localtime( &rawtime )
无法转换 rawtime
。当函数失败时,它 returns 一个空指针。取消引用该指针并尝试复制其值会导致段错误。
最有可能的问题是您的值太大了。如果你这样做
std::time_t t = std::time(nullptr);
std::cout << t << std::endl;
你得到
1499367157
这使得 1498493536984926976
成为遥远未来的日期。
这些行是你的问题:
char *buffer;
strftime (buffer,sizeof(buffer),"%j",&date);
您已经分配了一个 char *
但它没有指向任何东西。它只是一个随机值,因此您将一个野指针传递给 strftime()
。此外,sizeof(buffer)
将是指针的大小(4 或 8 个字节,具体取决于您的体系结构),而不是缓冲区应该指向的数组的大小。
将 char * buffer
更改为 char buffer[32];
或类似的东西。
这是一个可能的解决方案:
#include <string>
#include <iostream>
#include <ctime>
int main() {
// Original value is a 64-bit unsigned integer representing the time in nanoseconds
long long rawtime = 1498493536984926976LL;
std::cout << rawtime << std::endl;
// To convert from nanoseconds to seconds divide by a billion
time_t epochtime = rawtime / 1000000000LL;
std::cout << epochtime << std::endl;
struct tm date;
date = *std::localtime(&epochtime);
// Uses a fixed-length buffer for `strtftime`
char buffer[256];
std::cout << 2 << std::endl;
strftime(buffer,sizeof(buffer),"%j",&date);
std::cout << buffer << std::endl;
}
基于它们应该是纪元时间这一事实,您的时间戳以纳秒为单位。
1498493536984926976s = 4.749E10 years
.
1498493536984926976ns = 47.49 years
.
除非你的时间戳真的是 340 亿年后的未来,否则你应该将它们转换为秒,然后再将它们发送到 localtime
以获得 struct tm
。
这里使用的是Howard Hinnant's free, open source date/time library:
#include "date.h"
#include <iostream>
#include <sstream>
int
main()
{
using namespace std::chrono;
using namespace date;
std::istringstream file{"1498493536984926976"};
std::int64_t i;
file >> i;
std::cout << format("%j\n", sys_time<nanoseconds>{nanoseconds{i}});
}
输出:
177
备注:
您没有指定,但我假设 "seconds from the Epoch" 表示 UTC。一旦开始调用
localtime
之类的东西,您就会将计算机的本地时区偏移量带入计算中。我上面的代码将所有内容都保存在 UTC 中。从文件中解析
int
后,格式为一行,没有明确的转换因子。如果你需要一年中的第几天作为
int
,而不是流出,那也很容易实现:
>
#include "date.h"
#include <iostream>
#include <sstream>
int
main()
{
using namespace std::chrono;
using namespace date;
std::istringstream file{"1498493536984926976"};
std::int64_t i;
file >> i;
auto sd = floor<days>(sys_time<nanoseconds>{nanoseconds{i}});
auto y = year_month_day{sd}.year();
int doy = (sd - sys_days{y/jan/1}).count() + 1;
std::cout << doy << '\n';
}
在后一种情况下,纳秒级精度 time_point
被截断为精度为 days
的 time_point
。然后将截断的 time_point
转换为 year_month_day
对象,以提取当前的 year
(使用 UTC)。最后,从截断的 time_point
中减去那年的第一天,得到精度为 days
的 chrono::duration
。将 1 添加到结果中,因为 %j
指定 1 月 1 日是第 1 天。
输出又是:
177