日時属性の動作と形式

注意

Effective November 2020:

  • Common Data Service has been renamed to Microsoft Dataverse. Learn more
  • Some terminology in Microsoft Dataverse has been updated. For example, entity is now table and field is now column. Learn more

This article will be updated soon to reflect the latest terminology.

世界中にユーザーと事務所がある場合、複数のタイム ゾーンで日付と時刻の値を適切に表現することが重要です。 DateTimeAttributeMetadata (DateTimeAttributeMetadata EntityType または DateTimeAttributeMetadata クラス) は、Common Data Service で型 DateTime の属性を定義および管理するために使用されます。 DateTimeBehavior プロパティを使用して(組織サービスについては、 DateTimeAttributeMetadata.DateTimeBehaviorを参照してください)、日付と時刻の値をタイムゾーン情報を付けて格納するか、付けないで格納するかを定義し、 DateTimeAttributeMetadata.Format プロパティを使用してこれらの属性の表示形式を指定します。

また、 Common Data Service のカスタマイズ領域を使用して、日時属性の動作と形式を定義します。 詳細: 日時フィールドの動作と形式

注意

Common Data Service では、すべての日付と時刻の属性は 1753 年 1 月 1 日午前 12:00 以降の日付をサポートします。

日時属性の動作の指定

DateTimeBehavior (DateTimeBehavior ComplexType または DateTimeBehavior クラス) を使用して、 DateTimeAttributeMetadata EntityType.DateTimeBehavior プロパティの値を指定することができます。 DateTimeBehavior には次のメンバーが含まれます。各メンバーは、メンバー名と同じ値の文字列を返します:

メンバーの名前および値 内容
UserLocal - 日時値を UTC 値としてシステムに格納します。
- 取得操作によって UTC 値が返されます。
- 更新操作は UTC 値を現在のユーザーのタイム ゾーン値に変換し、更新に対して指定された値の種類 (DateTimeKind) 基づいて、更新された値をそのまま、あるいは同等の UTC 値として格納します。 指定された値の種類が UTC の場合は、そのまま格納されます。 そうでない場合は、UTC 相当値が格納されます。
- 書式設定された値を取得すると、UTC から、ユーザーのタイム ゾーンとロケールの設定に基づいて、ユーザーの現在のタイム ゾーンを変換されます。
- ウェブAPIの場合、属性は DateTimeOffset として公開されます。
- この動作は、 CreatedOn および ModifiedOn のようなシステム属性に対して使用され、変更することはできません。 日時値をタイム ゾーン情報を付けて格納するユーザー定義属性の動作に対して、これを使用します。
DateOnly - 時刻値なしで、実際値の日付の値を格納します。
- フォーマットされた値を取得すると、日付の値が表示されます。
- Web API の場合、属性は Date として公開されます。
- この動作は、時刻情報が必要とされない生年月日や記念日を格納する、ユーザー定義属性に対して使用します。
TimeZoneIndependent - ユーザーのタイムゾーンに関係なく、実際の日時値をシステムに格納します。
- 取得および更新操作の場合、タイム ゾーンの変換は行われません、実際の日付と時刻の値が返されて、ユーザーのタイム ゾーンに関係なく、システム内でそれぞれ更新されます。
- 書式設定された値を取得すると、現在のユーザーのタイム ゾーンとロケールの設定で指定された形式に基づいて、日付と時刻の値が (タイム ゾーンの変換なしで) 表示されます。
- ウェブAPIの場合、属性は DateTimeOffset として公開されます。
- この動作は、ホテルのチェックインおよびチェック アウトの時間などの情報を格納する属性に対して使用されます。

次のサンプル コードは、新しい日時属性の UserLocal 動作の設定方法を示しています。

// Create a date time attribute for the Account entity
// with the UserLocal behavior
dtAttribute = new DateTimeAttributeMetadata
{                             
   SchemaName = "new_SampleDateTimeAttribute",
   DisplayName = new Label("Sample Date Time Attribute", _languageCode),
   RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),                
   Description = new Label("Created by SDK Sample", _languageCode),                
   DateTimeBehavior = DateTimeBehavior.UserLocal,
   Format = DateTimeFormat.DateAndTime,
   ImeMode = ImeMode.Disabled
};

CreateAttributeRequest createAttributeRequest = new CreateAttributeRequest
{
   EntityName = Account.EntityLogicalName,
   Attribute = dtAttribute
};
_serviceProxy.Execute(createAttributeRequest);
Console.WriteLine("Created attribute '{0}' with UserLocal behavior\nfor the Account entity.\n", 
                           dtAttribute.SchemaName);

