16

標準mktime関数を使用して astruct tmをエポック時間値に変換しています。フィールドはtmローカルで入力され、エポック時間を GMT として取得する必要があります。この目的のためにローカル GMT オフセットを秒単位で設定できるフィールドがtmあります。gmtoff

しかし、その情報を取得する方法がわかりません。確かに、オフセットを返す標準関数がどこかにあるはずですか? それはどのようにlocaltime行うのですか?

4

9 に答える 9

23

次の手順を実行してください。

#define _GNU_SOURCE /* for tm_gmtoff and tm_zone */

#include <stdio.h>
#include <time.h>

/* Checking errors returned by system calls was omitted for the sake of readability. */
int main(void)
{
  time_t t = time(NULL);
  struct tm lt = {0};

  localtime_r(&t, &lt);

  printf("Offset to GMT is %lds.\n", lt.tm_gmtoff);
  printf("The time zone is '%s'.\n", lt.tm_zone);

  return 0;
}

注:によって返されたエポックからの秒数はtime()、グリニッジの場合と同様に測定されます。

于 2012-12-10T16:21:19.600 に答える
8

localtime はどのようにそれを行いますか?

localtimeマニュアルページによると

localtime() 関数は、あたかも tzset(3) を呼び出したかのように動作し、外部変数 tzname に現在のタイムゾーンに関する情報を設定します。 タイムゾーン は、協定世界時 (UTC) とローカル標準時間の差 (秒単位) を使用します。

したがって、どちらかを呼び出すことができ、または呼び出しlocaltime()の違いがあります。timezonetzset()

extern long timezone;
....
tzset();
printf("%ld\n", timezone);

localtime_r()注:これらの変数を設定する必要がないことに注意して選択する場合は、tzset()最初に setを呼び出す必要がありtimezoneます。

POSIX.1-2004 によると、localtime() は tzset() が呼び出されたかのように動作する必要がありますが、localtime_r() にはこの要件がありません。移植可能なコードの場合、localtime_r() の前に tzset() を呼び出す必要があります。

于 2012-12-10T16:32:25.943 に答える
6

尋ねる前にもう少し検索をするべきだったと思います。timegmの反対を行うほとんど知られていない関数があることがわかりましたgmtime。それは私の目的には十分なGNUとBSDでサポートされています。より移植性の高い解決策は、環境変数の値を一時的TZに「UTC」にmktime設定してから、を使用してから元にTZ戻すことです。

しかしtimegm、私のために働きます。

于 2012-12-10T17:27:59.090 に答える
1

少なくとも Linux では次のことが当てはまると思います: タイムゾーン情報は /usr/share/zoneinfo/ から取得されます。localtime は、zoneinfo からの適切なファイルのコピーである /etc/localtime を読み取ります。タイムゾーン ファイルで実行することにより、内部の内容を確認できzdump -vます (zdump は sbin にある場合がありますが、タイムゾーン ファイルを読み取るために昇格されたアクセス許可は必要ありません)。ここに1つの抜粋があります:

/usr/share/zoneinfo/EST5EDT Sun Nov 6 05:59:59 2033 UTC = Sun Nov 6 01:59:59 2033 EDT isdst=1 gmtoff=-14400
/usr/share/zoneinfo/EST5EDT Sun Nov 6 06:00:00 2033 UTC = Sun Nov 6 01:00:00 2033 EST isdst=0 gmtoff=-18000
/usr/share/zoneinfo/EST5EDT Sun Mar 12 06:59:59 2034 UTC = Sun Mar 12 01:59:59 2034 EST isdst=0 gmtoff=-18000
/usr/share/zoneinfo/EST5EDT Sun Mar 12 07:00:00 2034 UTC = Sun Mar 12 03:00:00 2034 EDT isdst=1 gmtoff=-14400
/usr/share/zoneinfo/EST5EDT Sun Nov 5 05:59:59 2034 UTC = Sun Nov 5 01:59:59 2034 EDT

必要に応じて、これを自分で解析できると思います。gmtoffを返すだけのstdlib関数があるかどうかはわかりません(あるかもしれませんが、わかりません...)

編集: man tzfile は、zoneinfo ファイルの形式を説明しています。適切なタイプの構造に簡単に mmap できるはずです。それは、そのトレースに基づいて zdump が行っていることのようです。

于 2012-12-10T16:00:23.090 に答える
0

これが私のやり方です:

time_t z = 0;
struct tm * pdt = gmtime(&z);
time_t tzlag = mktime(pdt);

の自動ローカル ストレージによる代替struct tm:

struct tm dt;
memset(&dt, 0, sizeof(struct tm));
dt.tm_mday=1; dt.tm_year=70;
time_t tzlag = mktime(&dt);

tzlag、秒単位で、UTC オフセットの負の値になります。UTC と比較した標準時のタイムゾーンの遅れ:

LocalST + tzlag = UTC

「夏時間」も考慮したい場合 は、 を特定の現地時間に適用した後 (または で取得した後)tm_isdstから減算します。tzlagtm_isdststruct tmmktimelocaltime

機能する理由:
このセットstruct tmは 1970 年 1 月 1 日の「エポック」の瞬間であり、これtime_tは 0 に対応します。その日付を呼び出すmktime()と、それが UTC であるかのように変換さtime_tれ (したがって 0 になります)、それから UTC オフセットが減算されます。出力を生成する順序time_t。したがって、UTC_offset のマイナスを生成します。

于 2021-11-13T00:17:21.603 に答える