[JSONata] AWS Step Functionsの機能で日付文字列を加工してみる
こんにちは。サービス開発室の武田です。
AWS Step FunctionsのJSONata便利ですよね。使ってみると結構感動することが多いので、少しでも皆さんにお届けできればと思っています。
今回のテーマは「日付データの加工」です。
たとえば、ステートマシンのコンテキストには実行開始日時が記録されています。JSONPathであれば$$.Execution.StartTime
でアクセスでき、具体的には2025-05-28T09:00:00.000Z
のような文字列データを持っています。
ではこのデータから2025/05/28
という文字列を作るにはどう書きますか?Lambda関数などは使わずStep Functionsの機能のみで実現することとします。
JSONPath形式で書くなら
実際のやり方はいくつかありますが、たとえば次のようなPassステートを定義すれば目的の文字列を生成できます。
{
"Type": "Pass",
"Next": "Next Pass",
"Parameters": {
"date.$": "States.Format('{}/{}/{}', States.ArrayGetItem(States.StringSplit($$.Execution.StartTime, '-T'), 0), States.ArrayGetItem(States.StringSplit($$.Execution.StartTime, '-T'), 1), States.ArrayGetItem(States.StringSplit($$.Execution.StartTime, '-T'), 2))"
}
}
わかりにくいので式の部分だけ取り出します。
States.Format('{}/{}/{}',
States.ArrayGetItem(States.StringSplit($$.Execution.StartTime, '-T'), 0),
States.ArrayGetItem(States.StringSplit($$.Execution.StartTime, '-T'), 1),
States.ArrayGetItem(States.StringSplit($$.Execution.StartTime, '-T'), 2)
)
新しい文字列を作りたいので、全体のフォーマットはStates.Format
を使用します。次の年月日のデータをそれぞれのプレースホルダーに指定できればOKです。肝心の年月日ですが、States.StringSplit($$.Execution.StartTime, '-T')
という式が出てきていますが、これは次のような結果を返します。
["2025", "05", "28", "09:00:00.000Z"]
そのため、States.ArrayGetItem
を使用して必要な部分を取り出しているわけです。
結果としてStates.Format('{}/{}/{}', '2025', '05', '28')
という形になり、目的の2025/05/28
が取得できました。
JSONata形式で書くなら
続いて同じことをJSONataでもやってみましょう。どう書けばいいでしょうか?
一例としては次のような書き方ができます。
{
"Type": "Pass",
"Next": "Next Pass",
"QueryLanguage": "JSONata",
"Output": "{% {\"date\": $split($states.context.Execution.StartTime, \"T\")[0] ~> $replace(\"-\", \"/\")} %}"
}
こちらも式の部分だけ抜き出してみます。
$split($states.context.Execution.StartTime, "T")[0] ~> $replace("-", "/")
だいぶシンプルになりましたね。$split($states.context.Execution.StartTime, "T")
は文字列の分割をしています。先ほどとは違い単純にT
だけで分割しているため、次の結果になります。
["2025-05-28", "09:00:00.000Z"]
必要なのは1個目だけなので[0]
を指定しています。次に見慣れない~>
ですが、Linuxコマンドなどでいうところのパイプ(|
)機能です(JSONataでは Chain と呼ぶようです)。関数の実行結果を、次の関数の 第1引数 に渡せます。
つまり、今回の例では次の書き方と同じです。
$replace($split($states.context.Execution.StartTime, "T")[0], "-", "/")
個人的には関数のネストよりChainの方が好みですので、こちらの書き方を推していきたいです。さて、後続の処理は$replace("-", "/")
で、文字どおり-
を/
に置換します。結果として2025/05/28
が取得できます。
ちなみにJSONataでは正規表現も使えるため、かなり強力な文字列操作が可能です。夢が広がりますね。
また上記は「文字列操作」に主眼を置いた方法でしたが、日時データとしての扱いも知っておくと便利なので紹介しておきます。
JSONataはいわゆるDateTime
型というものはサポートしていません。代わりに文字列表現とミリ秒(エポックタイム)との相互変換がサポートされています。そこで次のように書いても、同様の結果が得られます(タイムゾーンの操作などが必要であればこちらの方が好ましいでしょう)。
$toMillis($states.context.Execution.StartTime) ~> $fromMillis("[Y0001]/[M01]/[D01]")
まとめ
JSONPath形式では面倒だった処理を、JSONataでは簡単に実現できました。これまで複数のステートを組み合わせたりLambda関数を挟んでいたような変換処理を記述できる、JSONataは非常に強力なツールです。
ぜひ使いこなしていきましょう!