このサンプル コードでは、文字列値 DateTimeBehavior = "UserLocal" を直接指定することによって、 DateTimeBehavior プロパティの値を設定することもできます。

日時属性の作成時に、動作を指定しない場合、既定で、属性は UserLocal 動作で作成されます。 完全なコード サンプルは、 サンプル: 日時の値の変換を参照してください。

重要

  • 動作を DateOnly または TimeZoneIndependent に設定した状態で、日時属性を作成すると、属性の動作は変更できません。 詳細: DateTime 属性の動作の変更
  • 動作が DateOnly または TimeZoneIndependent の日時属性は、 Dynamics 365 for Outlook の以前のバージョンでオフライン モードで編集すると、 UserLocal 動作を使用しているかのように処理されます。 これは、このクライアントが新しい動作を認識せず、その動作を UserLocal と区別して処理しないことによります。 日時属性はアップグレードで新しい動作に変換されません。したがって、ベスト プラクティスは、カスタマイザーが新しい動作のいずれかを採用する前に、すべての Common Data Service クライアントを最新のリリースにアップグレードすることです。 オンライン時には、フィールドのデータを新しい行動で編集しても問題なく動作します。

日時属性の形式の指定

Format プロパティを使用して、属性がシステムにどのように保存されているかに関係なく、属性の日付/時刻の表示形式を指定します。 DateTimeFormat 列挙体(DateTimeFormat EnumType or DateTimeFormat 列挙体)を使用して、 DateAndTime または DateOnly のいずれかの表示形式を指定できます。

DateTimeAttributeMetadata.DateTimeBehavior プロパティが DateOnly に設定されている場合、 DateTimeAttributeMetadata.Format プロパティの値を DateAndTime に設定または変更することはできません。

[日付のみ] の動作でサポートされない日付および時刻のクエリ演算子

時刻関連のクエリ演算子は、 DateOnly 動作に対してはサポートされません。 ここに表示されている時間固有のクエリ演算子を除いて、すべてのクエリ演算子がサポートされます。

  • が X 分よりも古い

  • が X 時間よりも古い

  • 過去 X 時間

  • 今後 X 時間

詳細: FetchXML の日時クエリ演算子

日時属性の動作の変更

Common Data Service インスタンスでシステム カスタマイザー ロールを所有していて、日時属性の DateTimeAttributeMetadata.CanChangeDateTimeBehavior の管理プロパティが True に設定されている場合、日時属性を更新してその動作を変更できます。

注意事項

日時属性の動作を変更するには、その前に、業務ルール、ワークフロー、計算フィールド、またはロールアップ属性などの属性のすべての依存性を検討して、動作の変更によって問題が発生しないことを確認する必要があります。 システム カスタマイザは、 DateTimeAttributeMetadata.CanChangeDateTimeBehavior マネージド プロパティを使用して、既存の日時属性の動作の変更を制限できます。

少なくとも、日時属性の動作を変更した後、変更した日時属性に依存する、業務ルール、ワークフロー、計算属性、およびロールアップ属性の各レコードを開いて、情報を確認し、そのレコードを保存して、最新の属性の動作と値が使用されることを確認する必要があります。

