6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Streamlitで日付やカレンダーを扱う

Last updated at Posted at 2023-08-31

Streamlitはデータサイエンティストやデータエンジニア向けのPythonライブラリです。HTMLやCSSの知識がなくてもシンプルな記述でWebアプリケーションを作成することができます。

標準コンポーネントで日付を入力する:date_input()

日付の入力で使えるシンプルなコンポーネントはdate_inputです。

streamlit_app.py
import datetime
import streamlit as st

d = st.date_input('誕生日を入力してください。', datetime.date(1998, 2, 16))
st.write('私の誕生日は:', d)

デフォルトだと日付の選択範囲が±10年に設定されているので、必要に応じてmin_valuemax_valueを設定します。

streamlit_app.py
min_date = datetime.date(1900, 1, 1)
max_date = datetime.date(2100, 12, 31)
d = st.date_input('誕生日を入力してください。', datetime.date(1998, 2, 16), min_value=min_date, max_value=max_date)

input1.png

なお、うるう年にも対応しています。

標準コンポーネントで日付を入力する:slider()

日付の入力で使えるもう一つのコンポーネントはsliderです。
valueに日付のタプルを渡してあげると日付範囲を入力させることができます。

streamlit_app.py
import datetime
import streamlit as st

min_date = datetime.date(1900, 1, 1)
max_date = datetime.date(2100, 12, 31)
result = st.slider('調査期間を指定してください。', value=(min_date, max_date), format='YYYY-MM-DD (ddd)', min_value=min_date, max_value=max_date)
st.write('開始日は:', result[0])
st.write('終了日は:', result[1])

input2.png

formatがカスタマイズ可能なので、例えばdddを指定してあげれば曜日を表示することができます。

3rd-Partyコンポーネント streamlit-calendar でカレンダーを表示する

カレンダーらしいカレンダーを表示するには、3rd-Partyコンポーネントであるstreamlit-calendarを使うことになりそう。
FullCalendarというオープンソースのJavaScriptライブラリを元にしているそうです。

streamlit-calendar:導入手順

3rd-Partyコンポーネントなので追加インストールが必要になります。

pip install streamlit-calendar

streamlit-calendar:最小の使い方

ほぼ設定なしでも一応動作して、空のカレンダーが表示されます。あまり意味はないですね。

streamlit_app.py
import streamlit as st
import streamlit_calendar as st_calendar

st_calendar.calendar()

st_calendar1.png

streamlit-calendar:イベントを表示する

イベント(予定)を表示するには、イベント一覧をdictの配列で定義して、eventsに渡す必要があります。
イベントの定義に使えるプロパティはFullCalendarのドキュメントを参照するしかなさそう。

streamlit_app.py
# イベントを定義
event1 = {
    'id': '1', # イベントを識別するためのID。重複不可
    'title': 'Data Cloud World Tour', # イベント名
    'start': '2023-09-08T09:00:00', # 時間帯も指定する
    'end': '2023-09-08T20:00:00', # 時間帯も指定する
}
event2 = {
    'id': '2',
    'title': '月〆',
    'start': '2023-08-31', # 日付のみ指定するとallDayがTrueになる。終日イベントとして表示される
}
event3 = {
    'id': '4',
    'editable': True, # ドラッグで開始日時や終了日時を変更できるようにする
    'groupId': 'Streamlit勉強会', # 同じgroupIdのイベントは同じ変更が適用される
    'title': 'Streamlit勉強会',
    'start': '2023-09-03T09:00:00',
    'end': '2023-09-03T11:00:00',
}
event4 = {
    'id': '4',
    'editable': True,
    'groupId': 'Streamlit勉強会',
    'title': 'Streamlit勉強会',
    'start': '2023-09-10T09:00:00',
    'end': '2023-09-10T11:00:00',
}
# calendarにはイベント一覧を配列にして渡す
event_list = [event1, event2, event3, event4]

# options = {
#     'initialView': 'timeGridWeek',
# }

# イベントを表示するカレンダーを作成
cal = st_calendar.calendar(events=event_list)
st.write(cal)

event1.png

カレンダー上でイベント名の直前に表示される9aなどは開始時間を略記してくれているようです。
9:00開始なら9AM→9a、20:00開始なら8pm→8p、という感じですね。

streamlit-calendar:ビューを変更してみる

色々なビューが使えます。
FullCalendarのドキュメントのViewsにデモサイト付きで紹介されています。

initialViewというパラメータを設定したdictをoptionsに渡してあげれば初期状態で表示されるビューを設定することができます。

streamlit_app.py
# オプションを指定
options = {
    'initialView': 'dayGridMonth'
}

# イベントを表示するカレンダーを作成
cal = st_calendar.calendar(events=event_list, options=options)

いくつか触ってみました。

dayGridMonth:デフォルト。
view1.png

timeGridWeek:日々の予定を確認するのによさそう。
view2.png

