典型的なWebアプリケーションでは、日付は強く型付けされたデータベースレイヤーから取得されます(たとえば、c#ではSystem.StringではなくSystem.DateTimeとして)。
日付を文字列として表現する必要がある場合(ページに表示するなど)、DateTimeから文字列への変換はプレゼンテーション層で行われます。
どうしてこれなの?DateTimeをデータベース層の文字列に変換するのはなぜ悪いことですか?
典型的なWebアプリケーションでは、日付は強く型付けされたデータベースレイヤーから取得されます(たとえば、c#ではSystem.StringではなくSystem.DateTimeとして)。
日付を文字列として表現する必要がある場合(ページに表示するなど)、DateTimeから文字列への変換はプレゼンテーション層で行われます。
どうしてこれなの?DateTimeをデータベース層の文字列に変換するのはなぜ悪いことですか?
回答:
日付、DateTimes、および実際に他の型付きオブジェクトは、一般に、他の型にする必要がある瞬間まで、特にその型が人間が読める形式である場合、特に非可逆/一方向の変換。
どうして?このタイプは、適切な等価性テスト、加算と減算、比較(より大きい、より小さい)、タイムゾーンおよびロケール機能(特に時間関連の場合に重要)など、多くの便利な組み込み機能を提供すると想定されているため、など。アメリカ人と「Month Day [th]、Year」フォーマット、および一般的な英国スタイルの「Day Month Year」、またはISO標準の「Year-Month-Day」をサポートする場合は、それが文字列であり、その変更を行う必要がある場合はどうしますか?それを解析して日付に戻しますか?ええと、感謝しません-そのように多くの悪と卑劣なバグがありますが、それらは完全に回避するのが最善です。
より具体的には、後でデータとは別のプレゼンテーション層を持つ階層型アーキテクチャについて言及しました。これは実際に、日付を文字列ではなく日付として渡すもう1つの大きな理由です。日付を入力する必要があるのは、どのタイプの文字列フォーマットですか。英語、中国語、秒/ミリ秒の有無にかかわらず、完全な月名または数字、日付フィールドで後で並べ替えますか(文字列で並べ替えるには、適切に機能させるために特定の文字列形式が必要です)。これはすべてプレゼンテーションの問題であり、ユーザーがデータをどのように表示する必要があるかということです。また、そのロジックを他の場所に配置すると、最初から階層アーキテクチャを使用する利点が制限されます。データベースは、将来の日付をどのように表示するかを知っている必要はありません。
最後に、時間を重視するほぼすべての複雑なアプリケーション(階層型アーキテクチャの目的)は、多くのさまざまな方法で、多くの場合アーキテクチャのすべてのレベルで時刻/日付を使用することを避けられません。時刻と日付に関連する型付きオブジェクトは、本当に正当な理由で存在します。時刻自体、特に人間のカレンダーシステムは奇妙で難しいものです。最終的に、時刻と日付は、整数と浮動小数点が文字列ではないのと同じ理由で文字列ではありません。実際には文字の配列であると偽装しようとすると、人生が難しくなります。
Why? Because it is assumed that the type provides you with lots of handy built in functionality
私の意見では、これは二次的なものです。本当の理由は、タイプが何かを教えてくれるからです。日付は文字列ではなく、たまたま人間が読める文字列に簡単に変換できます。
彼は、Webサーバーを使用してデータ時間を文字列に変換することを言っています。Webサーバーではなく、データベースサーバーで行うと言っています。なぜそれが良いと思いますか?- MTヘッド
タイプを知りたい。
データベースが文字列、一部の整数、またはバイトのいずれに情報を保存するかは、実際には気にしません。データベースで必要とされるよりも多くのスペースを占める文字列は、私を悩ませません。私が気になるのは、このような日付に遭遇しています:
2016年11月10日
そして、それが11か月目か10か月目か分からない。
しかし、あなたが言うことは検証済みです。検証プロセスを通過してください。日付は完全に正しいです。しかし、ここで私はこのことを維持しており、私が知っているのは日付が文字列であることだけです。私はこれが何日であるかさえあなたに話すことができません。
「主君の二千十六年目の十一月十日。」
それは文字列です。プレゼンテーションの1つでは、その形式でそれを必要とします。データベースはすべての日付を文字列に変換すると言いましたね?それを楽しんでください。
データベースの仕事は、存在しないデータを保存することです。もちろん、文字列でそれを行うこともできますが、それを解析して、他の形式で表示するのに役立つようにする必要があります。DBが提供するあらゆるタイプの標準の解析済みフォームに保存することで、プレゼンテーションを決定することなく、できる限りプレゼンテーションの準備が整います。DBがそのタイプを文字列、整数、またはバイトでバッキングするかどうかは、私にとって実際には関係ありません。それが何をしているかを知っている限り。
ただし、日付を処理していることをDBに通知せず、日付を文字列として保存すると、他のすべてのプレゼンテーションよりも早めに1つのプレゼンテーションを提示することになります。これにより、変換する前に他のすべてのプレゼンターが解析されます。いいえ、データベースはプレゼンテーション層の一部ではありません。あるように頼まないでください。
同様に、プレゼンテーション層はデータベースの一部ではないため、レポートをデータベースの詳細に結合することは賢明ではありません。型を操作する方がはるかに堅牢です。
プレゼンテーション目的で日付を文字列に変換するには、ユーザー設定を知る必要があります。これは、通常、まったく同じ日付が異なるロケールのユーザーに対して異なる方法で表示されるためです。アプリケーションで単一のロケールを使用する場合でも、適切な動作では、データベースサーバーの代わりにアプリケーションのロケールを使用する必要があります。現時点で偶然一致したとしても、同一であるとは限りません。
ユニバーサル日付データ型からロケール固有の文字列への変換は、プレゼンテーション層で行われる必要があります。これは、変換がどのように実行されるべきかを知っているのは層だからです。
型には理由があります。利点が追加されない場合、それらは使用されず、使用されず、「型」のみが存在し、すべてがそのようになります。彼らは便利であるだけでなく、安全性と効率性も追加します。以下は、文字列ではなく、常にネイティブ形式で型を保持する必要がある理由のリストです。DateTime
ほとんどの場合、例として使用しましたが、整数、小数、バイナリなどのプリミティブ型にも同じ原理が適用されます。
ほとんどすべてのデータストアでは、データの制約を指定できます。これには型の制約が含まれます。DateTime
インスタンスを指定する主な利点の1つは、保存されたデータがそのタイプに制限されることです。データがストアに挿入された方法に関係なく、日時以外は入力できません。後者は、ストアと直接対話する複数のプロセスがある大規模なシステムにとって重要です。これには、2月はうるう年で29日、うるう年でない場合は28日しか持てないため、2月30日(任意の年)のような誤った日付を追加しようとすることも含まれます。
また、挿入された日付が現在の日付を超えないようにする、または開始日が終了日より前に発生するようにするなど、データストアに実装できる検証制約もあります。
ほとんどのデータ・ストアにも同様の操作/機能に組み込まれているDateAdd
か、DatePart
MS SQL Serverのインチ これにより、データがまだストアにある(まだアプリケーションに取得されていない)間に特定のデータのフィルタリングまたは選択を開始できます。
ネイティブタイプを使用することにより、ストアと対話する他の開発者またはシステムは、そのプリミティブタイプがどのように格納されるかについての詳細を知る必要がありません。その型が文字列として格納されている場合は、そうではありません。その場合、すべての人がそのDateTime
文字列表現の形式を理解していることを確認する必要があります。このシステムは、データ発信元のロケール、地域、文化にまたがるデータ、アプリケーションの物理的な場所、そのデータとやり取りするエンドユーザー/システムの属性を扱う場合に脆弱になります。例:ある国の日付形式はMM / dd / yyyy(米国のように)かもしれませんが、別の国ではdd / MM / yyyyである可能性があり、違いがほとんど不可能になることを検出します。
取得の速度、検証の速度、操作の速度、ストレージ効率もすべて重要な要素です。取得速度の例:データストアは列のインデックスを許可し、型がネイティブ形式で格納されている場合、これらのインデックスは一般的により効率的に使用できます。
開発者は再びストレージ形式を推測する必要がないため、ネイティブタイプシステムを使用すると、ストアに対するクエリの実行がより簡単になります。ほとんどすべてのデータストアアプリケーションプロバイダー(例:ado.net)は、渡されたネイティブ型に基づいて適切なパラメーター化されたクエリを作成するためのメカニズムを提供します。文字列で同じことを行うと、非常に面倒で壊れやすく/エラーが発生しやすくなります。
command.Parameters.Add(new SqlParameter("@startDate", SqlDbType.Date) {Value = myDateInstance.Date});
コード内のネイティブタイプは、.netタイプなどの標準操作も提供しSystem.Date
ます。操作は通常、日付の追加、日付の違いの検出など、数学的な性質を持っています。繰り返しますが、これは文字列型に対して簡単に行うことはできません。
プリミティブ型が最終的にプレゼンテーション層で文字列に変換されるとき(そうするためのプログラムスタック内の正しい場所)、プログラマーには、提示されたコンテキストに従って正しく表示するためのさまざまなオプションがあります。このコンテキストは通常、データの実際の意味とユーザーのロケールで構成されます。
例1日時インスタンスは、ユーザーのロケールに基づいて自動的にフォーマットできます。
DateTime.Now.ToString("D", CultureInfo.GetCultureInfo(userContext.Culture))
例2
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)だけでなく、そのタイムゾーンも含まれていることを意味します。 。UTCベースの時間文字列を強く好みます。
長所:
短所:
誰かがこれをやりたいと言ったら、「なぜ?」あまり意味がないからです 誰かが日付を文字列として返したい理由が、それを直接表示するためである場合、これはDBの文字列を使用する正当な理由ではありません。