将时间(以秒为单位)从大纪元转换为一年中的某一天?

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 被截断为精度为 daystime_point。然后将截断的 time_point 转换为 year_month_day 对象,以提取当前的 year(使用 UTC)。最后,从截断的 time_point 中减去那年的第一天,得到精度为 dayschrono::duration。将 1 添加到结果中,因为 %j 指定 1 月 1 日是第 1 天。

输出又是:

177