C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

DateTime型のNULL許容

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■86818 / inTopicNo.1)  DateTime型のNULL許容
  
□投稿者/ kitsune (1回)-(2018/03/23(Fri) 13:50:27)

分類:[C#] 

visual studio 2017を使用してc#の学習をしています。

DateTime型にNULL値を登録したいのですが
調べてみるとDateTimeの後ろに演算子?
をつけると許容できるとわかったのですがうまくいきません。

MaskedTextBox(MtxtBirthDay)に生年月日を入れてボタンをクリックすると
TextBox(TextAge)に年齢が表示されるコードです。


以下コード

private void ButtonAgeCal_Click(object sender, EventArgs e)
        {

            DateTime BD;

            if (!DateTime.TryParseExact(MtxtBirthDay.Text, "yyyy/MM/dd", null, System.Globalization.DateTimeStyles.None, out BD))
            {
                MessageBox.Show("生年月日を正しく入力してください");
            }
            else
            {
                int age = DateTime.Today.Year - BD.Year;
                if (BD > DateTime.Today.AddYears(-age)) age--;

                TxtAge.Text = age.ToString();
            }
        }


以上

DateTime BD ; ← DateTime? BD=null;
このように書き換えると

out BD のBDに赤波線が引かれ
引数5は'out System.DateTime?'から'out System.DateTime'へ変換することはできません。

BD.Year;のYearに赤波線が引かれ
'DateTime?'に'Year'の定義が含まれておらず、型'DateTime?の最初の引数を受け付ける
拡張メソッド'Year'が見つかりませんでした。usingディレクティブまたはアセンブリ参照が不足していないことを確認してください

とエラーが発生します。
どのように対処すればよろしいでしょうか?
ご協力をお願いいたします。


引用返信 編集キー/
■86819 / inTopicNo.2)  Re[1]: DateTime型のNULL許容
□投稿者/ Hongliang (621回)-(2018/03/23(Fri) 14:07:29)
そもそもこのコードでは処理が十分に完結していて、null許容にする意味が全くないように見えます。
nullが欲しいケースはDateTime.TryParseに失敗したケースでしょうが、このコードではメッセージボックスを出して終了ですから、nullを入れる意味がありません。
nullを入れて、どうしたいのでしょうか?
引用返信 編集キー/
■86820 / inTopicNo.3)  Re[2]: DateTime型のNULL許容
□投稿者/ kitsune (2回)-(2018/03/23(Fri) 14:17:04)
No86819 (Hongliang さん) に返信
> そもそもこのコードでは処理が十分に完結していて、null許容にする意味が全くないように見えます。
> nullが欲しいケースはDateTime.TryParseに失敗したケースでしょうが、このコードではメッセージボックスを出して終了ですから、nullを入れる意味がありません。
> nullを入れて、どうしたいのでしょうか?


SQLserverと連携させていて
テーブルのdate型(NULL許容)に生年月日が登録されるようになっています。

その際、生年月日をブランクで登録すると1900/01/01で登録されてしまうので、それを回避したいためです。
引用返信 編集キー/
■86821 / inTopicNo.4)  Re[3]: DateTime型のNULL許容
□投稿者/ Hongliang (622回)-(2018/03/23(Fri) 14:24:18)
> SQLserverと連携させていて
> テーブルのdate型(NULL許容)に生年月日が登録されるようになっています。
>
> その際、生年月日をブランクで登録すると1900/01/01で登録されてしまうので、それを回避したいためです。

であれば、null許容が必要なのはそのDBへの登録処理であったりです(NULLを登録する方法としてnull許容型を使うかどうかは、DBへの登録処理に使用するライブラリ次第ですが)。
今提示されているコード部分にはそれらが存在していません。
引用返信 編集キー/
■86823 / inTopicNo.5)  Re[1]: DateTime型のNULL許容
□投稿者/ WebSurfer (1445回)-(2018/03/23(Fri) 15:13:36)
No86818 (kitsune さん) に返信

Teratail のスレッドは放置ですか?

date型にNULLを登録できません
https://teratail.com/questions/117725

レスやコメントがついているのに、それに一切答えず放置して、他(ここ)で聞くのはマナー的に
どうかと思うのですが・・・
引用返信 編集キー/
■86829 / inTopicNo.6)  Re[3]: DateTime型のNULL許容
□投稿者/ shu (1105回)-(2018/03/24(Sat) 14:35:27)
No86820 (kitsune さん) に返信

> SQLserverと連携させていて
> テーブルのdate型(NULL許容)に生年月日が登録されるようになっています。
> 
> その際、生年月日をブランクで登録すると1900/01/01で登録されてしまうので、それを回避したいためです。
DBへの登録処理で

if 生年月日 = Nothing then
    〇〇 = DBNull.Value
else
  〇〇 = 生年月日
end if

とすればDBにNullが設定されます。

