web-dev-qa-db-ja.com

std :: chrono :: time_pointをUNIXタイムスタンプに変換します

固定日以降に_std::chrono::duration_を取得するにはどうすればよいですか? _std::chrono::time_point_をUNIXタイムスタンプに変換するためにこれが必要です。

XXXにコードを挿入

_auto unix_Epoch_start = XXX;
auto time = std::chrono::system_clock::now();
auto delta = time - unix_epoc_start;
auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(delta).count();
_

_time_point_にはtime_since_Epoch()メソッドがありますが、これがUNIXエポック(1970年1月1日00:00:00 UTC)と同じであるという保証はありません。

28
Daniel

UNIXタイムスタンプは、1970年1月1日UTCからの秒数として定義されますが、すべての秒はカウントされません。これはいくぶんばかげているので、そのポイントが何であるか疑問に思う必要があるので、これはばかげた質問であることに同意します。

とにかく、_time_t_およびtime()のプラットフォームドキュメントを見てみましょう。

Linux

time()は、Epoch 1970-01-01 00:00:00 +0000(UTC)以降の秒数として時刻を返します。

POSIX.1は、指定された時間とエポックの間の秒数を概算する式を使用して、エポック以降の秒を定義します。この式は、4で均等に割り切れるすべての年がうるう年であるという事実を考慮していますが、100で割り切れる年は、400で均等に割り切れる場合を除き、うるう年ではありません。この値は、うるう秒とシステムクロックを標準参照に同期させる必要がないため、時刻とエポックの間の実際の秒数とは異なります。意図は、エポック値からの秒の解釈が一貫していることです。さらなる根拠については、POSIX.1-2008根拠A.4.15を参照してください。

Windows

Time関数は、システムクロックに従って、1970年1月1日午前0時(協定世界時(UTC))から経過した秒数を返します。

Mac OS X

関数ctime()、gmtime()、およびlocaltime()はすべて、エポック(1970年1月1日00:00:00 UTC、1970年1月1日)以降の秒単位の時間を表す時間値を引数として取ります。

Asctime()、ctime()、difftime()、gmtime()、localtime()、およびmktime()関数は、ISO/IEC 9899:1990(ISO C90''), and conform to ISO/IEC 9945-1:1996 ( POSIX.1 '')ローカルタイムゾーンにはうるう秒テーブルが含まれていません(zic(8)を参照)。

AIX、HP-UX、Solarisなど、他のシステムについても同様のドキュメントを見つけることができます。

C++では指定されていませんが、Unixタイムスタンプを取得する簡単で広く移植可能な方法があります。

_auto unix_timestamp = std::chrono::seconds(std::time(NULL));
_

UTC 1970年1月1日からのミリ秒数(同様にすべてをカウントしない)が必要な場合は、次のようにします。

_int unix_timestamp_x_1000 = std::chrono::milliseconds(unix_timestamp).count();
_

これらの値は実時間ではないことを覚えておいてください。そのため、一般的に、Unixタイムスタンプを算術演算で使用することはできません。たとえば、Unixタイムスタンプを減算しても、正確な秒数のカウントは得られません。または、次のようなことをした場合:

_std::chrono::steady_clock::now() - unix_timestamp;
_

1970-01-01 00:00:00 + 0000に実際に対応する時点は取得できません。


アンディ・プロールが示唆するように、あなたは次のような愚かなことをすることができます:

_// 1 Jan 1970 (no time zone)
std::tm c = { 0, 0, 0, 1, 0, 70, 0, 0, -1};

// treat it as 1 Jan 1970 (your system's time zone) and get the
// number of seconds since your system's Epoch (leap seconds may
// or may not be included)
std::time_t l = std::mktime(&c);

// get a calender time for that time_point in UTC. When interpreted
// as UTC this represents the same calendar date and time as the
// original, but if we change the timezone to the system TZ then it
// represents a time offset from the original calendar time by as
// much as UTC differs from the local timezone.
std::tm m = *std::gmtime(&l);

// Treat the new calendar time as offset time in the local TZ. Get
// the number of seconds since the system Epoch (again, leap seconds
// may or may not be counted).
std::time_t n = std::mktime(&m);

l -= (n-l); // subtract the difference
_

lは、1970年1月1日UTCからの(間違った)秒数を表すようになりました。システムエポックと1970年1月1日(システムタイムゾーン)の間にうるう秒がない場合、またはシステムエポックから他の方向に同じ時間内にうるう秒がない場合、カウントされたうるう秒はキャンセルされ、lは、Unixタイムスタンプが間違っているという点で間違っています。


別のオプションは、 Howard Hinnantの_chrono::date_ などの適切な日付ライブラリを使用することです。 (Howard Hinnantは、C++ 11 _<chrono>_ライブラリで働いていた人の一人でした。)

_auto now = system_clock::now();
sys_days today = time_point_cast<days>(now);
system_clock::time_point this_morning = today;

sys_days unix_Epoch = day(1)/jan/1970;
days days_since_Epoch = today - unix_Epoch;

auto s = now - this_morning;

auto tz_offset = hours(0);
int unix_timestamp = (days_since_Epoch + s + tz_offset) / seconds(1);
_

うるう秒を処理する場合、Howard Hinnantは a library も提供します。これには、うるう秒データのソースとしてタイムゾーンデータベースを解析するだけでなく、それらを処理する機能が含まれています。

32
bames53

簡単に言えば、ここにUnixタイムスタンプを取得するために使用する関数があります(1970年1月1日UTCからの秒数):

static uint64_t getUnixTimeStamp(const std::time_t* t = nullptr)
{
    //if specific time is not passed then get current time
    std::time_t st = t == nullptr ? std::time(nullptr) : *t;
    auto secs = static_cast<std::chrono::seconds>(st).count();
    return static_cast<uint64_t>(secs);
}

この関数の利点は、デフォルトのパラメーター値が現在の時間を提供するだけであることです。ただし、特定の時間をUNIXタイムスタンプに変換する場合は、同様に変換できます。

7
Shital Shah

このC++ 11実装はどうですか

auto microsecondsUTC = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_Epoch()).count();
4
siamoss

mktime()を使用して、tm構造にエンコードされた目的の日付をlocal-time _time_t_値に変換できます。

UTC時間が必要な場合は、gmttime()を使用してその_time_t_値をUTC tm構造に変換し、どのtmを取得するかを把握しますmktime()への入力で指定された場合、構造体は目的のUTC _time_t_を生成します。

少し手の込んだ、しかしうまくいけばうまくいくか、少なくともヒントを提供します。

2
Andy Prowl