人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

海外のある時点の日付・時間がサマータイム(夏時間)かどうかの判別をしたいと思っています。
言語はなんでもいいのですが、サマータイムの判別アルゴリズムをご存知の方、ポイントはずみますのでよろしくお願いします。

なお、使える関数は、年の取得関数・月の取得関数・日の取得関数・時の取得関数・分の取得関数・秒の取得関数・曜日の取得関数のみです。

●質問者: wizemperor
●カテゴリ:コンピュータ ウェブ制作
✍キーワード:アルゴリズム サマータイム ポイント 曜日 海外
○ 状態 :終了
└ 回答数 : 6/6件

▽最新の回答へ

1 ● xxxatsxxx
●10ポイント

localtime_r(またはlocaltime)

の戻り値の構造体内のtm_isdstがその名の通り、サマータイムフラグです。

http://www.linux.or.jp/JM/html/LDP_man-pages/man3/ctime.3.html

C標準でいろんなLL等からも利用できます。

◎質問者からの返答

説明が足りなかったかもしれませんが、あくまでアルゴリズムでお願いします。

if構文やwhileループ・forループなどの基本的なCの文は使えますが、質問の関数以外の組み込み関数や構造体は使えません。

変数、1次元配列は使えます。


2 ● wasisan
●13ポイント

正直私もまだよくわかっていませんが,とりあえず

サマータイムの判定について -OKWave:

http://okwave.jp/qa2332703.html

を張っておきます.

◎質問者からの返答

なるほど、ParseDateという関数では第n曜日というのが取得できるようですね。

ただ、今回は質問の関数しか使えないのです。

ParseDate関数のような第n曜日かを返す関数を実装するためのアルゴリズムでもかまいません。


3 ● hiramatsu_kg
●8ポイント

http://ja.wikipedia.org/wiki/%E5%A4%8F%E6%99%82%E9%96%93

アルゴリズムではなく、3月の第四日曜日からという風に日が各国別に決まってるんです。

◎質問者からの返答

それはわかっていますが、それをどうやって機械的に判別するかが今回の質問になります。

一般的な言語では、TZやサマータイムかどうかを表す定数などがありますが、今回は使えないのです(Cをかなりシンプルにしたような言語のため)。

第n曜日という決まりがあるので、第n曜日を取得するアルゴリズムがわかれば実装できそうなんですけどねぇ…。


4 ● j1960
●15ポイント

要件があいまいなのですが、何かのマシンにソフトを走らせて取得した日付と時間からそのマシンの置いてある国を特定して今サマータイムかどうかを判定するということですよね?

なお、使える関数は、年の取得関数・月の取得関数・日の取得関数・時の取得関数・分の取得関数・秒の取得関数・曜日の取得関数のみです。

使える関数が上記だけなら不可能です。

TZが取得できないということであれば現在「どこ」なの分からないということですから。

それとも、JST(TZ-9)の時計が動いているマシンがあって、国名とかを指定するとその国ではサマータイム中がどうかを教えてくれる、ということでしょうか?

だとするとアルゴリズムでは無理です。

まず、TZの指定だけではサマータイムかどうかは判定できません。

サマータイムを決めるのは国家です。

国家にひとつのタイムゾーンとは限りません。

例えば、オーストラリアはタイムゾーンを3ないしは4持っています。

しかも州によって夏時間があったり無かったりします。さらに夏時間の定義は国によって異なりますし、政治的な都合でしばしば変更されます。

これらをテーブルを引く方法以外に何らかのアルゴリズムで定義することは不可能です。


http://www.linux.or.jp/JM/html/LDP_man-pages/man2/gettimeofday.2...

http://man.cx/settimeofday(2)/ja

◎質問者からの返答

そうですね、なので質問してみました。ただ、ちょっと質問が曖昧でしたね。

想定しているタイムゾーンはアメリカの東部時間(EST, EDT)です。

基本的に自分で使うものなので、今から100年前だとか、今後数十年とかまで通用するアルゴリズムではなくてもいいです。

