完璧じゃなくてもとりあえず終わらせるブログ

主にSalesforceの悪夢を記録しています

Salesforceのシステム日付を変更したい

Salesforceのシステム日付は変更できるか?

結論:できません

残念ながらできません。
自前のサーバーであれば当然可能ですが、SalesforceのようなSaaSでシステム日付を任意に変更することはできません。

でも、開発したApplicationのテストを実施する場合など、システム日付を変更したいという場面はよくありますよね。
だから無理やり頑張ってみる。


Apexテストクラスのために変更したいだけなら

Test.isRunningTest()

を使用することでなんとか実現することはできるでしょう。

例えば

public with sharing class SampleCls {
    public SampleCls() {
        /* 前略 */

        // システム日付を取得
        //Date today = Date.today();      // ← この取得方法を避ける
        Date today = SampleCls.getSystemToday();
        System.debug('today:' + today);

        /* 後略 */
    }

    // テストクラス実行時は2022/01/01を返却
    private static Date getSystemToday() {
        return !Test.isRunningTest() ? Date.today() : Date.newInstance(2022, 1, 1);
    }
}

このように書けば、テストクラス実行中のみ日付を指定できます。

テストクラス側で日付を指定したい場合は、

  1. テスト対象クラス(ここではSampleCls)側に日付をセットする用のプロパティを持たせる
  2. そのプロパティに@TestVisibleアノテーションを付ける
  3. テストクラスでプロパティに値をセットする

といったことをすればなんとかなりそう。

でもさすがに場当たり的だし、開発したApplicationを動かすときには使えない。

カスタム表示ラベルとUtility.clsで頑張る

そもそも論ですよ。開発初期にこんな仕組みにしておく。

システム日付をセットする用のカスタム表示ラベルを作成する
変更したいときはyyyyMMddを指定、普段は - を指定
Utility.clsで取得用メソッドを用意
public inherited sharing class Utility {

    //テストクラス用に SYSTEM_TODAYの上書きを許可
    @TestVisible
    private static Date systemTodayForTest;

    /**
     * SYSTEM_TODAY
     * 	@return カスタム表示ラベルから日付が取得できた場合はその日付を返す
     *          取得できない場合はSFDCのシステム日付を返す
     */
    public static Date SYSTEM_TODAY() {
        try {
            Date sysdate = stringToDate(Label.SYSTEM_TODAY);

            //テスト実行時のみ上書き可能
            if (Test.isRunningTest() && systemTodayForTest != null) {
                return systemTodayForTest;
            }

            if (sysdate == null) {
                return Date.today();
            }

            return sysdate;
        } catch (Exception e) {
            return Date.today();
        }
    }

    /**
     * String型をDate型に変換
     */
    public static Date stringToDate(String str) {
        if (str == null || str.length() != 8) {
            return null;
        }
        Integer year = Integer.valueOf(str.substring(0, 4));
        Integer month = Integer.valueOf(str.substring(4, 6));
        Integer day = Integer.valueOf(str.substring(6, 8));

        return Date.newInstance(year, month, day);
    }
}


そして、コーディング規約として以下を定める。
システム日付を取得する場合は、Utility.SYSTEM_TODAY()を使用すること


これなら開発したApplicationを未来日付で動かしたい、という要望があってもカスタム表示ラベルを変更するだけで実現できますね。

Utility.clsには systemTodayForTest も持たせたのでテスト実行時にも対応可能です。


よし、とりあえず終わらせたぞ