Automation Anywhere A2019 変数型「日時 (Datetime)」に関するTips～稼働日も判定可能

Automation Anywhere A2019では、変数に型の宣言が必要になりました。一番使うことが多いのは「文字列型」だと思いますが、日付や時間を格納する日時型 (Datetime) もうまく使うと便利です。この型を使っていていくつか気づいたことをメモしておきます。

**環境**

* Automation Anywhere Enterprise A2019.13 (ビルド4705) 

**参考記事**

* [Automation Anywhere A2019で変数を使う (v11との比較)](https://qiita.com/RPAbot/items/efdd03462e35dad35012)
* [変数の概要](https://docs.automationanywhere.com/bundle/enterprise-v2019/page/enterprise-cloud/topics/aae-client/bot-creator/using-variables/cloud-using-variables.html?_LANG=jpjp) - 製品ドキュメント
* [日付時刻 パッケージ](https://docs.automationanywhere.com/bundle/enterprise-v2019/page/enterprise-cloud/topics/aae-client/bot-creator/commands/cloud-date-time-operations-command.html?_LANG=jpjp) - 製品ドキュメント
* [日付時刻の形式](https://docs.automationanywhere.com/bundle/enterprise-v2019/page/enterprise-cloud/topics/aae-client/bot-creator/commands/cloud-date-time-formats.html?_LANG=jpjp) - 製品ドキュメント
* [Automation Anywhere -【A2019】変数](https://licensecounter.jp/engineer-voice/blog/articles/20200226_AutomationAnywhere-A2019-Variable.html) - C&S Engineer Vioce

# 日時型変数で初期値を与えない時の初期値はどうなる?
日時型の変数は、変数の作成画面で**タイプ=日時**を指定することで作成することが可能です。名前は適切なものを指定してください。デフォルト値は**オプション**となっています。特定の日時を指定してもいいのですが、空欄でもOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/148839bf-fb38-9a80-b15f-6435c7a90373.png)

デフォルト値が空欄の時のふるまいは、実は製品ドキュメントには記載がないのですが、調べてみると**「Botが開始された時点での日時」**(つまり変数が初期化されたときの日時) を返すようです。(最初にメッセージボックスで長時間停止して、OKを押すと次に進んで日時型変数を参照、文字列に変換して表示するBotを作ってみることでわかります)


### システム変数と同じ名前のユーザー定義変数も作れる
上記の例でもお分かりの通り、「Date」という名前をつけてもエラーが出ません。(既に同じ名前が存在するときは、「この名前はすでに存在します」というエラーが出ます。また大文字小文字は区別されません。) システム変数 Dateは厳密に言うと`$System:Date$`という表現になっており、ユーザー定義変数の`$Date$`とは書式が異なるからだと思われます。

# システム変数 Date
変数のパレットを見ると、日時関連では以下のようなシステム変数があらかじめ定義されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/6c2af8a3-1a45-2894-9616-c1cdf119a11e.png)

これらの変数の値も製品ドキュメント「[システム変数](https://docs.automationanywhere.com/bundle/enterprise-v2019/page/enterprise-cloud/topics/aae-client/bot-creator/using-variables/cloud-system-related-variables.html?_LANG=jpjp)」には、何の値が返るのか明確には書いていないのですが、システムの現在日時を返します。

|変数名|表記|型|説明|
|:--|:--|:--|:--|
|Date|`$System:Date$`|日時|システムの現在日時を返します。|
|Day|`$System:Day$`|数字|システムの現在日時の「日」を数字で返します。|
|Hour|`$System:Hour$`|数字|システムの現在日時の「時間」を数字で返します。|
|Millisecond|`$System:Millisecond$`|数字|システムの現在日時の「ミリ秒」を数字で返します。|
|Minute|`$System:Minute$`|数字|システムの現在日時の「分」を数字で返します。|
|Month|`$System:Month$`|数字|システムの現在日時の「月」を数字で返します。|
|Second|`$System:Second$`|数字|システムの現在日時の「秒」を数字で返します。|
|Year|`$System:Year$`|数字|システムの現在日時の「年」を数字で返します。|



# 型キャストが存在しない⇒すべてアクションパッケージを使ってフォーマット

A2019の変数は「[型キャスト](https://docs.automationanywhere.com/bundle/enterprise-v2019/page/enterprise-cloud/topics/aae-client/bot-creator/using-variables/type-casting.html)」ができるようになっているのですが、実は日時型は型キャストが使えない変数型です。(型キャストの全体像は[こちら](https://qiita.com/RPAbot/items/c6b23a8b84ae30aef0ff)) 日時は文字列に変換する際はフォーマットがかなり細かく存在するために型キャストのレベルでは対応できないのが原因なのだと想像されます。標準では「日時 (Datetime)」パッケージが使えるので、これを使ってさまざまな型に変換したり演算を行ったりします。

### 日時パッケージ (Datetime)
以下のようなアクションがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/f19894ab-43f3-afe9-193e-bd594bf5b804.png)

それぞれ以下の用途に使われます。アクションによっては複数の用途に使われます。

**値の代入**

|アクション名|入力型|出力型|説明|
|:--|:--|:--|:--|
|代入 (Assign)|日時型|日時型|1つの日時型変数から別の日時型変数に値を代入。特定の日時を変数にだ代入しておきたい場合は、日時型ユーザー変数作成時に初期値として設定します。Botの途中で特定の日時を使いたい場合もあらかじめ初期値の入った変数を作成しておきます。|

**演算**

|アクション名|入力型|出力型|説明|
|:--|:--|:--|:--|
|追加 (Add)|日時型、数字型、および選択肢 (年月日時分秒ミリ秒)|日時型|入力で指定された日時型変数に選択肢の単位の数字 (例: 3分) を足した結果を日時型変数に格納します。|
|減算 (Subtract)|日時型、数字型、および選択肢 (年月日時分秒ミリ秒)|日時型|入力で指定された日時型変数に選択肢の単位の数字 (例: 3分) を引いた結果を日時型変数に格納します。|

**値の比較**

|アクション名|入力型|出力型|説明|
|:--|:--|:--|:--|
|指定日より前の日時 (Is before)|日時型1、日時型2|Boolean|日時型1<日時型2ならTrueそれ以外はFalseを返す。|
|指定日と同じ日時 (Is equal)|日時型1、日時型2|Boolean|2つの日時型変数の値が同じならTrueそれ以外はFalseを返す。|
|指定日より後の日時 (Is after)|日時型1、日時型2|Boolean|日時型1>日時型2ならTrueそれ以外はFalseを返す。|

**型変換**

|アクション名|入力型|出力型|説明|
|:--|:--|:--|:--|
|代入 (Assign)|文字列型、書式の選択肢|日時型|日時の文字列を日時型に変換する。(ただし日本で一般的に使われている書式はない)|
|文字列に変換 (To string)|日時型、書式の選択肢|文字列型|日時型を文字列型に変換する。(ただし日本で一般的に使われている書式はない)|

日時型の書式:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/3cf4c989-d086-4909-f007-05b64c349a30.png)


# 日本市場向けのパッケージ 「日時(日本)」を使う (Datetime (Japan))
標準の「日時」パッケージでは、日本でよくつかう日時の書式が使えないため、Bot Storeで公開されている日本市場向けのパッケージ [「日時(日本)」パッケージ](https://botstore.automationanywhere.com/jp/bot/a2019-datetime-japan/)をダウンロードして使いましょう。

このパッケージには以下のアクションが含まれています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/54bbdfb8-7d51-ce7f-129c-59ae9f9cf87b.png)

また、書式として和暦 (令和対応含む)や、日本でよく使われる西暦の書式が用意されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/5d26640d-9313-0c4e-26d3-47d57791bcad.png)


**型変換**

|アクション名|入力型|出力型|説明|
|:--|:--|:--|:--|
|日時に変換 (Convert To Date)|文字列型、選択肢|日時型|日時の文字列を日時型に変換する。|
|文字列に変換 (Convert To String)|日時型、選択肢|文字列型|日時型を文字列型に変換する。|
|シリアル値を日時に変換 (Excel Serial Number To Date)|文字列型|日時型|文字列に変換されたExcelのシリアル値を日時型に変換する。|

[「Excelの基本操作」パッケージで日付セルの値を取得する](https://qiita.com/RPAbot/items/71180788baee33db48c3)際に結果がシリアル値で返ります。ここで「シリアル値を日時に変換」アクションを使うと便利です。

**休日・祝日処理**

|アクション名|入力型|出力型|説明|
|:--|:--|:--|:--|
|休日・祝日前後の日付を取得 (Get Before/After Holiday)|日時型、祝休日の種類、前後|日時型|指定日が祝休日の場合はその前日または後日の日時を得る。|
|休日・祝日の名前を取得 (Get Holiday Name)|日時型|文字列型|指定日が祝休日の場合の名前を取得する。|
|休日・祝日判定 (Holiday Judgement)|日時型、祝休日の種類|Boolean|指定日が祝休日かどうかを判定する。|

2020/7/24を引数として「文字列に変換」「休日・祝日の名前を取得」を実行してみると、きちんと今年の特別な休日にも対応していることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/4a28c7af-4393-1df0-9961-f99d0e7254f4.png)
実行結果:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/3a862342-44b1-55a4-b490-6e138d573d70.png)

また、指定した日が稼働日かどうかの判定が可能です。
稼働日なら同じ日付が、稼働日でなければ次の稼働日が返るBotは以下のように簡単に作れます。連休や祝休日・土日も考慮できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/5068f3b6-9073-b4d9-c61b-96031f9bfa17.png)
実行結果:
平日を指定した場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/9cd08de7-bed5-b780-17ca-a4aa4ea0eae0.png)
連休初日を指定した場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/e8c1c470-b736-769f-afc3-ab1ed99cf74c.png)


### システム変数Dateと相性が悪いのでユーザー定義変数を使おう
ところで、この「日時 (日本)」パッケージですが、引数にシステム変数の`$System:Date$`を指定するとなぜか以下のようなエラーが出てしまいます。**「We cannot finish pre-processing the bot/エラーコード: processing.failure」**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/135b14ea-9cae-9ca2-b1ec-f410078bddd9.png)

A-Peopleなども[いろいろ調べている](https://apeople.automationanywhere.com/s/question/0D52t00000468KsCAI/we-cannot-finish-preprocessing-the-bot-this-error-is-showing-many-times-when-i-want-to-run-my-bot-my-bot-was-working-fine-earlier-but-i-dont-know-why-it-is-showing-this-error-message-please-give-me-some-solution?language=ja)と、これはどうも変数周りの不整合で発生するエラーのようです。(例: Any型変数を使っているときにも出る？)

この場合、システム変数を一度ユーザー定義変数に代入して、ユーザー定義変数を引数に指定することで解決しました。