【Python】outlookカレンダーの予定から、予定時間の天気を返す

# 製作意図
自分の予定に合わせた天気予報が欲しかったため。

天気予報に関するプロダクトは世にあふれているが、個人の予定に合わせて柔軟に天気予報を出すプロダクトは見かけない。

outlookカレンダーの予定をもとに、予定の場所で天気を判定することができれば、要件を満たせそう。

# 利用環境等
### 言語・ライブラリ
- pyhon3.11.1
    - バージョンの指定は必要ない
- PyWin32
    - pythonでwindows32APIを利用するためのライブラリ
    - outlookデスクトップアプリから予定を取得するために必要
- Requests
    - HTTP通信ライブラリ
    - 天気APIなどを利用するために必要
- urllib
    - URLを扱うためのライブラリ
    - 今回はurlに日本語をパーセントエンコーディングするために必要
    - 標準ライブラリ
- datetime
    - 時間を扱うライブラリ
    - 当日の予定を取得するために利用
    - 標準ライブラリ
    
### その他
 - outlookデスクトップアプリケーション
:::note warn
注意
デスクトップアプリでoutlookにログインできる環境であることが前提
webアプリは非対応
:::
 - [Open-Meteo](https://open-meteo.com/)
     - 天気API
     - 登録不要
- 国土地理院API
    - 場所から緯度経度を取得することが可能
    - 登録不要

# 開発
### ライブラリインストール
PyWin32とrequestsライブラリをインストール

```コマンドプロンプト:コマンドプロンプト
$ pip install pywin32
$ pip install requests
```
## Open-Meteoから天気コードを取得し、天気を判定する

```Python:weather.py
import requests

### Meteo Weather APIから今日の天気コードを取得 
def get_weather(lat, lng):
    url = "https://api.open-meteo.com/v1/forecast?latitude=" + str(lat) + "&longitude=" + str(lng) + "&hourly=weathercode&forecast_days=1&timezone=Asia%2FTokyo"
    weather_today = requests.get(url).json()

    return(weather_today)

### 特定時間の天気コードを取得
def weather_jedge(lat, lng, hour):
    
    date = get_weather(lat, lng)
    weather_code = date["hourly"]['weathercode'][hour]
    if weather_code > 60:
        return("雨が降るでしょう")
    else:
        return("晴れるでしょう")

```

**説明文追加予定**


### 天気コード取得用の緯度経度を取得する
```Python:geocoder.py
import urllib
import requests

# 指定地域から緯度経度を取得
def get_giocode(address):
    # APIから情報の取得
    query = urllib.parse.quote(address)
    url = "https://msearch.gsi.go.jp/address-search/AddressSearch?q="+query
    response = requests.get(url)

    #緯度経度を取得（天気API利用のために緯度経度は小数点第4位まで）
    latlng = response.json()[0]["geometry"]["coordinates"]
    lng = round(latlng[0], 4)
    lat = round(latlng[1], 4)
    return lat, lng

```
**説明文追加予定**

## outlookから予定を取得&予定ごとの天気をprintする
```Python:main.py
import win32com.client
import datetime
import giocoder
import weather
# outlookカレンダーのデスクトップアプリから使用者のカレンダー情報を取得
calendar = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI").GetDefaultFolder(9)

#カレンダーから取得した予定
items = calendar.Items

# 指定した期間内の予定を入れるリスト
select_items = []

# 予定を抜き出したい期間を指定
date = datetime.date.today()

# 上記の
#期間の予定リストを作成
for item in items:
    if date == item.start.date():
        select_items.append(item)

# 抜き出した予定の詳細を表示
for select_item in select_items:

    #変数の定義
    address = []
    time = []
    address = str(select_item.location)
    time = int(str(select_item.start)[10:13])

    if address:
        # #緯度経度の取得
        lat= giocoder.get_giocode(address)[0]
        lng = giocoder.get_giocode(address)[1]

        #天気の取得
        weather_output = weather.weather_jedge(lat, lng, time)
        print("-----")
        print(str(time) + "時:"+ select_item.subject+"の時は"+weather_output)
        print("場所：", select_item.location)
        print("-----")
        
    else:
        print("-----")
        print(str(time) + "時:"+ select_item.subject)
        print("場所：", select_item.location)
        print("-----")
```

**説明文追加予定**

# 実行結果
``` コマンドプロンプト:コマンドプロンプト
$ python main.py
# 以下実行結果


-----
13時:友達とランチの時は晴れるでしょう
場所：神奈川県横浜市
-----
-----
19時:図書館の時は雨でしょう
場所：東京都
-----
```

# 課題
- 実行結果の予定の表示順序が予定登録順
    - 予定の時間順じゃないのは地味に不便