2012-01-27 10 views
2

set_time()関数は、特定の時間をとり、この時間に指定された分数を加算して*tに保存することになっています。だから、UTC時刻を含むstruct tmに分を追加するにはどうすればよいですか?

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

enum {JAN, FEB, MAR, APR, MAY, JUNE, JULY, AUG, SEP, OCT, NOV, DEC}; 

void set_time(struct tm *t, 
       int year, int mon, int day, 
       int hour, int min, int sec, 
       int mins_to_add) 
{ 
    /* Copy all the values. */ 
    t->tm_year = (year - 1900); 
    t->tm_mon = mon; 
    t->tm_mday = day; 
    t->tm_hour = hour; 
    t->tm_min = min; 
    t->tm_sec = sec; 

    // No DST since we are storing UTC time. 
    t->tm_isdst = 0; 

    /* Add minutes to time. */ 
    t->tm_min += mins_to_add; 
    mktime(t); 

    /* Debug print */ 
    printf("%s\n", asctime(t)); 
} 

int main(int argc, char **argv) 
{ 
    struct tm t; 
    set_time(&t, 2011, AUG, 1, 10, 00, 00, 0); 
    return 0; 
} 

、私は、WindowsのシステムはESTのタイムゾーンに設定されている場合は、私が手に出力された8月1日に午前10時00分00秒2011年には何も追加しないようにset_time()を頼む:Mon Aug 01 11:00:00 2011

上記の例で指定された時間(上記の例では0)を指定された時間(上記の例では2011年8月1日10:00:00)に追加する作業を行うため、エラーが発生します。

/* Add minutes to time. */ 
    t->tm_min += mins_to_add; 
    mktime(t); 

mktime()は、他のすべてのmembを調整するために呼び出されます追加のためにt->tm_minが59を超える場合の構造体の変数。しかしmktime()は、struct tmオブジェクトの時刻を現地時間として扱います。したがって、日付が2011年8月1日で、ローカルタイムゾーンがESTであると見なされると、DSTを適用する必要があるとみなされますが、t->tm_isdst0に設定されます(DSTは*tの時刻に適用されません)。したがって、DSTを適用し、2011年8月1日10:00:00から2011年8月1日11:00:00までの日付を調整し、t->tm_isdst1に設定します。

私は1t->tm_isdstを初期化持っていたmktime()*tの時間がすでにDSTがそれに適用されていることがわかっているだろうので、この問題は発生していません。しかし、set_time()に、DSTが適用されてはならない日付に何も追加しないように頼んだら、Jan 01 10:00:00 2011と言うと、結果が乱れてしまいました.DSTをオフにして、*tt->tm_isdstを0に設定し、Jan 01 09:00:00 2011に日付を再調整してください。

この結果、これは、指定した時刻に余分な時間を追加したり、余分な時間を差したりするという望ましくない効果がありますそれに何も追加しない。これは、mktime()t->tm_isdstのDST設定がシステムの現地時間帯にあるべきでないと判断した場合、時刻を*tに再調整して正しく設定しようとするためです。

この問題を解決する正しい方法は何ですか?

+1

おそらく関連しています。間違いなく、dupe:http://stackoverflow.com/questions/530519/stdmktime-and-timezone-info – ruakh

+0

ruakh、あなたが言及した投稿は密接に関連していますが、類似していません。問題は、 'mktime()'によって返されたタイムスタンプからタイムゾーンオフセットを差し引くことを含むきちんとした回避策があります。しかし、私の問題は、 'struct tm'オブジェクトのある時間に特定の分数を追加し、' mktime() 'がDST設定のために日付から余分なものを追加または減算しないことを確認することです。 –

答えて

1

mktimeの代わりにWindows機能_mkgmtimeを使用して、この変換を安全に実行することができます(ローカルタイムゾーンの設定に関係なく)。

+0

DRH、http://msdn.microsoft.com/en-us/library/2093ets1(v=vs.80).aspxのドキュメントには次のように書かれています。「tm構造時間を指定するときは、tm_isdstフィールドをゼロに設定してください0)、夏時間が有効であることを示す0より大きい値、Cランタイムライブラリコードで標準時間または夏時間があるかどうかを計算するための0より小さい値効果。" - 私は 't-> tm_isdst'を初期化するのとは無関係に、常に同じ答えを得ます。だから、私はこの関数が 'tm_isdst'をいかに正確に利用しているのか理解できません。 –

+0

@Susam Pal私は100%ではありませんが、ドキュメンテーションは 'mktime'のドキュメントから取り除かれ、実際には' _mkgmtime'には当てはまりません。これは、 'tm_isdst'をさまざまな値に設定して、DSTにローカルタイムを設定するだけでなく、' tm_isdst'の結果が '0'に設定されたことに基づいています(これは、 UTC)、 – DRH

+0

Unixにいるあなたのために、 'gmtime'の逆である' timegm'( '' localtime'の逆で '' timelocal''、 'mktime'に相当)があります。 – musiphil

2

struct tm上のドキュメントは

は夏時間フラグ(tm_isdstが)言う 情報が利用できない場合...ゼロより小さいです。

-1に設定して、それが修正されるかどうかを確認することをお勧めします。

+1

これは、 'set_time(&t、2011、MAR、13、01、59、00、1);'のようなDST遷移の周りに問題を残している可能性があり、PSTのローカルタイムゾーンは03:00:00を返します。 – DRH

+0

@DRHあなたはそれを試しましたか? – Borodin

+1

@Borodinはい、私のコメントは不完全でした。元のコードは '03:00:00'を返します。更新されたコード( 'tm_isdst = -1'を使用)は' 01:00:00'を返します。 – DRH

関連する問題