国・タイムゾーンは自分で指定するので、1つの国・タイムゾーンに固定になります。

アメリカ(GMT-5、夏はGMT-4)の日付時間を渡すと、夏時間かどうか判別したいということになります。

アメリカ東部であれば、第何曜日というのが決まっているので、ある日付が月の第何曜日かわかれば、できると思ったんですが…。


5 ● noocyte
●300ポイント ベストアンサー

四則演算と剰余は使っていいんですか?


夏時間についてはよく知りませんが,

Wikipedia を参考に判定プログラムを書いてみました.



であれば,次のようにして判定できると思います.ただし,


その補正を行う前の値とする.(そうでないと期間終了時の1時間が判定不能となる.)


Bool IsSummerTime(int month, int day, int w, int hour,
 int startMonth, int startN, int startW, int startHour,
 int endMonth, int endN, int endW, int endHour)
{
 int w1; // month月1日の曜日
 int dstDay; // 夏時間開始または終了日付

 // デバッグ用
 printf("\n%d月%d日(%d曜) %d時は夏時間?\n", month, day, w, hour);
 assert((1 <= day) && (day <= 31));
 assert((0 <= w) && (w <= 6));
 assert((0 <= startW) && (startW <= 6));
 assert((0 <= endW) && (endW <= 6));

 if((month < startMonth) || (endMonth < month)) goto NotDST;

 // month月1日の曜日w1を求める.day=1 ならば w1=w で,
 // dayが1日増えるごとにw1は1日前にずれるので,数学的には
 // w1 = (w - (day - 1)) mod 7
 // しかしC言語の場合は被除数が負になるとまずいので,
 // 負にならないようにするための最小の7の倍数35を足して
 w1 = (w + 36 - day) % 7;

 // デバッグ用
 printf("%d月%d日(%d曜) → 1日は%d曜\n", month, day, w, w1);

 if(month == startMonth) {
 // month月のstartN回目のstartW曜日の日付dstDayを求める.
 dstDay = NthDayOfWeekToDay(startN, startW, w1);

 // デバッグ用
 printf("夏時間開始:%d月%d日(%d曜) %d時\n",
 startMonth, dstDay, startW, startHour);

 // (day, hour) が (dstDay, startHour) より前ならば夏時間ではない.
 if((day < dstDay) || ((day == dstDay) && (hour < startHour)))
 goto NotDST;
 }
 if(month == endMonth) {
 // month月のendN回目のendW曜日の日付dstDayを求める.
 dstDay = NthDayOfWeekToDay(endN, endW, w1);

 // デバッグ用
 printf("夏時間終了:%d月%d日(%d曜) %d時\n",
 endMonth, dstDay, endW, endHour);

 // (day, hour) が (dstDay, startHour) 以後ならば夏時間ではない.
 if((day > dstDay) || ((day == dstDay) && (hour >= endHour)))
 goto NotDST;
 }

 printf("夏時間だよ.\n"); // デバッグ用
 return TRUE;

NotDST:
 printf("夏時間じゃないよ.\n"); // デバッグ用
 return FALSE;
}

