3

私が書いた関数があります(適切な標準の代替品があれば教えてください...)

time_t get_unix_time(string time_str) {
    time_t loctime;
    time(&loctime);

    struct tm *given_time;
    time_str = time_str.substr(0, time_str.find_first_of('.'));

    replace(time_str.begin(), time_str.end(), ':', ',');
    replace(time_str.begin(), time_str.end(), '-', ',');
    replace(time_str.begin(), time_str.end(), '/', ',');
    replace(time_str.begin(), time_str.end(), ' ', ',');

    given_time = localtime(&loctime);
    vector<string> trecord = split_string(time_str, ',');

    given_time->tm_year = atoi(trecord.at(0).c_str()) - 1900;
    given_time->tm_mon  = atoi(trecord.at(1).c_str()) - 1;
    given_time->tm_mday = atoi(trecord.at(2).c_str());
    given_time->tm_hour = atoi(trecord.at(3).c_str());
    given_time->tm_min  = atoi(trecord.at(4).c_str());
    given_time->tm_sec  = atoi(trecord.at(5).c_str());

    return mktime(given_time);
}

関数への入力 (time_str) の形式は 1970-01-01 00:00:00.0です。split_string() 関数は、文字列time_strを以下を含むベクトルに分割します。

{ 1970, 01, 01, 00, 00, 00 }

given_time 構造体を埋めるために使用されます。

私はそれをテストする関数を書き、正確にその入力 (エポックの開始) を渡しました。ただし、返される時間は 21600 で、これは1970-01-01 06:00:00またはUTC+6です。予想される出力は0 (エポックの開始) です。

注: 私は UTC - 6 の米国中部時間帯にいます。1970 年 1 月 1 日 CST の真夜中、時間 @ UTC は 1970 年 1 月 1 日 06:00:00 になります。

私のタイムゾーンに固有のものになっている私の機能に何かありますか? 私はこの関数で何か間違ったことをしていますか、それとも別のことをしてゾーンに依存しないようにするか、少なくとも常に UTC にすることができますか?

4

6 に答える 6

5

glibcを使用している場合は、このtimegm関数を自由に使用できます。これはmktime、時間を常にGMTタイムゾーンにあるかのように解釈する のバージョンです。残念ながら、その関数のドキュメントには基本的に、それ以外の方法では標準ライブラリ呼び出しを使用して実装できないと記載されています。だから、それを持っていない限り、あなたはちょっと運が悪い.

于 2011-01-13T16:38:08.443 に答える
4

mktimeローカル タイム ゾーンで時間がかかります。したがって、 1970-01-01 00:00:00 local timeを渡すと、本来の1970-01-01 06:00:00 UTCが返されます。

別の方法として、 glibc を使用している場合はtimegmを呼び出すことができます。glibc を使用していない場合は、timegm のマンページで説明されているように、TZ 環境変数をいじって mktime を呼び出すときに、ローカル時間を一時的に UTC に変更します。

time_t my_timegm (struct tm *tm) {
    time_t ret;
    char *tz;
    tz = getenv("TZ");
    setenv("TZ", "", 1);
    tzset();
    ret = mktime(tm);
    if (tz)
        setenv("TZ", tz, 1);
    else
        unsetenv("TZ");
    tzset();
    return ret;
}

また、 への呼び出しlocaltimeは不要です。おそらく、夏時間の問題given_time->tm_isdstを回避するために を設定する必要があります。

于 2011-01-13T16:41:19.113 に答える
1

タイムゾーンの問題を取り除くために、gmtime代わりに, を使用する必要があるかもしれません。time

編集: 構造体に現在の時刻を入力し、そのすべてのコンポーネントを上書きする理由がよくわかりません。それだけではない理由:

time_t get_unix_time(const string& time_str)
{
    vector<string> trecord = split_string(time_str, ',');

    tm given_time;
    given_time.tm_year = atoi(trecord.at(0).c_str()) - 1900;
    given_time.tm_mon  = atoi(trecord.at(1).c_str()) - 1;
    given_time.tm_mday = atoi(trecord.at(2).c_str());
    given_time.tm_hour = atoi(trecord.at(3).c_str());
    given_time.tm_min  = atoi(trecord.at(4).c_str());
    given_time.tm_sec  = atoi(trecord.at(5).c_str());

    return mktime(&given_time);
}

別の編集:

うーん、mktime現地時間も考慮します。タイムゾーンのロケールを UTC に設定する以外に、これを回避する方法がよくわかりません。

于 2011-01-13T16:29:36.700 に答える
1

これらの厄介な関数を避けて、自分で計算してください。POSIXtime_tは、「エポック」(1970-01-01 00:00:00 GMT) からの秒の形式の算術型であり、うるう秒のナンセンスがないことを指定します (すべての日は正確に 86400暦秒であり、 SI 秒とは 1秒ずつ異なります)。ごくわずか)、うるう年のロジックを除けば、計算は非常に簡単です。

このようなカレンダーの計算は、標準的なプログラミングの入門演習なので、Web 上で解決したり、解決策を見つけたりできると確信しています。

余談ですが、おそらく ISO C と POSIX がそのような関数を省略している理由は、任意に複雑になる可能性があり、ホストのライブラリのみが異なるアプリケーション間で確実かつ一貫して実行できるタイムゾーンを含む変換とは異なり、GMT 変換は外部関数のない純粋な算術演算であるためです。パラメーター。

于 2011-01-13T19:02:54.420 に答える
0

mktime を呼び出すと、パラメーターが現地時間として解釈されます。また、「localtime」のような役に立たないように見える関数も使用していますが、それらは削除できると思います。

于 2011-01-13T16:37:44.950 に答える
0

strptime解析を行うためのラッパーを書くことができます。

struct tm given_time;

strptime(time_str.c_str(), "%Y-%m-%d %H:%M:%S", &given_time);

return mktime(&given_time);

@Josh Kelley の回答は、タイムゾーンの問題を徹底的に説明しています。

于 2011-01-13T16:43:02.013 に答える