引用返信 編集キー/
■86846 / inTopicNo.7)  Re[1]: DateTime型のNULL許容
□投稿者/ 魔界の仮面弁士 (1596回)-(2018/03/25(Sun) 23:55:00)
No86820 (kitsune さん) に返信
> テーブルのdate型(NULL許容)に生年月日が登録されるようになっています。

データベースの NULL と、C# の null は別物です。
https://docs.microsoft.com/ja-jp/dotnet/framework/data/adonet/sql/handling-null-values

同じように扱うライブラリもありますが、ADO.NET においては通常、
DBNull.Value がデータベースの null に相当します。



No86818 (kitsune さん) に返信
> DateTime型にNULL値を登録したいのですが
> 調べてみるとDateTimeの後ろに演算子?
> をつけると許容できるとわかったのですがうまくいきません。

「DateTime?」は「System.Nullable<System.DateTime>」の省略表記ですが、
DataSet は Nullable<> 型をサポートしていないのでご注意ください。

ADO.NET の拡張ライブラリ(たとえば LINQ to DataSet や Dapper.NET など)を併用すれば、
NULL 許容なフィールドを Nullable<> 型にマッピングできなくは無いですが…。



> out BD のBDに赤波線が引かれ
> 引数5は'out System.DateTime?'から'out System.DateTime'へ変換することはできません。

ここの out 引数は、「DateTime?」型ではなく「DateTime」型でなければなりません。

MaskedTextBox からの変換結果を受け取る変数は DateTime のままにしておき、それとは別に
誕生日を保持する null 許容な変数を設け、その別変数を DateTime? にするのが良いでしょう。

また、TryParseExact は引数が多いので、変換用のメソッドを作っておくと
楽かと思います。たとえばこんな感じのメソッドを用意するのは如何でしょうか。


private static DateTime? ToDate(string ymd)
{
 return DateTime.TryParseExact(ymd, @"yyyy\/MM\/dd",
  CultureInfo.InvariantCulture, DateTimeStyles.None,
  out DateTime dt) ? dt : default(DateTime?);
}


private void Form1_Load(object sender, EventArgs e)
{
 // これらはデザイン時に指定しておくこともできます。
 MtxtBirthDay.TextMaskFormat = MaskFormat.IncludeLiterals;
 MtxtBirthDay.Mask = @"0000\/00\/00";
 MtxtBirthDay.ValidatingType = typeof(DateTime);
}


使う場合にはこんな感じです。

  DateTime? birthday = ToDate(MtxtBirthDay.Text); // ★上記の自作メソッドで変換★
  if (birthday == null) // ここの判定は「if (!birthday.HasValue)」でも良い
  {
    TxtAge.Clear();
    MessageBox.Show(this, "生年月日を正しく入力してください。",
      "入力漏れ", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    MtxtBirthDay.Focus();
  }
  else
  {
    // DateTime BD = (DateTime)birthday;
    DateTime BD = birthday.Value;
    //
    // 以下年齢計算処理……誕生日に未来の日付が指定された場合、マイナスの年齢をどう扱いますか?
    //
  }


> TextBox(TextAge)に年齢が表示されるコードです。
ご存知かもしれませんが、年齢の数え方にはいくつかの方法があるのでご注意ください。


ひとつは仏教などで使われている【数え年】。
「いくつの年と関わったか」を表す数え方であり、
出生した時点で「1歳」とし、以降、正月を迎えるたびに +1 歳していく方法です。
月や日は考慮せず、西暦部だけで計算できるので最も簡単な数え方ですね。
この方式では 2000/12/31 生まれの場合、2000/12/31 時点で 1 歳、2001/01/01 時点で 2 歳と数えます。


もう一つは、法律上における年齢算出となる【満年齢】。
http://elaws.e-gov.go.jp/search/elawsSearch/elaws_search/lsg0500/detail?lawId=135AC0000000050
出生した時点を「0歳」とし、以降、誕生日の前日(の24時)を迎えるたびに +1 歳する方法です。
この方式では 2000/01/01 生まれの場合、2000/12/30 までは 0 歳、2000/12/31 時点で 1 歳と数えます。


もう一つは、kitsune さんが書かれていた方法。
これも満年齢の一種ではあるのですが、こちらは法律上の満年齢とは 1 日ズレがあり、
出生した時点を「0歳」とし、以降、誕生日(の0時)を迎えるたびに +1 歳する方法となります。
この方式では 2000/01/01 生まれの場合、2000/12/31 までは 0 歳、2001/01/01 時点で 1 歳と数えます。



> c#の学習をしています。
ちなみに正式名称は c# ではなく C# です。細かい事ですが、一応指摘。

[JIS X 3015]
》 C#は,“しーしゃーぷ”と発音する。
》 C#は,LATIN CAPITAL LETTER C (U+0043)の次に NUMBER SIGN # (U+0023)を書く。

[ECMA-334]
》 The name C# is pronounced “C Sharp”.
》 The name C# is written as the LATIN CAPITAL LETTER C (U+0043) followed by the NUMBER SIGN # (U+0023).
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