典型的なWebアプリケーションでは、日付は強く型付けされたデータベースレイヤーから取得されます(たとえば、c#ではSystem.StringではなくSystem.DateTimeとして)。
日付を文字列として表現する必要がある場合(ページに表示されるなど)、DateTimeから文字列への変換はプレゼンテーション層で行われます。
どうしてこれなの? DateTimeをデータベース層で文字列に変換するのが悪いのはなぜですか?
チャットでの激論 、および これのすべてを開始した元の質問 も参照してください。
日付、DateTime、およびその他の実際に型指定されたオブジェクトは、他の型に変換する必要があるときまで、通常は適切に入力された形式のままにしておく必要があります。特に、その型が人間が読める形式である場合、特にそれが不可逆/一方向の変換の場合。
どうして?この型は、適切な等価性テスト、加算と減算、比較(より大きい、より小さい)、タイムゾーン、ロケール機能(特に時間に関連するものにとって特に重要)などの便利な組み込み機能を数多く提供することが前提となっているため、など。アメリカ人と「Month Day [th]、Year」形式、および一般的な英国スタイルの「Day Month Year」またはISO標準の「Year-Month-Day」をサポートする場合は、それが文字列であり、その変更を行う必要がある場合はどうしますか?それを解析して日付に戻しますか?ええと、感謝します-そのようにして完全に回避するのが最善の方法である、多くの悪とあからさまなバグがあります。
具体的には、プレゼンテーションレイヤーが後でデータから分離されている階層型アーキテクチャについて説明しました。これは実際には、日付を文字列ではなく日付として渡すもう1つの大きな理由です。日付を入れる必要があるのは、どのような種類の文字列フォーマットですか。英語、中国語、秒/ミリ秒、月の完全な名前または数字の有無にかかわらず、後で日付フィールドで並べ替えますか(文字列での並べ替えには、特定の文字列形式が必要です)。これはすべて、プレゼンテーション(ユーザーがデータをどのように表示するか)の問題であり、そのロジックを他の場所に配置すると、最初に階層型アーキテクチャを使用する利点が制限されます。データベースは、将来の日付をどのように表示するかを知っていたり、気にする必要はありません。
最後に、時間を重視するほぼすべての複雑なアプリケーション(階層型アーキテクチャーの目的)は、必然的に多くのさまざまな方法で、多くの場合、アーキテクチャーのすべての異なるレベルで、時刻/日付を使用します。時刻と日付に関連する型付きオブジェクトが存在するのは、本当に良い理由があります。時刻自体、特に人間のカレンダーシステムは、奇妙で難しいものです。結局のところ、時刻と日付は、整数と浮動小数点が文字列ではないのと同じ理由で文字列ではありません。文字列が実際には単なる文字配列ではないというふりをしようとすると、人生が難しくなります。
彼は、データ時刻を文字列に変換するためにWebサーバーを使用すると言っています。私はそれをウェブサーバーではなくデータベースサーバーで行うと言っています。なぜそれが良いと思いますか? - M T頭
タイプを知りたい。
結局のところ、結局のところそれは常にとにかく常にバイトであるため、データベースが情報を文字列、一部の整数、またはバイトに格納しているかどうかは本当に気にしません。データベースで必要とされるよりも多くのスペースを占めるそのストリングは、私を悩ませません。気になるのはこのような日付に遭遇しています:
2016年11月10日
それが11か月目か10か月目かはわかりません。
しかし、あなたが言うことは検証されています。確かに、検証プロセスを通過します。日付は完全に正しいです。しかし、ここではこのことを維持しており、日付が文字列であることだけを知っています。私はこれが何日であるかさえあなたに言うことはできません。
「私たちの領主の2000年と16年目の11月10日。」
それは文字列です。私たちのプレゼンテーションの1つは、その形式でそれを必要とします。データベースはすべての日付を文字列に変換すると言っていましたか?楽しんでください。
データベースの仕事は、存在するデータではなくデータを格納することです。もちろん、それを文字列で行うこともできますが、それを解析して他の形式で提示するのに役立つようにする必要があります。 DBが提供するすべてのタイプの標準の解析済み形式でそれを保存すると、プレゼンテーションの決定をしなくても、プレゼンテーションの準備ができる限り近くなります。 DBがその型を文字列、整数、またはバイトで裏付けているかどうかは、私には実際には関係ありません。それが何をしているかを知っている限り。
しかし、DBに日付を処理していることを知らせない場合、日付を文字列として保存すると、時期尚早に提示し、他のすべてのプレゼンテーションよりも優先することになります。これにより、他のすべてのプレゼンターは変換前に解析を強制されます。いいえ、データベースはプレゼンテーション層の一部ではありません。それがあるように頼んではいけない。
同様に、プレゼンテーションレイヤーはデータベースの一部ではないため、レポートをデータベースの詳細に結合することは賢明ではありません。型を操作する方がはるかに堅牢です。
日付を文字列に変換してプレゼンテーションを行うには、ユーザーの好みを知っている必要があります。これは、正確に同じ日付は、通常、ユーザーがロケールによって異なるように表示されるためです。アプリケーションで単一のロケールを使用している場合でも、適切な動作では、データベースサーバーではなくapplicationのロケールを使用する必要があります。また、現時点で一致している場合でも、それらが同一であるとは限りません。
普遍的な日付データ型からロケール固有の文字列への変換は、変換が実行される必要があることをhowが認識している層であるため、プレゼンテーション層で行われる必要があります。
これは、any型をアプリケーション層に到達したらすぐに盲目的に文字列に変換したくないのと同じ理由で望ましくありません。オブジェクトをユーザーに提示する前に、そのオブジェクトを何らかの方法で使用する可能性が高いです(ユーザーに提示する場合でも)。この特定の例では、オブジェクトに対して日付計算を行う必要があると想像してください。表示する前にオブジェクトを文字列に正確に変換するだけの欠点はありません。
型が存在するのには理由があります。もしそれらが何の利益ももたらさなければ、私たちはそれらを持たず、それらを使用せず、「型」を持っているだけで、すべてがそうなります。それらは便利であるだけでなく、安全性と効率も高めます。以下は、常にネイティブ形式で型を永続化する必要がある理由のリストです文字列としてではなく。私はほとんどの場合DateTime
を例として使用しましたが、整数、小数、バイナリなどのプリミティブ型にも同じ原則が適用されます。
ほとんどすべてのデータストアでは、データの制約を指定できます。これには、型の制約も含まれます。 DateTime
インスタンスを指定する主な利点の1つは、格納されたデータがその型に制限されることです。データがストアにどのように挿入されたかに関係なく、日付時刻以外のものを入力することはできません。後者は、ストアと直接対話する複数のプロセスがある大規模なシステムでは重要です。 2月にはうるう年は29日、うるう年以外は28日しかないため、これには(任意の年の)2月30日などの誤った日付を追加することも含まれます。
挿入された日付が現在の日付を超えないようにする、または開始日が終了日より前に発生することを保証するなど、データストアに実装できる検証制約もあります。
ほとんどのデータストアには、MS SQL ServerのDateAdd
またはDatePart
などの組み込みの操作/関数もあります。これにより、データがまだストアにある(まだアプリケーションに取得されていない)間に、特定のデータのフィルタリングまたは選択を開始できます。
ネイティブタイプを使用することで、ストアと相互作用する他の開発者やシステムは、そのプリミティブタイプがどのように格納されるかについての詳細を知る必要がありません。これは、その型が文字列として格納されている場合は当てはまりません。その場合、すべての人がDateTime
文字列表現の形式を理解していることを確認する必要があります。このシステムは、データのロケール、地域、文化にまたがるデータを扱う場合、アプリケーションの物理的な場所、およびそのデータと対話するエンドユーザー/システムの属性を扱うときに脆弱になります。例:ある国の日付形式はMM/dd/yyyy(米国のように)かもしれませんが、別の国ではdd/MM/yyyyかもしれません、違いがほとんど不可能になることを検出します。
検索の速度、検証の速度、操作の速度、ストレージ効率もすべて重要な要素です。検索速度の例:データストアでは列のインデックスが可能であり、これらのインデックスは通常、タイプがネイティブ形式で保存されている場合に、より効率的に使用できます。
開発者がストレージ形式を推測する必要がないため、ネイティブタイプシステムを使用すると、ストアに対するクエリの実行がより簡単になります。ほとんどすべてのデータストアアプリケーションプロバイダー(例:ado.net)は、渡されたネイティブタイプに基づいて適切なパラメーター化されたクエリを作成するためのメカニズムを提供します。以下は、ado.netに日付部分を追加する例ですSQL Serverストアに対してクエリを実行する場合、文字列で同じことを行うと、非常に扱いにくく、壊れやすく、エラーが発生しやすくなります。
command.Parameters.Add(new SqlParameter("@startDate", SqlDbType.Date) {Value = myDateInstance.Date});
コード内のネイティブタイプは、.netタイプSystem.Date
などの標準操作も提供します。操作は通常、日付の追加、日付間の差異の検索など、本質的に数学的なものです。繰り返しますが、これは文字列型に対して簡単に行うことはできません。
プリミティブ型が最終的にプレゼンテーション層の文字列に変換されると(そうするためのプログラムスタック内の正しい位置)、プログラマーはさまざまなオプションを使用して、それを状況に応じて正しく表示することができます。提示されます。このコンテキストは通常、データの実際の意味とユーザーのロケールで構成されます。
日時インスタンスは、ユーザーのロケールに基づいて自動的にフォーマットできます。
DateTime.Now.ToString("D", CultureInfo.GetCultureInfo(userContext.Culture))
10進数のインスタンスは金額(通貨)を表している可能性があり、ユーザーのロケールも好みに応じて金額を表示する必要があります。次に、c#アプリケーションは、
amount.ToString("C", CultureInfo.GetCultureInfo(userContext.Culture))
異なる文化では数字の表示が異なるため、これは重要になる可能性があります。米国では、ピリオド(。)とコンマ(、)は、オランダとまったく同じ意味を持ちます。
これはDateTime
インスタンスに非常に固有です。日付と時刻は、特定の瞬間の出来事を表しますが、通常、これは自分のタイムゾーンに応じてユーザーに伝達/提示する必要があります。例:DateTime
インスタンス2016-09-21T23:38:21.399Z
は、米国の東部タイムゾーンのユーザーには9/21/2016 5:21 PM
として表示できます。これを行うには多くの方法がありますが、日付時刻インスタンスが文字列型としてメモリに保持されるか、データ型に文字列型として保持される場合、ほぼ不可能になります。
アプリケーションの一般的な2つのルールは、プリミティブ型を文字列表現に変換する際に従うものです。
日付にあいまいでない形式を使用している限り、これを行うことで本当に何も問題はありません(サービスで常に行われます)。明確にすることで、日付が明確であるだけでなく(例:MM/DDとDD/MM)、それがどのタイムゾーンであるかを示します。そのため、日付をテキストとして表す場合は、ISO形式を使用してください。 。私はUTCベースの時間文字列を強く好みます。
長所:
短所:
誰かがこれをやりたいと言ったら、「なぜ?」と尋ねます。あまり意味がないからです。誰かが日付を文字列として返したい理由が直接日付を表示するためである場合、これはDBから文字列を使用する適切な理由ではありません。