日付の有効性チェックについて – プログラミング – Home

日付の有効性チェックについて
 
通知
すべてクリア

[解決済] 日付の有効性チェックについて

固定ページ 1 / 2

佐倉
 佐倉
(@佐倉)
ゲスト
結合: 21年前
投稿: 43
Topic starter  

YYYYMMDDのような文字列が
正しい日付であるかどうかをチェックする方法がありますか?

たとえば
20010101⇒OK
20000001⇒NG
2001010A⇒NG

など


引用未解決
トピックタグ
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

書式が常に YYYYMMDD の形式ならば簡単だと思います。
・年、月、日のそれぞれに分解
・それぞれが適切な範囲にあるかどうか検証
・日はうるう年に注意


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 600
 

そんなもん簡単に作れるでしょうに。

- 8桁であること
- 全部が数字であること。
- その月/その日が正当であること
(ただし2月に限りうるう年を考慮すべし)

これだけ。

# なくはないでしょう。
# struct tm につっこんで mktime呼べばいいんじゃないかしら(おそらく)


返信引用
tib
 tib
(@tib)
ゲスト
結合: 23年前
投稿: 468
 

・文字列を分解して数値に変換し、CTimeに代入。
・CTime::Format( %Y%m%d )で日付の文字列を作る。
・元の文字列と一致していればOK。

という方法ではどうでしょう?


返信引用
佐倉
 佐倉
(@佐倉)
ゲスト
結合: 21年前
投稿: 43
Topic starter  

> 文字列を分解して数値に変換し、CTimeに代入。
CTime(2001,1,1,1,1,1)のように、インスタンスを生成するですか?


返信引用
佐倉
 佐倉
(@佐倉)
ゲスト
結合: 21年前
投稿: 43
Topic starter  

> # なくはないでしょう。
> # struct tm につっこんで mktime呼べばいいんじゃないかしら(おそらく)

struct tm when;
CString sTemp = 20010101;
when.tm_year = atoi(sTemp.Left(4));
when.tm_mon = atoi(sTemp.Mid(4,2));
when.tm_mday = atoi(sTemp.Mid(6,2));
mktime(&when);
time_t result;
if((result = mktime(&when)) != (time_t)-1 ){
 printf(OK\n);
}else {
 printf(error\n);
}

できました。
επιστημη さんありがとう。
ちなみに、名前どういう意味ですか?


返信引用
tib
 tib
(@tib)
ゲスト
結合: 23年前
投稿: 468
 

> 文字列を分解して数値に変換し、CTimeに代入。
> CTime(2001,1,1,1,1,1)のように、インスタンスを生成するですか?
そういうことです。今日なら
CTime( 2004, 5, 27, 0, 0, 0 )
でしょうか。


返信引用
佐倉
 佐倉
(@佐倉)
ゲスト
結合: 21年前
投稿: 43
Topic starter  

正しくない日付を代入すると、CTimeのコンストラクタ内のASSERTでエラーになる。
たとえば:
CTime(2001,13,32,1,1,1)


返信引用
tib
 tib
(@tib)
ゲスト
結合: 23年前
投稿: 468
 

> 正しくない日付を代入すると、CTimeのコンストラクタ内のASSERTでエラーになる。
> たとえば:
> CTime(2001,13,32,1,1,1)

そうですね。でもこの方法は、「struct tm につっこんで mktime呼ぶ」ではチェックし
きれない「2月29日」などには有効です。「20030229」と「20040229」で試してみてくだ
さい。違いが解ると思います。

επιστημηさんが提示してくれた方法でOKという結果がでたら、この方法でもう一度チェッ
クしてみるといいでしょう。余談ですが、
> when.tm_year = atoi(sTemp.Left(4));
> when.tm_mon = atoi(sTemp.Mid(4,2));

これでは不十分だと思います。


返信引用
tib
 tib
(@tib)
ゲスト
結合: 23年前
投稿: 468
 

mktime()では「20040431」みたいに、小の月のチェックもしてくれません。
また、mktime()もCTimeも扱える年の範囲が狭いので、1970年以前の日付などもチェック
しなくてはならないようならば、ひと工夫必要です。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 600
 

そーなるとゼラーの公式適用して自前でこさえちまったほうがいいんじゃないのか、と。


返信引用
佐倉
 佐倉
(@佐倉)
ゲスト
結合: 21年前
投稿: 43
Topic starter  

CTimeをつかうと、ASSERTでプログラムが終了するではないですか?


返信引用
tib
 tib
(@tib)
ゲスト
結合: 23年前
投稿: 468
 

だからぁ、

επιστημηさんが提示してくれた方法でOKという結果がでたら、この方法でもう一度チェッ
クしてみるといいでしょう。

と書いたんですけど。


返信引用
tib
 tib
(@tib)
ゲスト
結合: 23年前
投稿: 468
 

なるほど、今ちょっと試してみましたが、

> 佐倉 [E-Mail] 2004/05/27(木) 17:34:25
> CTime(2001,13,32,1,1,1)

この例ではmktime()はOKと判断するんですね。これではmktime()の判定結果をそのまま信
じてCTimeに渡すのは確かに危険です。

CTime::CTime(int...)のソースを見ると、
 ASSERT(nDay >= 1 && nDay <= 31);
 ASSERT(nMonth >= 1 && nMonth <= 12);
 ASSERT(nYear >= 1900);
となっていますので、この範囲チェックを行ってからCTimeに渡すようにするとか。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

ぜらーさんは 1583年 ~ 3999年までしか使えないとか。
せっかく MFC 使うなら COleDateTime 使っちまいなっ!


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました