初めに
我々AIdeaは5人中2人のメンバーが海外におり、9月からは5人中4人のメンバーがヨーロッパの各地に住む予定である。このチームで活動している中で最もネックなのが日程調整である。日本時間で日程を提案すると、ヨーロッパ時間に変換するのがめんどくさいかつあっているか不安になる。VICE VERSA
時差変換をする際のめんどくささを解消するためにslackのbotを導入したので記事にする。
最終的なアウトプット
12:30と書かれているメッセージにCET(Central European Time)というスタンプが押されると04:30と変換しスレッドでメッセージが送られるようなもの。日本時間への変換はJSTというスタンプを押してできる。
スレッド内でのメッセージたち(これはサマータイムCESTで行われている。)
本記事の内容
以下の手順で進めていった。
- AWSのLambdaを使って時差変換できるようにする
- SlackにAPIを通せるようにする
- チャンネルに追加してテスト
自分たちで実装したところはコードを書いているが、コピペでできた部分に関しては参考文献を載せている。載せているものはとってもいい参考文献でした。
1. AWSのLambdaを使って時差変換できるようにする
12:00や12:00のような:や:の両端に二桁の数字がある時にその数字に対して処理を行うようにする。
2:00などの一桁の数字が絡んでくる場合12:00も含まれてしまい、めんどくさいことになるので、今回は2:00と入力したいときは02:00と入力するようにメンバーに頼んでいる。
どのように時差変換を実装しているかというと、
cestという名前のreactionが押された場合にはJSTからCESTへの変換であると判断し、inputテキスト内の時間から7時間引かれるように関数を組んでいる。jstという名前のreactionが押された場合にはCET or CESTからJSTへの変換であると判断し7 or 8時間足すようにしている。
サマータイムが関連しているのでスタンプが押されたタイミングがサマータイムかどうかでcetかcestを判断するようにしている。
実際の日程がサマータイムかどうか判断するには何月何日などの情報が必要になる。しかし日程調整をする際は23日12:00~のような日にちだけに省略することがほとんどだと思うので、注意してとしか言えない。
以下のようなコードでlambdaを組み
テストとしては↓を使った。
{
"input_text": "これが10:00です。これが10:00です。これがaa:00です。",
"reaction": "CEST"
"event_ts": "1689763200"
}
以下コード
def lambda_handler(event, context):
input_text = event["input_text"]
if not input_text:
return {'statusCode': 400, 'body': 'Failed to get the message text'}
reaction = event["reaction"]
reaction_timestamp = event["event_ts"]
if reaction == "cest":
converted_text = convert_all_times(input_text, -7) # JSTからCESTへの変換(-7時間)
converted_text = "from JST to CEST \n" + converted_text
elif reaction == "cet":
converted_text = convert_all_times(input_text, -8) # JSTからCETへの変換(-8時間)
converted_text = "from JST to CET \n" + converted_text
elif reaction == "jst":
if is_summer_time(reaction_timestamp, 'Europe/Zurich'):
converted_text = convert_all_times(input_text, 7) # CESTからJSTへの変換(+7時間)
converted_text = "from CEST to JST \n" + converted_text
else:
converted_text = convert_all_times(input_text, 8) # CETからJSTへの変換(+8時間)
converted_text = "from CET to JST \n" + converted_text
else:
return {'statusCode': 400, 'body': 'Unsupported reaction'}
return {
'statusCode': 200,
'body': converted_text
}
def convert_all_times(text, time_difference):
# 時間のパターン(コロンで区切られた2桁の数字)を探す正規表現
time_pattern = re.compile(r'(\d{2}):(\d{2})')
time_pattern_2 = re.compile(r'(\d{2}):(\d{2})')
# 時間を探し、見つかったら時差変換を行う
def replace_time(match):
hour, minute = int(match.group(1)), int(match.group(2))
# 元の時間をdatetimeオブジェクトとして作成
original_time = datetime(year=1901, month=1, day=1, hour=hour, minute=minute)
# 時差を加算
new_time = original_time + timedelta(hours=time_difference)
if new_time.day == 31:
return str(new_time.strftime('%H:%M')) + "\t(The Day Before)"
elif new_time.day == 2:
return str(new_time.strftime('%H:%M')) + "\t(The Next Day)"
else:
return new_time.strftime('%H:%M')
# テキスト内の全ての時間表記を変換
text2 = time_pattern.sub(replace_time, text)
text3 = time_pattern_2.sub(replace_time, text2)
return text3
def is_summer_time(timestamp, timezone_str):
tz = pytz.timezone(timezone_str)
dt = datetime.fromtimestamp(float(timestamp), tz)
return dt.dst() != timedelta(0)
日付周辺の日時提案では日付が変わることがあるので時間の後に(翌日)や(前日)などをつけて注意を促すようにしている。
2. SlackにAPIを通せるようにする
この辺りを参考にするとできる。
Slack で API を使うために API gateway のエンドポイントを検証する必要がある。そこで"challenge"というインプットを与え、その中の値をそのまま返すだけの関数を作る必要がある。(参考: URL検証プロセス)
一度検証が終わると、その後は自由にエンドポイントを使うことができる。
3. アプリをチャンネルに追加してテスト
こちらのコードを大いに参考にさせていただき実装した。
コードはほとんどコピペで動くくらいいい記事なのでここからコピペしたらいいと思う。
入力出力の値の型等を確認してコピペすればすぐ動く。
僕自身もコピペで行って少し入力出力を調整したらエラーも起きずに実装できたので多分簡単にできるはず。逆にエラーでず実装できて不安になったくらいにはうまくいった。
終わりに
時差変換のところだけ自分たちでコードを書く必要があったが、そのほかは先人たちが残してくれた記事でうまく実装することができた。本記事の流れで実装を行うと自由自在に処理を実行する Slack bot が作れると思う。
参考文献
余談
最近知ったがSlackのバージョン履歴のコメントがなかなか面白い。こうゆうユーモアあるアップデートの詳細が書けるエンジニアになりたいなと思った。