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

関連

SFDC:テストクラス判定できるTest.isRunningTest処理をつかったメンテナンス性の向上について

Apex開発でTest.isRunningTest処理を使ったメンテナンス性の向上についてです。
f:id:tyoshikawa1106:20190916103758p:plain

Salesforce Developers


Apex開発を行ったときにはテストクラスの作成が必要になります。テストクラスをきちんと作成することで既存処理への予期せぬ影響に気づけたり、実装した箇所の考慮漏れや実装ミスに気づくことができます。


・・・ですが処理の内容によってはテストクラスが作成しずらい場面がでてきます。


たとえば下記のような処理です。

// 次回スケジュールバッチ実行時間取得
Datetime nextBatchTime = Datetime.now().addMinutes(5);
// 次回スケジュールバッチ実行時間登録
OpportunityChatterPostBatchSchedule cls = new OpportunityChatterPostBatchSchedule();
String jobName = 'OpportunityChatterPostBatchScheduleJob_' + nextBatchTime.format('yyyyMMddHHmm');
String sch = nextBatchTime.format('0 m H d M ? yyyy');
// スケジュールバッチ登録
System.schedule(jobName, sch, cls);


上記の処理をそのままテスト実行すると下記のエラーが発生します。

System.AsyncException: "OpportunityChatterPostBatchScheduleJob_201909161032" という Apex ジョブはすでに実行がスケジュールされています。 3483
Class.OpportunityChatterPostBatch.finish: line 54, column 1

f:id:tyoshikawa1106:20190916104136p:plain


スケジュールバッチ処理実行時にジョブ名をユニークにするために日時を付与していますが、テストクラスで同じタイミングで複数呼び出しされることでユニークにならなくなってしまいました。こうした処理がある場合の対処方法として、テストクラスの実装を諦めるという手段もありますが、Test.isRunningTest処理を利用することできれいに解決できます。


Test.isRunningTest処理は「現在実行中のコードが、テストメソッドに含まれているコード」かを判別するための処理です。
f:id:tyoshikawa1106:20190916104550p:plain


これで下記のような書き方が可能となります。(if処理では「!」をつけてテストではない場合にという判定にできる)

if (!Test.isRunningTest()) {
    // テストでない場合にスケジュール登録処理を実行
    System.schedule(jobName, sch, cls); 
}


スケジュール登録処理のみスキップできるようになりテストクラスを開発できるようになります。ですが上記の判定方法だとif判定内の処理は絶対に実行できないためカバー率低下が発生します。この問題を回避するために下記の記述にした方が良いと思います。

// スケジュールバッチ登録
String nextBatchJobId = (!Test.isRunningTest()) ? System.schedule(jobName, sch, cls) : '';

f:id:tyoshikawa1106:20190916105754p:plain


テストクラスの実行判定は行単位で識別されるのでこの書き方ならカバー率低下を回避することができます。また必要に応じてテスト処理の場合のみ任意も戻り値を指定することも可能になります。


このようにTest.isRunningTest()をうまく利用することでテスト実装ができない問題を回避しつつ正しくテストを行い品質とメンテナンス性を向上することができると思います。

関連

SFDC:Apexバッチの数分おきに繰り返し実行を試してみました

Apexバッチを指定の時間や定期的に実行したい場合は、スケジュールバッチの仕組みを使って対応します。スケジュールバッチは「implements Schedulable 」を宣言したクラスを用意することで作成できます。

Scheduleクラス

f:id:tyoshikawa1106:20190916082622p:plain

Connectクラス

f:id:tyoshikawa1106:20190916082421p:plain


上記のようなクラスを用意するとApexクラスの設定で「Apex をスケジュール」の仕組みが利用できるようになります。
f:id:tyoshikawa1106:20190916082810p:plain


こちらがApexスケジュールの設定画面です。
f:id:tyoshikawa1106:20190916082918p:plain