/*--------------------------------------------------------------------------
IsSummerTime() のテスト.
--------------------------------------------------------------------------*/
void IsSummerTimeTest(void)
{
 // USA の夏時間
 const int startMonth = 3;
 const int startN = 2;
 const int startW = 0;
 const int startHour = 2;
 const int endMonth = 11;
 const int endN = 1;
 const int endW = 0;
 const int endHour = 1; // 夏時間補正前の時刻

#define ISSUMMERTIME(month, day, w, hour, isDST) \
 assert(IsSummerTime((month), (day), (w), (hour), \
 startMonth, startN, startW, startHour, \
 endMonth, endN, endW, endHour) \
 == (isDST))

 // 2007年の場合
 ISSUMMERTIME( 2, 28, 3, 23, FALSE); // 開始月の前月
 ISSUMMERTIME( 3, 10, 6, 23, FALSE); // 開始月,開始日より前
 ISSUMMERTIME( 3, 11, 0, 1, FALSE); // 開始日,開始時刻より前
 ISSUMMERTIME( 3, 11, 0, 2, TRUE ); // 開始日開始時刻ピッタリ
 ISSUMMERTIME( 3, 11, 0, 3, TRUE ); // 開始日,開始時刻より後
 ISSUMMERTIME( 3, 12, 1, 0, TRUE ); // 開始月,開始日より後
 ISSUMMERTIME( 4, 1, 0, 0, TRUE ); // 開始月の翌月
 ISSUMMERTIME(10, 31, 3, 23, TRUE ); // 終了月の前月
 ISSUMMERTIME(11, 3, 6, 23, TRUE ); // 終了月,終了日より前
 ISSUMMERTIME(11, 4, 0, 0, TRUE ); // 終了日,終了時刻より前
 ISSUMMERTIME(11, 4, 0, 1, FALSE); // 終了日,終了時刻ピッタリ
 ISSUMMERTIME(11, 4, 0, 2, FALSE); // 終了日,終了時刻より後
 ISSUMMERTIME(11, 5, 1, 0, FALSE); // 終了月,終了日より後
 ISSUMMERTIME(12, 1, 6, 0, FALSE); // 終了月の翌月
}

/*--------------------------------------------------------------------------
実行結果
--------------------------------------------------------------------------*/
2月28日(3曜) 23時は夏時間?
夏時間じゃないよ.

3月10日(6曜) 23時は夏時間?
3月10日(6曜) → 1日は4曜
夏時間開始:3月11日(0曜) 2時
夏時間じゃないよ.

3月11日(0曜) 1時は夏時間?
3月11日(0曜) → 1日は4曜
夏時間開始:3月11日(0曜) 2時
夏時間じゃないよ.

3月11日(0曜) 2時は夏時間?
3月11日(0曜) → 1日は4曜
夏時間開始:3月11日(0曜) 2時
夏時間だよ.

3月11日(0曜) 3時は夏時間?
3月11日(0曜) → 1日は4曜
夏時間開始:3月11日(0曜) 2時
夏時間だよ.

3月12日(1曜) 0時は夏時間?
3月12日(1曜) → 1日は4曜
夏時間開始:3月11日(0曜) 2時
夏時間だよ.

4月1日(0曜) 0時は夏時間?
4月1日(0曜) → 1日は0曜
夏時間だよ.

10月31日(3曜) 23時は夏時間?
10月31日(3曜) → 1日は1曜
夏時間だよ.

11月3日(6曜) 23時は夏時間?
11月3日(6曜) → 1日は4曜
夏時間終了:11月4日(0曜) 1時
夏時間だよ.

11月4日(0曜) 0時は夏時間?
11月4日(0曜) → 1日は4曜
夏時間終了:11月4日(0曜) 1時
夏時間だよ.

11月4日(0曜) 1時は夏時間?
11月4日(0曜) → 1日は4曜
夏時間終了:11月4日(0曜) 1時
夏時間じゃないよ.

11月4日(0曜) 2時は夏時間?
11月4日(0曜) → 1日は4曜
夏時間終了:11月4日(0曜) 1時
夏時間じゃないよ.

11月5日(1曜) 0時は夏時間?
11月5日(1曜) → 1日は4曜
夏時間終了:11月4日(0曜) 1時
夏時間じゃないよ.

12月1日(6曜) 0時は夏時間?
夏時間じゃないよ.
◎質問者からの返答

質問が曖昧、条件が厳しい中、コードまで書いていただきまして、ありがとうございます。四則演算と剰余は使えます。

第何曜日かを求める関数がなく悩んでいましたが、NthDayOfWeekToDay関数は助かりました。

とても汎用的なコードを教えていただけたので、問題なく実装できそうです。ありがとうございました。


1-5件表示/6件
4.前の5件|次5件6.
関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