C/C++ 时区正确的时间转换(自纪元以来的秒数) [英] C/C++ time zone correct time conversion (to seconds since epoch)

查看:34
本文介绍了C/C++ 时区正确的时间转换(自纪元以来的秒数)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道时间是自纪元以来的秒数.值得注意的是,我不希望进行转换的机器在哪里,时区字符串应该足够了.

I would like to know time as seconds since the epoch. Notably, I would not like it to matter where the machine doing the conversion is, the time zone string should be enough.

我有这个测试程序,pt.cc:

I have this test program, pt.cc:

#include <assert.h>
#include <errno.h>
#include <iostream>
#include <stdio.h>
#include <string>
#include <string.h>
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE
#endif
#include <time.h>

using namespace std;  // To be brief, don't do this in real life.

int main(int argc, char* argv[]) {
    (void)argc; (void)argv;   // Skip compile warning.

    // I expect both of these to transform to 1440671500.
    cout << "1440671500 expected" << endl;
    const char utc_example[] = "2015-08-27T11:31:40+0100";
    struct tm tm;
    memset(&tm, 0, sizeof(struct tm));
    char* end = strptime(utc_example, "%Y-%m-%dT%H:%M:%S%z", &tm);
    assert(end);
    assert(*end == '\0');
    time_t seconds_since_epoch = mktime(&tm);
    cout << "utc example: " << seconds_since_epoch << "  or maybe  "
         << seconds_since_epoch - tm.tm_gmtoff + (tm.tm_isdst ? 3600 : 0) << endl;

    const char tz_example[] = "2015-08-27T10:31:40Z";
    memset(&tm, 0, sizeof(struct tm));
    end = strptime(tz_example, "%Y-%m-%dT%H:%M:%S%nZ", &tm);
    assert(end);
    assert(*end == '\0');
    seconds_since_epoch = mktime(&tm);
    cout << " tz example: " << seconds_since_epoch << "  or maybe  "
         << seconds_since_epoch - tm.tm_gmtoff + (tm.tm_isdst ? 3600 : 0) << endl;

    return 0;
}

这是输出:

jeff@birdsong:tmp $ clang++ -ggdb3 -Wall -Wextra -std=c++14 pt.cc -o pt
jeff@birdsong:tmp $ ./pt
1440671500 expected
utc example: 1440671500  or maybe  1440667900
 tz example: 1440667900  or maybe  1440664300
jeff@birdsong:tmp $ TZ=America/New_York ./pt
1440671500 expected
utc example: 1440693100  or maybe  1440711100
 tz example: 1440689500  or maybe  1440707500
jeff@birdsong:tmp $ TZ=Europe/London ./pt
1440671500 expected
utc example: 1440675100  or maybe  1440675100
 tz example: 1440671500  or maybe  1440671500
jeff@birdsong:tmp $ 

注意 mktime() 的返回值如何根据环境时区而变化.mktime() 的手册页条目表明它将故障时间解释为本地时间.因此,我尝试减去 GMT 偏移量并补偿时区,以防它忽略这些值(或可能"值).

Note how the return value of mktime() changes depending on the ambient time zone. The man page entry for mktime() suggests it interprets the broken down time as local time. So I tried subtracting the GMT offset and compensating for timezone in case it was ignoring those values (the "or maybe" value).

有关如何正确执行此操作的任何提示?(如果有关系,我只需要它在 linux 上工作.)

Any tips on how to do this correctly? (Should it matter, I only need this to work on linux.)

推荐答案

这里有一个答案,可以使用 Google 的 https://github.com/google/cctz

Here's an answer that does what you want using Google's https://github.com/google/cctz

#include <chrono>
#include <iostream>
#include <string>

#include "src/cctz.h"

using namespace std;

int main(int argc, char* argv[]) {
  const char kFmt[] = "%Y-%m-%dT%H:%M:%S%Ez";

  // I expect both of these to transform to 1440671500.
  const char utc_example[] = "2015-08-27T11:31:40+0100";
  const char tz_example[] = "2015-08-27T10:31:40Z";
  cout << "1440671500 expected" << endl;

  // Required by cctz::Parse(). Only used if the formatted
  // time does not include offset info.
  const auto utc = cctz::UTCTimeZone();

  std::chrono::system_clock::time_point tp;
  if (!Parse(kFmt, utc_example, utc, &tp)) return -1;
  cout << "utc example: " << std::chrono::system_clock::to_time_t(tp) << "\n";

  if (!Parse(kFmt, tz_example, utc, &tp)) return -1;
  cout << " tz example: " << std::chrono::system_clock::to_time_t(tp) << "\n";

  return 0;
}

输出为:

1440671500 expected
utc example: 1440671500
 tz example: 1440671500

<小时>

请注意,涉及从 time_t 中添加/减去偏移量的其他答案正在使用一种称为纪元转移"的技术,但实际上并没有起作用.我在 12:30 的 CppCon 演讲中解释了为什么:https://youtu.be/2rnIHsqABfM?t=12分30秒

这篇关于C/C++ 时区正确的时间转换(自纪元以来的秒数)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