開始日と終了日を設定でき、実行対象の曜日と時間を指定できます。一日一回のスケジュール実行という要件の場合はこちらの設定画面のみで対応できます。注意が必要なのは数分単位で実行したい場合です。Apex をスケジュールの設定では1時間単位でのみ実行時間を指定できます。そのため5分間隔や15分間隔での実行はサポートされていません。今回は設定ページのみでは実現できない数分間隔での実行方法を紹介します。


Apexバッチの処理は「コンストラクタ」「start」「execute」「finish」のメソッドで構成されます。「start」のメソッドで対象となるデータを取得します。「execute」のメソッドでメインの処理が実行されます。バッチサイズの件数分に分割して繰り返し処理を実行します。(バッチサイズ200件で1000件対象データがある場合は200×5回繰り返し実行されます。)「finish」のメソッドが最後に一回呼び出されて処理を実行します。

Apexバッチクラス

f:id:tyoshikawa1106:20190916083634p:plain


最後に実行される「finish」メソッドで次のスケジュールバッチを登録することが可能です。
f:id:tyoshikawa1106:20190916084102p:plain


スケジュールバッチは「System.schedule(jobName, sch, cls);」の処理で登録できます。ジョブ名、スケジュール実行時間、対象のスケジュールバッチクラスが引数として必要です。

/**
 * Finish
 */
public void finish(Database.BatchableContext BC) {
    // 次回スケジュールバッチ登録判定
    if (this.isNextBatch) {
        // 次回スケジュールバッチ実行時間取得
        Datetime nextBatchTime = Datetime.now().addMinutes(5);
        // 次回スケジュールバッチ実行時間登録
        OpportunityChatterPostBatchSchedule cls = new OpportunityChatterPostBatchSchedule();
        String jobName = 'OpportunityChatterPostBatchScheduleJob_' + nextBatchTime.format('yyyyMMddHHmm');
        String sch = nextBatchTime.format('0 m H d M ? yyyy');
        System.schedule(jobName, sch, cls);
    }
}

ジョブ名はユニークにする必要があります。Apex処理で自動登録する場合は実行日時などを追加するのが良さそうです。
スケジュール実行時間は文字列で宣言します。引数の渡し方はいくつか用意されていますが任意の時間に一回実行したい場合は下記の引数を渡します。

(秒 分 時 日 月 ? 年)

時間は24時間表記です。DateTime型の.formatでは「hh:mm:ss」と宣言できますが「hh」を「HH」と大文字で宣言することで24時間表記になります。また「H」とのみ宣言することで0埋めがされなくなります。


この方法で実行した結果がこちらです。約5分おきに実行されています。
f:id:tyoshikawa1106:20190916084729p:plain


検証時ですが20:00など切りの良い時間から開始しましたが一晩立つ頃には1分ズレが発生しました。こればバッチ実行は宣言してすぐに実行されない(一度キューに貯まる)ことと、Finsh時点での日時を基準に5分後で登録したので処理に時間がかかることで1分間のズレが発生したためと思います。


5分おきに実行する場合はこうしたズレも考慮した方が良いみたいです。またバッチのキューは一度に登録できる件数に上限があります。夜間バッチなど処理が多く実行される場合は登録をスキップするなどの考慮も必要になると思います。

補足

上記サンプルのバッチクラスでは下記の「Helper」クラスと「Dao」クラスを宣言しています。目的に合わせてクラスを分けるとメンテがしやすいと思います。

Helperクラス

f:id:tyoshikawa1106:20190916085723p:plain

Daoクラス

f:id:tyoshikawa1106:20190916085745p:plain

利用例

今回の数分単位でのバッチ実行ですが、例として新規商談を登録した際にChatterに投稿すると行った場面で利用できます。社内ユーザが新規商談を登録した際には何も気にせずプロセスビルダーでそのまま対応できますが、Force.comサイトで作成したフォーム経由で登録された場合など社外ユーザの作成時には通常Chatter投稿ができません。Apexのスケジュールバッチの場合は管理者権限で実行できるので、社外ユーザ権限で商談作成できる仕組みを構築したいときなどに利用できると思います。

