C言語関係掲示板

過去ログ

No.453.日付の妥当性チェック

[戻る] [ホームページ]
No.3249

日付の妥当性チェック
投稿者---ヒナコ(2002/10/30 20:38:38)


毎々お世話になっております。
またまたハマっております。

やりたい事は、日付の妥当性チェックです。
いろいろ調べてみて、以下のような感じで処理を行っているのですが、
日付として正しい値が入っても、正しくない値が入っても
「日付として正しくない」になってしまいます。
どなたかお力添えをよろしくお願い致します。

int main()
{
struct tm *ltime;
char wkDate[256];

strcpy(wkDate,"20020101");

/* 年月日を構造体に格納 */
memcpy( &ltime->tm_year, wkDate, 4 );
memcpy( &ltime->tm_mon, wkDate+4, 2 );
memcpy( &ltime->tm_mday, wkDate+6, 2 );

/* 年月日以外の必要情報に固定値を設定 */
ltime->tm_isdst = -1; /* サマータイムフラグ */
ltime->tm_hour = 0; /* 時 */
ltime->tm_min = 0; /* 分 */
ltime->tm_sec = 0; /* 秒 */

if( mktime(ltime) == -1 ){
printf("日付として正しくありません\n");
}
}

このやり方で間違えている所をご指摘頂けたらと思います。
また、日付をチェックする方法で違うやり方があったら教えて下さい。
よろしくお願い致します。


No.3252

Re:日付の妥当性チェック
投稿者---ともじ(2002/10/30 23:07:31)


こんばんは。

>このやり方で間違えている所をご指摘頂けたらと思います。
>また、日付をチェックする方法で違うやり方があったら教えて下さい。
>よろしくお願い致します。

ポインタの値が不定です。
tm構造体の設定の仕方も違います。年は1900からの経過年数で
月は0〜11です。年月日に文字列は設定できません。
文字列のコピーは文字列処理関数を使いましょう。
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
	struct tm ltime;
	char wkDate[256];
	char wk[10];

	strcpy(wkDate,"20020101");

	/* 年月日を構造体に格納 */
	wk[0] = '\0';	strncat(wk, wkDate, 4);
	ltime.tm_year = atoi(wk) - 1900;
	wk[0] = '\0';	strncat(wk, wkDate+4, 2);
	ltime.tm_mon = atoi(wk) - 1;
	wk[0] = '\0';	strncat(wk, wkDate+6, 2);
	ltime.tm_mday = atoi(wk);

	/* 年月日以外の必要情報に固定値を設定 */
	ltime.tm_isdst = -1; /* サマータイムフラグ */
	ltime.tm_hour = 0; /* 時 */
	ltime.tm_min = 0; /* 分 */
	ltime.tm_sec = 0; /* 秒 */

	if( mktime(<ime) == -1 ){
		printf("日付として正しくありません\n");
	}
	else
		printf("日付として正しいです\n");

	return (0);
}


No.3254

Re:日付の妥当性チェック
投稿者---ヒナコ(2002/10/31 09:54:37)


おはようございます。

>ポインタの値が不定です。
>tm構造体の設定の仕方も違います。年は1900からの経過年数で
>月は0〜11です。年月日に文字列は設定できません。
>文字列のコピーは文字列処理関数を使いましょう。

勉強になりました。ありがとうございました。


No.3255

Re:日付の妥当性チェック
投稿者---ヒナコ(2002/10/31 10:32:29)


度々すみません。
下記のように修正し、処理を実行したのですが、
"20021301"
"20020230"
のような日付として正しくない値で実行しても、
「日付として正しいです」と表示されてしまいます。

このような日付の妥当性チェックだと、その日付が存在するか
どうかまでのチェック(閏年も含む)は出来ないのでしょうか?
教えて下さい。


No.3256

Re:日付の妥当性チェック
投稿者---かずま(2002/10/31 11:22:16)


>"20021301"
>"20020230"
>のような日付として正しくない値で実行しても、
>「日付として正しいです」と表示されてしまいます。
>
>このような日付の妥当性チェックだと、その日付が存在するか
>どうかまでのチェック(閏年も含む)は出来ないのでしょうか?
#include <stdio.h>
#include <time.h>

int check1(int y, int m, int d)
{
    static int t[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
    return y > 1582 && m >= 1 && m <= 12 && d >= 1
        && d <= t[m-1] + (m==2 && y%4==0 && (y%100!=0 && y%400==0));
}

int check2(int y, int m, int d)
{
    struct tm t;

    t.tm_year = y - 1900;
    t.tm_mon  = m - 1;
    t.tm_mday = d;
    t.tm_hour = 0; /* 時 */
    t.tm_min  = 0; /* 分 */
    t.tm_sec  = 0; /* 秒 */
    t.tm_isdst = -1; /* サマータイムフラグ */
    if (mktime(&t) == -1) return 0;
    printf("  %d/%d/%d\n", t.tm_year+1900, t.tm_mon+1, t.tm_mday);
    return 1;
}

int main()
{
    int y, m, d;

    while (scanf("%d%*c%d%*c%d", &y, &m, &d) == 3) {
        printf(" check1(%d/%d/%d) = %d\n", y, m, d, check1(y, m, d));
        printf(" mktime(%d/%d/%d) = %d\n", y, m, d, check2(y, m, d));
    }
    return 0;
}
----------------------------------------------------------------------
実行結果
2002 10 31
 check1(2002/10/31) = 1
  2002/10/31
 mktime(2002/10/31) = 1
2002 13 1
 check1(2002/13/1) = 0
  2003/1/1
 mktime(2002/13/1) = 1
2002 2 30
 check1(2002/2/30) = 0
  2002/3/2
 mktime(2002/2/30) = 1
q
mktime に 2002/13/1 を渡すと、2003/1/1 に補正してしまいます。
2002/13/1 を不正とは判断しません。

No.3261

Re:日付の妥当性チェック
投稿者---ヒナコ(2002/10/31 14:52:58)


ご回答、ありがとうございます。

以下の処理で分からない箇所があります。
年月日それぞれの範囲をチェックしているのかなと思いますが、
詳しく教えていただけないでしょうか?

>return y > 1582 && m >= 1 && m <= 12 && d >= 1
> && d <= t[m-1] + (m==2 && y%4==0 && (y%100!=0 && y%400==0));

また、教えていただいた処理を組み込みましたが、
うるう年の判定が出来ませんでした。
うるう年は、また違う方法でチェックしなければいけないのでしょうか?

それと、"25000101"は日付として正しいはずなのに、
mktimeで判定すると、-1が戻ってきてしまいます。

なぜだか分かる方、教えて下さい。
よろしくお願い致します。

No.3262

Re:日付の妥当性チェック
投稿者---かずま(2002/10/31 15:07:55)


>>return y > 1582 && m >= 1 && m <= 12 && d >= 1
>> && d <= t[m-1] + (m==2 && y%4==0 && (y%100!=0 && y%400==0));
>
> また、教えていただいた処理を組み込みましたが、
> うるう年の判定が出来ませんでした。

すみません。最後の && は || の間違いでした。

 && d <= t[m-1] + (m==2 && y%4==0 && (y%100!=0 || y%400==0));


> それと、"25000101"は日付として正しいはずなのに、
> mktimeで判定すると、-1が戻ってきてしまいます。

mktime は、1970/1/1 から 2038/1/19 までしか扱えないはずです。
日付を 1970/1/1 からの秒数で表現して、それが 31ビットの整数だから。