tyoshikawa1106のブログ

- Force.com Developer Blog -

SFDC:日時型をSOQLクエリで条件指定するときに注意すること

日時型をSOQLクエリで条件指定するときに注意することについてです。例えば作成日を条件に取得するようなケースがあたります。

f:id:tyoshikawa1106:20190919071350p:plain


日時型はSalesforceを普通に操作するような場面では下記のように表示されます。

「2019/09/19 7:10」


ですがApexなどでシステム上の値としては次の形で保持されています。GMT表記となり日本時間から9時間ずれた値として表示されます。

「2019-09-18T22:10:49.000+0000」

f:id:tyoshikawa1106:20190919071559p:plain

日付型や日時型の値を今日や昨日というように取得したい場合は日付リテラルの仕組みで取得できます。
f:id:tyoshikawa1106:20190919072318p:plain


「 WHERE CreatedDate = TODAY」というような記述ができます。これは実行ユーザのタイムゾーンに合わせて取得してくれるようです。

SELECT Name, CreatedDate FROM Account WHERE CreatedDate = TODAY ORDER BY CreatedDate

f:id:tyoshikawa1106:20190919072517p:plain

f:id:tyoshikawa1106:20190919072728p:plain


注意が必要なのは日付リテラルではなくDAY_ONLYなどの日付関数を利用する場合になります。
f:id:tyoshikawa1106:20190919073221p:plain


日付関数は協定世界時 (UTC)の値で返します。日本時間の9時より前の時間値は9時間ずれで前日扱いとなります。

WHERE DAY_ONLY(CreatedDate) =: targeDate
本日を条件に取得した場合

f:id:tyoshikawa1106:20190919073551p:plain

f:id:tyoshikawa1106:20190919073722p:plain

前日日付で取得する方法

f:id:tyoshikawa1106:20190919073838p:plain

f:id:tyoshikawa1106:20190919073854p:plain

検証コード
// 前日日付で実行
Date targeDate = System.today().addDays(-1); 

List<Account> accounts = [SELECT Name,CreatedDate FROM Account WHERE DAY_ONLY(CreatedDate) =: targeDate ORDER BY CreatedDate];

System.debug('取得結果 = ' + accounts.size());
for (Account account : accounts) {
    System.debug(account.Name + ' : ' + String.valueOf(account.CreatedDate));
}


上記のとおり日付関数だと作成日が本日のものでも前日の日付で取得される状態となります。開発者ガイドにも表記されていますが日付関数を利用してユーザのタイムゾーンに合わせるときには「convertTimezone」関数を使用します。

f:id:tyoshikawa1106:20190919074248p:plain


これで日付関数でもユーザのタイムゾーンに合わせてデータを取得できます。
f:id:tyoshikawa1106:20190919074400p:plain

その他の対応方法

頻繁に条件指定で使用する場合などでApex側でタイムゾーンを意識して処理を実装するのが大変な場合は数式で日付型に変換した値を用意すると便利かもしれません。

f:id:tyoshikawa1106:20190919075112p:plain


次のように当日日付として取得できました。
f:id:tyoshikawa1106:20190919075247p:plain

おまけ

日時型の項目はString.valueOf処理で文字列に変換するとユーザのタイムゾーンで表示されます。
f:id:tyoshikawa1106:20190919075540p:plain

関連