AWS Lambdaで環境変数のTZは指定しないほうが良いかもしれない件

## 追記(2023/1/11)
TZが予約語ではなくなりましたので、
指定して問題ないです。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-envvars.html#:~:text=TZ%20%EF%BC%8D%20%E7%92%B0%E5%A2%83%E3%81%AE%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%BE%E3%83%BC%E3%83%B3%20(UTC)%E3%80%82%E5%AE%9F%E8%A1%8C%E7%92%B0%E5%A2%83%E3%81%AF%E3%80%81%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%82%AF%E3%83%AD%E3%83%83%E3%82%AF%E3%82%92%E5%90%8C%E6%9C%9F%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AB%20NTP%20%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%BE%E3%81%99%E3%80%82


## はじめに
Lambdaで現在日時を取得する際、
リージョン関係なくデフォルトでUTCとなっています。

そのため業務等では、扱いやすいようにJSTに変換して運用するかと思いますが、
その方法で2022年1月現在、よく見かけるのが2パターン存在します。

本記事はPython3.9を使用していますが、
他の言語に読み替えていただいても内容は問題ありません。

## 1.Lambdaの環境変数でタイムゾーンを設定する方法

まずは環境変数なしで取得してみます。

![スクリーンショット 2022-01-28 18.36.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392337/2f5a7920-6d0c-6973-6e14-63b00bc016e7.png)

```python
from datetime import datetime

def lambda_handler(event, context):

    current_at = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

    print(current_at)

```

実行結果

```
2022-01-28 11:21:22
```

この記事の執筆時が20時21分なので、
このようにUTCで取れます。

では次にLambdaの環境変数を設定してみます。
キーにTZ、値にAsia/Tokyoを設定します。

![スクリーンショット 2022-01-28 18.31.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392337/ba46242c-98e1-4faa-fe59-291c2da49e08.png)

実際に取得してみます。
コードはさっきと同じです。

```python
from datetime import datetime

def lambda_handler(event, context):

    current_at = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

    print(current_at)

```

実行結果

```
2022-01-28 20:21:59
```

環境変数の設定だけで、現在日時をJSTで取得できるようになりました。


## 2.プログラムから取得する際にJSTを指定する方法

環境変数には何も設定しません。

![スクリーンショット 2022-01-28 18.36.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392337/f4a1eb36-241e-3bfb-7c95-90f8c4aae6e7.png)

コード上でJSTを指定してから現在日時を取得します。

```python
from datetime import datetime, timedelta, timezone

def lambda_handler(event, context):

    JST = timezone(timedelta(hours=+9), 'JST')
    current_at = datetime.now(JST).strftime('%Y-%m-%d %H:%M:%S')

    print(current_at)

```

実行結果

```
2022-01-28 20:22:41
```

こちらも環境変数のタイムゾーンを変更した場合と同様に、
JSTで取得することが出来ました。

## 問題点
ここからが本題です。
環境変数の設定で、なぜJSTになるのか…？と疑問を抱き、
気になったので調べてみたところ、
TZがどうやらAWS Lambdaの予約語のようです。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-envvars.html#:~:text=%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E8%A8%AD%E5%AE%9A-,%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0,-%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3

その中に、

>予約済み環境変数

>TZ － 環境のタイムゾーン (UTC)。実行環境は、システムクロックを同期するために NTP を使用します。

という記述があります。

本当かどうか念のため確認してみると、

```python
import os

def lambda_handler(event, context):

    print(os.environ['TZ'])
```

実行結果

```
:UTC
```

確かに設定されています。
さらに、

>定義されたランタイム環境変数

>Lambda ランタイムは、初期化中にいくつかの環境変数を設定します。ほとんどの環境変数は、関数またはランタイムに関する情報を提供します。これらの環境変数のキーは予約済みであるため、関数設定では設定できません。

環境変数のキーは予約済みであるため、関数設定では設定できませんと書いてありますが、
実際には設定できてしまいます。

## 結論

仕様なのかどうかは微妙なところですが、
ドキュメントで予約語と明記され、設定もできないとなっているものを設定して使うのは、
基本的によろしくないと思います。

いつ修正されるかも不明ですので、素直にプログラムから取得する際にJSTを指定したほうが良さそうです。

## 参考

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-envvars.html#:~:text=%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E8%A8%AD%E5%AE%9A-,%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0,-%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3


https://qiita.com/mattsu6/items/5511c5631e7a54550f7f

## 追記(2022/1/31)
@yatsbashy さんより教えて頂きました。
数年前にサーバーワークスさんがAWSサポートに確認されたようです。

>AWS のサポートにも確認してみましたが「将来にわたって TZ の上書きが可能であるという保証はできないため環境変数の TZ は使用しないようにお願いします」とのことでした。

https://blog.serverworks.co.jp/tech/2019/10/30/lambda-timezone-2/