計算属性またはロールアップ属性の日時動作の変更後、計算フィールドまたはロールアップ フィールドの定義エディターを開いて、そのフィールド定義を保存して、動作の変更後、それらの属性が引き続き有効であることを確認します。 システム カスタマイザは、 Common Data Service のカスタマイズ領域の フィールドの種類 の横にある 編集 をクリックして、計算属性またはロールアップ属性に対するフィールド定義エディターを開くことができます。 詳細: 計算フィールドの定義 および ロールアップ フィールドの定義

  • 標準のエンティティとユーザー定義エンティティの CreatedOn および ModifiedOn 属性の動作は、既定では、 UserLocal に設定され、 DateTimeAttributeMetadata.CanChangeDateTimeBehavior 管理プロパティは False に設定されます。このことは、これらの属性の動作は変更できないことを意味します。 ユーザー定義エンティティのこれらの属性の DateTimeAttributeMetadata.CanChangeDateTimeBehavior 管理プロパティの値を変更することはできますが、属性の動作は変更できません。

  • 新しいユーザー定義の日時属性の場合は、 DateTimeAttributeMetadata.CanChangeDateTimeBehavior 管理プロパティが True に設定されています。 このことは、ユーザー定義の日時属性の動作を、 UserLocal から DateOnly または TimeZoneIndependent のいずれかに変更できることを意味しています。他の動作の移行は使用できません。

    Common Data Service 組織の一部であるユーザー定義の日時属性の場合は、その属性または親エンティティがカスタマイズ可能でなければ DateTimeAttributeMetadata.CanChangeDateTimeBehavior 管理プロパティは True に設定されます。

    注意

    属性の DateTimeAttributeMetadata.DateTimeBehavior プロパティを UserLocal から DateOnly に更新するときは、DateTimeAttributeMetadata.Format プロパティもかならず DateAndTime から DateOnly に変更してください。 そうしなければ、例外が発生します。

  • Common Data Service の次の標準の日時属性は、既定では、DateOnly に設定され、これらの属性の DateTimeAttributeMetadata.CanChangeDateTimeBehavior 管理プロパティは False に設定されます。このことは、これらの属性の動作は変更できないことを意味します。

    日付と時間の属性です。 上位エンティティ
    anniversary 取引先担当者
    birthdate 取引先担当者
    duedate 請求書
    estimatedclosedate リード
    actualclosedate 営業案件
    estimatedclosedate 営業案件
    finaldecisiondate 営業案件
    validfromdate 製品
    validtodate 製品
    closedon 見積もり
    expireson 見積もり

    これらの属性の動作を UserLocal に、DateTimeAttributeMetadata.CanChangeDateTimeBehavior 管理プロパティを True に設定し、 これらの属性の動作を DateOnly のみに変更できます。 他の動作の移行は使用できません。

属性の動作の更新後、変更が有効になるには、そのカスタマイズを公開する必要があります。 日時属性の動作を更新することによって、属性の動作の変更 に入力または更新されたすべての値が、新しい動作でシステムに格納されるようになります。 これは、データベースにすでに格納されている値には影響を与えず、それらは引き続き UTC 値として保存されます。 ただし、既存の値を SDK を使用して取得したり、UI でそれを表示するときは、既存の値はその属性の新しい動作にしたがって表示されます。 たとえば、取引先企業エンティティに関するユーザー定義の属性の動作を、 UserLocal から DateOnly に変更し、SDK を使用して既存の取引先企業レコードを取り出した場合、日付と時刻は、 <Date> の後に 12 AM (00:00:00) が続く形式で表示されます。 同様に、 UserLocal から TimeZoneIndependent への動作の変更の場合、データベースにある実際の値は、タイム ゾーンの変換なしに、そのまま表示されます。

次のサンプル コードは、新しい日時属性動作の更新方法を示しています。

// Retrieve the attribute to update its behavior and format
RetrieveAttributeRequest attributeRequest = new RetrieveAttributeRequest
{
    EntityLogicalName = Account.EntityLogicalName,
    LogicalName = "new_sampledatetimeattribute",
    RetrieveAsIfPublished = false
};
// Execute the request
RetrieveAttributeResponse attributeResponse =
                (RetrieveAttributeResponse)_serviceProxy.Execute(attributeRequest);

Console.WriteLine("Retrieved the attribute '{0}'.",
                attributeResponse.AttributeMetadata.SchemaName);

// Modify the values of the retrieved attribute
DateTimeAttributeMetadata retrievedAttributeMetadata =
                (DateTimeAttributeMetadata)attributeResponse.AttributeMetadata;
retrievedAttributeMetadata.DateTimeBehavior = DateTimeBehavior.DateOnly;
retrievedAttributeMetadata.Format = DateTimeFormat.DateOnly;

// Update the attribute with the modified value
UpdateAttributeRequest updateRequest = new UpdateAttributeRequest
{
    Attribute = retrievedAttributeMetadata,
    EntityName = Account.EntityLogicalName,
    MergeLabels = false
};
_serviceProxy.Execute(updateRequest);
Console.WriteLine("Updated the behavior and format of '{0}' to DateOnly.",
    retrievedAttributeMetadata.SchemaName);

// Publish customizations to the account entity
PublishXmlRequest pxReq = new PublishXmlRequest
{
    ParameterXml = String.Format("<importexportxml><entities><entity>account</entity></entities></importexportxml>")
};
_serviceProxy.Execute(pxReq);
Console.WriteLine("Published customizations to the Account entity.\n");
 

完全なコード サンプルは、 サンプル: 日時の値の変換を参照してください。

データベース内の既存の日時値の動作の変換

日時属性を更新して、属性の動作を UserLocal から DateOnly または TimeZoneIndependent に変更する場合、データベース内の既存の属性値は自動的に変換されません。 この属性の変更は、その属性の変更 に、属性に入力または属性内で更新された値にのみ影響します。 システム内の既存の日付および時刻の値は引き続き UTC 形式であり、前のセクションで説明したとおりに、SDK を使用してまたは UI で取得されたときに、新しい動作にしたがって Common Data Service によって表示されます。 UserLocal から DateOnly に行動が変更された属性の場合、 ConvertDateAndTimeBehavior メッセージを使用して、データベース内の既存の UTC 値を適切な DateOnly 値に変換して、データのアノマリを回避することができます。

このメッセージを使用すると、UTC から DateOnly への値の変換に使用するタイム ゾーンを選択するための変換ルール (組織サービスと連携する場合、 ConversionRuleを参照してください) を指定できます。 次のいずれかの変換ルールを指定できます。

  • SpecificTimeZone: 指定された Common Data Service タイム ゾーンに従い、UTC 値を DateOnly 値に変換します。 この場合、 TimeZoneCode パラメーターの値を指定する必要もあります。

  • CreatedByTimeZone: UTC 値を、レコードを作成したユーザーの UI に表示される DateOnly 値に変換します。

  • OwnerTimeZone: UTC値を、レコードを所有するユーザーの UI に表示するDateOnly値に変換します。

  • LastUpdatedByTimeZone: UTC 値を、レコードを最後に更新したユーザーの UI に表示する DateOnly 値に変換します。

DateTimeBehaviorConversionRule クラスの 4 つのメンバーのいずれかを使用して、 ConversionRule パラメーターの有効な値を指定できます。

注意

ConvertDateAndTimeBehaviorRequest メッセージを実行するには、 Common Data Service インスタンスのシステム管理者ロールが必要です。

ConvertDateAndTimeBehavior (組織サービスと連携する場合、 ConvertDateAndTimeBehaviorRequest メッセージを参照してください)を実行するとき、システム ジョブ (非同期処理) が作成されて、変換要求が実行されます。 メッセージ応答の ConvertDateAndTimeBehaviorResponse.JobId 属性には、変換の結果として作成されたシステム ジョブの ID が表示されます。 システム ジョブが完了したら、ジョブの詳細 (AsyncOperation.Message) をチェックして、変換の詳細またはエラーを必要に応じて表示します。

注意

複数の属性の変換を 1 つの変換ジョブにまとめて、1 つのジョブを一度に実行することを推奨します。これにより、変換時に競合がなくなり、また最適なシステム パフォーマンスが得られます。

ConvertDateAndTimeBehavior メッセージを使用する際に、以下のいくつかの考慮を必要とする重要な点があります。

  • ソリューションのインポート、または属性や上位エンティティの削除などのメッセージの実行中は、 Common Data Service 内のソリューションの大きな変更は避ける必要があります。 これを行うと、予期しない動作が発生することがあります。ただし、データの損失は発生しません。

  • メッセージの実行結果としてシステムで行われる更新では、ワークフローとプラグインは実行されません。

  • メッセージの実行結果としてシステムで行われる更新では、属性の "最終修正日" の値は変更されませんが、更新の監査が行われて、管理者が属性の変換の時刻および元の値と変更後の値を確認するのを支援します。

次のサンプル コードは、 メッセージの使用方法を示しています。

ConvertDateAndTimeBehaviorRequest request = new ConvertDateAndTimeBehaviorRequest()
{
    Attributes = new EntityAttributeCollection() 
            { 
                new KeyValuePair<string, StringCollection>("account", new StringCollection() 
                { "new_sampledatetimeattribute" }) 
            },
    ConversionRule = DateTimeBehaviorConversionRule.SpecificTimeZone.Value,
    TimeZoneCode = 190, // Time zone code for India Standard Time (IST) in CRM
    AutoConvert = false // Conversion must be done using ConversionRule
};

// Execute the request
ConvertDateAndTimeBehaviorResponse response = (ConvertDateAndTimeBehaviorResponse)_serviceProxy.Execute(request);

完全なコード サンプルは、 サンプル: 日時の値の変換を参照してください。

タイムゾーンを使用するためのベスト プラクティス

期待していた自分の日付/時刻フィールド (UTC/ローカル) で、反対の値が表示されています

