質問

1970年1月1日午前0時(UTC)から経過した秒数として表される時刻(以前のtime()呼び出しの結果)があります。この時間に1日を追加するにはどうすればよいですか?

24 * 60 * 60を追加するとほとんどの場合に機能しますが、夏時間の間にオンまたはオフになると失敗します。つまり、24時間を追加したいのですが、23時間または25時間を追加したい場合があります。

説明のために-プログラム:

#include <time.h>
#include <iostream>

int main()
{
  time_t base = 1142085600;
  for(int i = 0; i < 4; ++i) {
    time_t time = base + i * 24 * 60 * 60;
    std::cout << ctime(&time);
  }
  return 0;

}

プロデュース:

Sat Mar 11 08:00:00 2006
Sun Mar 12 09:00:00 2006
Mon Mar 13 09:00:00 2006
Tue Mar 14 09:00:00 2006

3月12日、13日、...の時間も午前8時にしたい。


FigBugの答えは、正しい方向を示してくれました。しかし、gmtimeの代わりにlocaltimeを使用する必要がありました。

int main()
{
  time_t base = 1142085600;
  for(int i = 0; i < 4; ++i) {
    struct tm* tm = localtime(&base);
    tm->tm_mday += i;
    std::cout << asctime(tm);
 }
 return 0;
}

お願い:

Sat Mar 11 08:00:00 2006
Sat Mar 12 08:00:00 2006
Sat Mar 13 08:00:00 2006
Sat Mar 14 08:00:00 2006

これは私が欲しいものです。 gmtimeを使用すると、14:00:00の時刻が表示されます

ただし、すべての日が土曜日であることに注意してください。また、3月32、33などになります。mktime関数をスローすると、開始した場所に戻ります。

#include <time.h>
#include <iostream>

int main()
{
  time_t base = 1142085600;
  for(int i = 0; i < 4; ++i) {
    struct tm* tm = localtime(&base);
    tm->tm_mday += i;
    time_t time = mktime(tm);
    std::cout << asctime(tm);
 }
 return 0;
}

教えてください:

 std::cout << ctime(&time);

不足しているもの???


OK、使用するFigBugの最新の提案を試しました:

Sat Mar 11 08:00:00 2006
Sun Mar 12 08:00:00 2006
Mon Mar 13 08:00:00 2006
Tue Mar 14 08:00:00 2006

asctimeではなく、同じ結果が得られます。だから、私のライブラリやコンパイラが台無しになっていると思います。 cygwinでg ++ 3.4.4を使用しています。ファイルをSolaris 5.8にコピーし、g ++ 3.3を使用してコンパイルしました。そこで正しい結果が得られました!実際、出力にctimeを使用してもasctimeを使用しても、正しい結果が得られます。

<*>

Red Hut Linux(g ++ 3.4.6)でも(両方の出力関数で)正しい結果が得られます。

だから、Cygwinのバグに遭遇したと思います。

ご協力ありがとうございます...

役に立ちましたか?

解決

gmtime()を使用して time_t struct tm

に変換します

1日追加( tm_mday

mktime()を使用して struct tm time_t

に戻す

詳細については、 time.h をご覧ください

編集:

試したところ、これは動作します:

int main()
{
  time_t base = 1142085600;
  for(int i = 0; i < 4; ++i) {
    struct tm* tm = localtime(&base);
    tm->tm_mday += i;
    time_t next = mktime(tm);
    std::cout << ctime(&next);
 }
 return 0;
}

他のヒント

24 * 60 * 60を追加します。 UTCはDSTを使用しないため、DST中に失敗することはありません。

失敗する場合、コードのどこかでUTCを使用していません。タイムゾーンの依存関係を削除します。

FigBugのソリューションは毎回ほぼ動作しますが、DSTの修正が必要です: tm-<!> gt; tm_isdst = -1

  

tm_isdstの正または0の値   mktime()が最初に推測するようにします   その夏時間   それぞれ、有効または無効です   指定された時間。負   tm_isdstの値により、mktime()が   夏時間かどうかを判断しよう   時間の節約は   指定された時間。

mktime spec から引用)