listWeek:タスクがたくさんある場合はこれかな。
view3.png

multiMonthYear:デフォルトのものに近いですがスクロールすると他の月まで見ることができます。
view4.png

resourceTimeline:リソース(会議室や物品など)の管理をするならこれがよさそう。
view5.png

resourceTimeLineを使う場合はいくつか追加の情報を指定する必要があります。
optionsに渡す設定でリソースIDを定義しておき、それぞれのイベントにどのリソースIDと対応しているのかを定義します。

streamlit_app.py
# オプションを指定。会議室の予約状況をイメージしたもの
options = {
    'initialView': 'resourceTimeline',
    'resourceGroupField': '会議室',
    'resources': [
        {'id': 'A', '会議室': '新宿オフィス', 'title': '8人会議室A [飲食不可]'},
        {'id': 'B', '会議室': '新宿オフィス', 'title': '8人会議室B [飲食不可]'},
        {'id': 'C', '会議室': '新宿オフィス', 'title': '8人会議室C [飲食不可]'},
        {'id': 'D', '会議室': '新宿オフィス', 'title': '個室A [北エリア]'},
        {'id': 'E', '会議室': '新宿オフィス', 'title': '個室B [北エリア]'},
        {'id': 'F', '会議室': '新宿オフィス', 'title': '個室C [南エリア]'},
    ],
}

# 会議室と対応させたイベントを追加
event5 = {
    'id': '5',
    'title': '打合せ',
    'start': '2023-09-08T13:00:00',
    'end': '2023-09-08T14:30:00',
    'resourceId': 'A', # 会議室Aのidを指定
}

# イベントを表示するカレンダーを作成
st_calendar.calendar(events=[event5], options=options)

streamlit-calendar:メニューのカスタマイズ

Toolbarと呼ばれているメニューをカスタマイズすることができます。
例えば、カレンダーの上部に表示されている前の期間/次の期間のボタンなどですね。
これもFullCalendarのドキュメントを見ながらカスタマイズしていきます。

streamlit_app.py
# Streamlit標準のページ設定。色々表示すると狭いので幅を広げる
st.set_page_config(layout='wide')

# オプションを指定
options = {
    'initialView': 'dayGridMonth',
    # left/center/rightの3つの領域に表示するものはこの例の順番でなくてもいい
    'headerToolbar': {
        # ヘッダーの左側に表示するものを指定
        # 日付を移動するボタンが表示される。'today'を省略してもいい
        'left': 'today prev,next',
        # ヘッダーの中央に表示するものを指定
        # 'title'は表示されている日付などのこと
        'center': 'title',
        # ヘッダーの右側に表示するものを指定
        # ビュー名をカンマ区切りで列挙して指定するとビューを切り替えるためのボタンが表示される
        'right': 'dayGridMonth,timeGridWeek,listWeek',
    },
    'footerToolbar': {
        # ヘッダーと同じものをフッターにも配置できる。配置しない場合は省力する
        # 'center': 'title',
    },
    'titleFormat': {
        # 例えば月の表記を数字を指定できる
        # 年/月/日の順番にするのはlocaleで設定
        'year': 'numeric', 'month': '2-digit', 'day': '2-digit'
    },
    'buttonText': {
        # 各ボタンを日本語化してみる
        'today': '当日',
        'month': '月ごと',
        'week': '週ごと',
        'day': '日ごと',
        'list': 'リスト'
    },
    'locale': 'ja', # 日本語化する
    'firstDay': '1', # 週の最初を月曜日(1)にする。デフォルトは日曜日(0)
}

# イベントを表示するカレンダーを作成
st_calendar.calendar(events=event_list, options=options)

calendar_customize.png

設定項目を把握すれば、ある程度は好みの設定にできるんじゃないでしょうか。

streamlit-calendar:カレンダー上の操作の検出

追記予定。

streamlit-calendar:イベントをすべて取得する

streamlit_calendar.calendarの返り値からeventsSetプロパティを読むことでイベントを取得できます。カレンダー上で操作した後のイベントも取得できます。
ただし、日付やイベントをクリックしたときには他のプロパティに値が設定されてしまうので、Noneでないことをチェックする必要があります。

streamlit_app.py
# イベントを表示するカレンダーを作成
calendar_status = st_calendar.calendar(events=event_list, options=options)

# デバッグ表示
with st.expander('デバッグ表示'):
    # eventsSetはカレンダー上でイベントが表示されたときに代入されるプロパティ
    if 'eventsSet' in calendar_status and calendar_status['eventsSet'] is not None:
        # 最新のイベントはeventsSetに代入されている
        events = calendar_status['eventsSet']
        # まずDataFrameに変換する
        import pandas as pd
        df = pd.DataFrame.from_dict(events)
        # 表示する
        st.dataframe(df)
    else:
        st.write('イベントはありません')

listup1.png

streamlit-calendar:その他の設定

追記予定。

6
7
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?