日時型をSOQLクエリで条件指定するときに注意することについてです。例えば作成日を条件に取得するようなケースがあたります。
日時型はSalesforceを普通に操作するような場面では下記のように表示されます。
「2019/09/19 7:10」
ですがApexなどでシステム上の値としては次の形で保持されています。GMT表記となり日本時間から9時間ずれた値として表示されます。
「2019-09-18T22:10:49.000+0000」
日付型や日時型の値を今日や昨日というように取得したい場合は日付リテラルの仕組みで取得できます。
「 WHERE CreatedDate = TODAY」というような記述ができます。これは実行ユーザのタイムゾーンに合わせて取得してくれるようです。
SELECT Name, CreatedDate FROM Account WHERE CreatedDate = TODAY ORDER BY CreatedDate
注意が必要なのは日付リテラルではなくDAY_ONLYなどの日付関数を利用する場合になります。
日付関数は協定世界時 (UTC)の値で返します。日本時間の9時より前の時間値は9時間ずれで前日扱いとなります。
WHERE DAY_ONLY(CreatedDate) =: targeDate
本日を条件に取得した場合
前日日付で取得する方法
検証コード
// 前日日付で実行 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」関数を使用します。
これで日付関数でもユーザのタイムゾーンに合わせてデータを取得できます。
その他の対応方法
頻繁に条件指定で使用する場合などでApex側でタイムゾーンを意識して処理を実装するのが大変な場合は数式で日付型に変換した値を用意すると便利かもしれません。
次のように当日日付として取得できました。
おまけ
日時型の項目はString.valueOf処理で文字列に変換するとユーザのタイムゾーンで表示されます。