関連・参考

SFDC:Apexで日付の曜日部分を取得する方法

Apexで日付の曜日部分を取得したいときは、一度日時型に変換して「.format('E')」の処理で取得できます。

f:id:tyoshikawa1106:20190907164758p:plain

// 月曜日
Datetime day1 = Datetime.newInstance(2019, 9, 9);
System.debug(day1.format('E'));

// 火曜日
Datetime day2 = Datetime.newInstance(2019, 9, 10);
System.debug(day2.format('E'));

// 水曜日
Datetime day3 = Datetime.newInstance(2019, 9, 11);
System.debug(day3.format('E'));

// 木曜日
Datetime day4 = Datetime.newInstance(2019, 9, 12);
System.debug(day4.format('E'));

// 金曜日
Datetime day5 = Datetime.newInstance(2019, 9, 13);
System.debug(day5.format('E'));

// 土曜日
Datetime day6 = Datetime.newInstance(2019, 9, 14);
System.debug(day6.format('E'));

// 日曜日
Datetime day7 = Datetime.newInstance(2019, 9, 15);
System.debug(day7.format('E'));

'月'、'火'ではなく'Mon'や'Thu'という形で取得できるのでそこから日本語表記には別途変換処理が必要になります。
f:id:tyoshikawa1106:20190907164929p:plain


変換用の共通クラスを用意しておくと使い回せると思います。

SFDC:関連レコードコンポーネントで商談に取引先の項目を表示するを試してみました

関連レコードコンポーネントをつかって商談に取引先の項目表示を試してみました。取引先の説明項目は自由入力のための項目で、補足や注意事項などユーザがメモしたい情報が登録されます。

f:id:tyoshikawa1106:20190829093555p:plain


商談のページに取引先の説明項目が表示されると商談のページのみで作業を進められて助かるという要望がありました。


最初に思いついたのは数式をつかった方法です。ですが数式項目はロングテキストエリア型の項目の値を参照することができません。取引先の説明項目はロングテキスト型の項目のため、数式による方法は実現不可でした。


数式対応は不可だったため検索してみたところワークフロールールで値を持ってくる方法が見つかりましたが、更新などのアクションが無いと更新処理が行えずに情報が古いままとなってしまう可能性があるので今回は見送り。


次に思いついたのはVisualforceページの埋め込みです。Lightningコンポーネントと違う部分で詳細ページレイアウト内の任意の位置に差し込むことができます。・・・が高さは固定値となるため見栄えが少し崩れる問題がありました。
f:id:tyoshikawa1106:20190829095010p:plain


どうしたものかなと悩んでいるところにTwitterで関連レコードコンポーネントをつかった方法を教えてもらいました。
f:id:tyoshikawa1106:20190829095816p:plain:w300


関連レコードで表示する場合は取引先のアクションを用意する必要があります。
f:id:tyoshikawa1106:20190829100100p:plain


レイアウトの設定で説明項目のみ表示させます。
f:id:tyoshikawa1106:20190829100140p:plain


アクションの準備ができたら商談のLightningページ設定で関連レコードコンポーネントを追加します。
f:id:tyoshikawa1106:20190829100456p:plain


ヘッダーの表示ラベルは任意のタイトルをつけたいときに入力します。参照項目は取引先を選択、更新アクションは先ほど作成した取引先の更新アクションを指定します。作成アクションは特に気にせずで大丈夫です。



これで商談の詳細ページに取引先の説明項目を表示できました。一つの取引先に複数の商談を作成したときにどの商談ページを開いていても共通の補足情報を表示できます。
f:id:tyoshikawa1106:20190829101001p:plain

関連レコードコンポーネント利用時の注意点

説明項目の文章量への考慮

関連レコードコンポーネントで説明項目を表示する場合、内容に応じて表示高さを自動調整してくれます。そのため文字の途中までしか表示されなかったり、続きはスクロールして確認というようなことは発生しないのですが、説明の値の行数が多くなってしまうとその下にある情報に気づきづらくなります。基本的には5〜10行ぐらいで管理するのがいいと思いますが、どうしてもながくなってしまう場合は別タブ表示などの対応を行ったほうがいいと思います。
f:id:tyoshikawa1106:20190829101529p:plain

一般ユーザへの編集権限の考慮

上記の方法で設定を行った場合、関連レコードコンポーネントのメニューには「参照」と「削除」の二種類が表示されていると思います。「参照」を選択すると参照元(この場合は取引先レコード)のページへ移動できます。
f:id:tyoshikawa1106:20190829101835p:plain


注意が必要なのは削除の方です。削除という表記ですが実態は取引先レコードとの関連付けを解除する操作になります。通常の編集ページでは商談レコードの取引先参照項目は必須項目となりますが、この部分から解除する場合は必須チェックの判定対象外として操作を行うことができます。なので知らぬ間に取引先と紐付かない商談が作成される可能性がでてきます。(補足として関連付けがクリアされるだけで取引先データ自体が削除されるわけではないため、一般ユーザの削除権限を無効化してもこの削除メニューは利用可能となってしまいます。)
f:id:tyoshikawa1106:20190829102206p:plain


この問題の対応方法は簡単で入力規則で対応できます。
f:id:tyoshikawa1106:20190829102731p:plain

f:id:tyoshikawa1106:20190829102828p:plain


ユーザには削除のメニューの利用は不要ですと伝えて基本的には操作しないルールとしつつ、誤って選択された場合は入力規則でブロックするという方法でシステムの整合性を担保できると思います。


関連レコードコンポーネントの利用に関してはこんな感じでした。説明項目など一部の情報のみ表示するという方法は今まで使ったことがなかったのですが非常に便利だと思います。鉛筆アイコンからデータの編集は可能ですが、そちらはプロファイルの編集権限で制御できると思います。(基本的に取引先で編集OKだったら編集できても問題はず。)

SFDC:関連レコードコンポーネントで商談に取引先の項目を表示するを試してみました

関連レコードコンポーネントをつかって商談に取引先の項目表示を試してみました。取引先の説明項目は自由入力のための項目で、補足や注意事項などユーザがメモしたい情報が登録されます。

f:id:tyoshikawa1106:20190829093555p:plain


商談のページに取引先の説明項目が表示されると商談のページのみで作業を進められて助かるという要望がありました。


最初に思いついたのは数式をつかった方法です。ですが数式項目はロングテキストエリア型の項目の値を参照することができません。取引先の説明項目はロングテキスト型の項目のため、数式による方法は実現不可でした。


数式対応は不可だったため検索してみたところワークフロールールで値を持ってくる方法が見つかりましたが、更新などのアクションが無いと更新処理が行えずに情報が古いままとなってしまう可能性があるので今回は見送り。


次に思いついたのはVisualforceページの埋め込みです。Lightningコンポーネントと違う部分で詳細ページレイアウト内の任意の位置に差し込むことができます。・・・が高さは固定値となるため見栄えが少し崩れる問題がありました。
f:id:tyoshikawa1106:20190829095010p:plain


どうしたものかなと悩んでいるところにTwitterで関連レコードコンポーネントをつかった方法を教えてもらいました。
f:id:tyoshikawa1106:20190829095816p:plain:w300


関連レコードで表示する場合は取引先のアクションを用意する必要があります。
f:id:tyoshikawa1106:20190829100100p:plain


レイアウトの設定で説明項目のみ表示させます。
f:id:tyoshikawa1106:20190829100140p:plain


アクションの準備ができたら商談のLightningページ設定で関連レコードコンポーネントを追加します。
f:id:tyoshikawa1106:20190829100456p:plain


ヘッダーの表示ラベルは任意のタイトルをつけたいときに入力します。参照項目は取引先を選択、更新アクションは先ほど作成した取引先の更新アクションを指定します。作成アクションは特に気にせずで大丈夫です。



これで商談の詳細ページに取引先の説明項目を表示できました。一つの取引先に複数の商談を作成したときにどの商談ページを開いていても共通の補足情報を表示できます。
f:id:tyoshikawa1106:20190829101001p:plain

関連レコードコンポーネント利用時の注意点

説明項目の文章量への考慮

関連レコードコンポーネントで説明項目を表示する場合、内容に応じて表示高さを自動調整してくれます。そのため文字の途中までしか表示されなかったり、続きはスクロールして確認というようなことは発生しないのですが、説明の値の行数が多くなってしまうとその下にある情報に気づきづらくなります。基本的には5〜10行ぐらいで管理するのがいいと思いますが、どうしてもながくなってしまう場合は別タブ表示などの対応を行ったほうがいいと思います。
f:id:tyoshikawa1106:20190829101529p:plain

一般ユーザへの編集権限の考慮

上記の方法で設定を行った場合、関連レコードコンポーネントのメニューには「参照」と「削除」の二種類が表示されていると思います。「参照」を選択すると参照元(この場合は取引先レコード)のページへ移動できます。
f:id:tyoshikawa1106:20190829101835p:plain


注意が必要なのは削除の方です。削除という表記ですが実態は取引先レコードとの関連付けを解除する操作になります。通常の編集ページでは商談レコードの取引先参照項目は必須項目となりますが、この部分から解除する場合は必須チェックの判定対象外として操作を行うことができます。なので知らぬ間に取引先と紐付かない商談が作成される可能性がでてきます。(補足として関連付けがクリアされるだけで取引先データ自体が削除されるわけではないため、一般ユーザの削除権限を無効化してもこの削除メニューは利用可能となってしまいます。)
f:id:tyoshikawa1106:20190829102206p:plain


この問題の対応方法は簡単で入力規則で対応できます。
f:id:tyoshikawa1106:20190829102731p:plain

f:id:tyoshikawa1106:20190829102828p:plain


ユーザには削除のメニューの利用は不要ですと伝えて基本的には操作しないルールとしつつ、誤って選択された場合は入力規則でブロックするという方法でシステムの整合性を担保できると思います。


関連レコードコンポーネントの利用に関してはこんな感じでした。説明項目など一部の情報のみ表示するという方法は今まで使ったことがなかったのですが非常に便利だと思います。鉛筆アイコンからデータの編集は可能ですが、そちらはプロファイルの編集権限で制御できると思います。(基本的に取引先で編集OKだったら編集できても問題はず。)

SFDC:Dreamforce 2019の登録サイトがオープンしました

Dreamforce 2019の登録サイトがオープンしました。

f:id:tyoshikawa1106:20190820233125p:plain

https://www.salesforce.com/dreamforce/

開催期間は現地時間で11月19日(火)〜11月22日(金)です。
f:id:tyoshikawa1106:20190820233308p:plain:w300


18日(月)はDreamforceの前日ですが参加を証明するバッチの受付が開始されます。(Registration and Badge Pickup)
f:id:tyoshikawa1106:20190820233504p:plain


時差のことを考慮すると日本から参加する場合はこんな感じのスケジュールになると思います。

  1. 日本時間:11/18 (月) - 日本の空港出発
  2. 現地時間 : 11/18 (月) - サンフランシスコ空港到着。市内へ移動して参加者バッチをもらう。ホテルチェックイン。
  3. 現地時間 : 11/19 (火) - DF19 Day 1 (イベント初日)
  4. 現地時間 : 11/20 (水) - DF19 Day 2
  5. 現地時間 : 11/21 (木) - DF19 Day 3
  6. 現地時間 : 11/22 (金) - DF19 Day 4 (イベント最終日)
  7. 現地時間 : 11/23 (土) - ホテルチェックアウト。サンフランシスコ空港出発。
  8. 日本時間 : 11/24 (日) - 帰国


Dreamforceの登録はまだやっていないのですが、8月中か9月前半には済ませておいた方が良いのかなと思います。それよりも優先度の高い対応事項があります。ホテルの予約と飛行機の予約です。
※8/24でソウルドアウトでした。公開されたら直ぐに買わないとダメだった。。

ホテルの予約について

Dreamforceの開催期間中サンフランシスコのホテルの価格が高騰します。滞在期間も5泊となるので多めの予算が必要です。また会場に近いホテルは比較的に早く埋まるため参加を検討する場合でまだ決めていない場合は早めに予約を済ませた方が良いと思います。


ホテルに関しては昨年の2018-09-16頃にDreamforce2019のスケジュールが発表された時点で予約したのがひとまず問題ありませんでした。(ホテルは予約キャンセルが可能になっている場合が多いので一旦予約しておくということが一応可能です。※参加できそうにない場合は早めにキャンセル手続きしないと迷惑をかけてしまいますが)

飛行機の予約について

今回...というか今朝(19日の朝)に気づいてちょっと焦ったのが飛行機の予約の方です。飛行機は予約キャンセルプランにすると料金が上がってしまうので参加できることを確認してから予約する方が良いと思います。6月とか7月とかに予約を済ませておけば良かったのですが8月後半まで後回しにしてしまった結果、飛行機の予約の選択肢がほぼなくなってました。

成田→サンフランシスコ(18日の出発)

こっちはまだ大丈夫。選択肢たくさん。
f:id:tyoshikawa1106:20190820235200p:plain

サンフランシスコ→成田(23日の出発)

空きが早朝の一つだけ、しかも乗継一回の便。
f:id:tyoshikawa1106:20190820235242p:plain


なお、成田ではなく羽田で検索してもけっこう厳しい。
f:id:tyoshikawa1106:20190820235559p:plain


完全にやってしまった状態だったのでANAを諦めて他の航空会社で検索してみました。

JAL

検索の仕方が良くないのか直行便が見つからず。。
f:id:tyoshikawa1106:20190821000027p:plain

ユナイテッド航空

往路。
f:id:tyoshikawa1106:20190821000418p:plain


復路。
f:id:tyoshikawa1106:20190821000446p:plain


合計。まだ選択肢が多いし直行便で行けるけど少し予算が。
f:id:tyoshikawa1106:20190821000502p:plain:w300



直行便で18日に出発して23日の便で帰ろうと思ったらユナイテッド航空の選択肢しかなさそうでした。。今回はユナイテッド航空さんにお世話になるか ‐‐‐と考えていたところで一つ選択肢が浮かびました。帰国日ずらす方法 - そもそものスケジュールの変更です。


再検索してみた結果。ぎりぎり選択肢が増えました。
f:id:tyoshikawa1106:20190821001526p:plain



スケジュール調整する場合、もう一つ気にしないと行けないのが宿泊場所です。18日から23日の場合は5泊で済みますが、24日以降に延長する場合はその分の宿泊ホテルを探す必要があります。ただ...ホテル予約でお気に入りのBooking.comとHotels.comで検索してみたところ、宿泊料金は比較的リーズナブルでした。
※24日以降はDreamforceの開催期間ではないため、通常料金に戻っているようです。23日に無理して帰るよりも一泊二泊した方がお釣りが来るぐらいでした。
※今回調べてみたのはサンフランシスコ空港の近くのホテルです。


こんな感じで23日発の飛行機予約はかなり厳しかったですが24日や25日まで滞在を延長して見たほうがやすく帰れそうです。とりあえずDreamforceへの参加を検討される場合はホテルと飛行機の確保を最優先に行動した方が良いと思います。