これは、エンティティフィールドの設定とアプリフォームの設定の間にパリティがないために発生します。 エンティティ フィールドが [タイムゾーン非依存] または [ユーザーローカル] に構成されている場合、データがストアから取得されるときに、タイムゾーンのオフセットが適用されるかどうかが決まります。 ただし、アプリ フォームには UTC またはローカルの設定もあります。

これは Common Data Service から受け取ったデータを解釈する方法をフォームに伝えます。 ストアから取得したデータがタイムゾーンに依存しないが、フォームがローカルに設定されている場合、UTC データはユーザーのタイムゾーンに基づいてユーザーのローカルタイムとしてプロファイルに表示されます。 この逆も当てはまります。フォームが UTC に設定されている場合、ストアからのユーザーローカル値は UTC として表示されます。 幸い、フォームの日付タイムゾーン値は、既存のレコードを中断することなく変更できます。

エンティティ フィールドで [日付のみ] を選択しましたが、フォームには日付ピッカーが表示されています。

これは、日付のみのフィールドに対してタイムゾーン非依存またはユーザー ローカルの動作を選択した場合に発生します。 規定では Common Data Service が 00:00:00 の時刻を保存しますが、フィールドをフォームに追加する場合は時刻も設定する必要があると想定します。 フォームに時間ピッカーを残した場合、ユーザーは時間を入力でき 00:00:00 以外として保存されます。 こちらがこれを修正する方法です。

  • フォームを編集して、時間ピッカーと関連する数式を削除します。 これにより、時刻が 00:00:00 として保存され、タイムゾーン ベースの日付計算が可能になります。
  • 現在、フィールドはユーザー ローカルに設定されており、日付をタイムゾーンで計算する必要がない場合は、日付のみに変更できます。 この変更は永続的であり、元に戻すことができません。 この変更は、タイムゾーンに依存しない動作フィールドに対して行うことはできません。 他のアプリ、プラグイン、ワークフローがデータに依存している可能性があるため、動作の変更には常に注意してください。

日付のみのフィールドがありますが、一部のユーザーに間違った日付が表示されています

これが発生した場合は、日付のみのフィールドに設定されている動作を確認してください。 フィールドがタイムゾーン非依存またはユーザーローカルに設定されている場合、含まれるタイム スタンプにより、日付がユーザーごとに異なって表示されます。 UTC やローカルのフォーム表示設定により、表示される日付がユーザーのタイムゾーン設定を使用して計算されるのか、それとも UTC 値として表示されるのかが決まります。 フォームの値をユーザー ローカルではなく UTC に変更すると、タイムゾーン オフセットの計算ができなくなり、保存されたレコードの UTC での日付が表示されます。 または、これを変更しない静的な日付にする必要があり、フィールドが現在ユーザー ローカルである場合は、フィールド動作を日付のみに変更できます。 これは元に戻すことはできませんのでご注意ください。

私 (スクリプト/プラグイン) は、ユーザー ローカル変換が発生する前に、ユニバーサル クライアントを使用して送信された日付をインターセプトする必要がありますが、代わりにユーザー ローカル データとして扱われます

UTC とユーザー ローカルの間でデータが変換される場合、Web クライアントとユニバーサル クライアントの動作は少し異なります。 Web クライアントでは、日付がクライアントに入力され、提供されたとおりに API に渡され、後でユーザーのローカル時間に変換されます。 これにより、スクリプト/プラグインがデータを取得し、データがプラットフォーム サービスに渡されてユーザーのローカル時間に変換される前にアクションを実行できるようになりました。 ユニバーサル クライアントでは、データが API に渡される前に日付からユーザーローカル値への変換が行われます。これにより、提供されるデータは UTC 日付ではなく、取得または投稿したユーザーに基づいてユーザー ローカルになります。 これを解決するには、ユーザーは次のいずれかを実行できます。

  • フォームを UTC 値を保持するタイムゾーン非依存に変更します。 これは、ユーザーがユーザー ローカル時間でフォームを表示する必要がない場合にのみ機能します。
  • スクリプトを変更して、使用されているタイムゾーン オフセットを検出し、スクリプト内で UTC に再計算して、アクションを実行します。

関連項目

サンプル: 日時の値の変換
日時フィールドの動作と形式
エンティティ属性メタデータのカスタマイズ
ConvertDateAndTimeBehaviorRequest
DateTimeAttributeMetadata ブログ: Common Data Service でタイムゾーンを使用して作業する