int main()
{
  time_t base = 1142085600;
  for(int i = 0; i < 4; ++i) {
    struct tm* tm = localtime(&base);
    tm->tm_mday += i;
    tm->tm_isdst = -1;        // don't know if DST is in effect, please determine
                              // this for me
    time_t next = mktime(tm);
    std::cout << ctime(&next);
 }
 return 0;
}

それ以外の場合、バグが発生します(2009年3月29日01:59:59から始まるモスクワの夏時間の例):

int main()
{
    // 28 March 2009 05:00:00 GMT ( local - 08:00 (MSK) )
    time_t base = 1238216400;

    std::time_t start_date_t = base;
    std::time_t end_date_t = base;

    std::tm start_date = *std::localtime(&start_date_t);
    std::tm end_date = *std::localtime(&end_date_t);

    end_date.tm_mday += 1;
//    end_date.tm_isdst = -1;

    std::time_t b = mktime(&start_date);
    std::time_t e = mktime(&end_date);

    std::string start_date_str(ctime(&b));
    std::string stop_date_str(ctime(&e));

    cout << " begin (MSK) (DST is not active): " << start_date_str;
    cout << " end   (MSD) (DST is active):     " << stop_date_str;
}

出力:

begin (MSK) (DST is not active): Sat Mar 28 08:00:00 2009
end   (MSD) (DST is active):     Sun Mar 29 09:00:00 2009

タイムスタンプをUTCに維持し、値を表示するときに指定したタイムゾーン(夏時間を含む)に変換すると、常に最高の結果が得られました。

これにより、このような手間が大幅に節約されます(プログラムがタイムゾーンに依存しなくなります。

非常に古い質問に対する新しい回答。

新しい答えの理由:この問題を解決するためのより良いツールがあり、シリアル<!> lt;-<!> gt;を最小化することで、エラーを起こしにくく、読みやすく、実際に効率的にします。フィールド変換。

新しい回答には、C ++ 11/14、<chrono>、およびこの無料、オープンソース、タイムゾーンライブラリ

コードは次のとおりです。

#include "tz.h"
#include <iostream>

int
main()
{
    using namespace std::chrono;
    using namespace date;
    auto base = make_zoned("Pacific/Easter", sys_seconds{1142085600s});
    for (int i = 0; i < 4; ++i)
    {
        std::cout << format("%a %b %d %T %Y %Z", base) << '\n';
        base = base.get_local_time() + days{1};
    }
}

まず、希望のタイムゾーンとUnixタイムタイムスタンプをペアにしてzoned_timeを作成します。

任意の形式でフォーマットされます。

また、1日の追加はタイムゾーンのローカルタイムシステムで行われ、夏時間を考慮に入れます。出力は次のとおりです。

Sat Mar 11 09:00:00 2006 -05
Sun Mar 12 09:00:00 2006 -06
Mon Mar 13 09:00:00 2006 -06
Tue Mar 14 09:00:00 2006 -06

判明したように、この出力はOPが望んだとおりではありません(要求された出力は毎日08:00:00です)。ただし、このライブラリを使用して、この日付の惑星全体の時間遷移を完全に調査しました。また、この日付に移行したタイムゾーンは太平洋/イースターのみです。そしてその移行は、前進ではなく、1時間後退することでした。これは、南半球のチリで使用されるタイムゾーンであり、3月のタイムフレームで1つがフォールバックします。

これは、現地時間ではなくUTCで算術演算を行うことで実証できます。これは、上記のプログラムを1行で微調整するだけです。

        base = base.get_sys_time() + days{1};

base.get_sys_time()ではなくbase.get_local_time()を使用すると、算術は<!> quot; system time <!> quot;で実行されます。これは、うるう秒を無視したUTCです。そして、出力は次のように変わります。

Sat Mar 11 09:00:00 2006 -05
Sun Mar 12 08:00:00 2006 -06
Mon Mar 13 08:00:00 2006 -06
Tue Mar 14 08:00:00 2006 -06
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top