11
1

More than 3 years have passed since last update.

time-windowを使ってみた

Last updated at Posted at 2020-03-02

はじめに

みなさま,はじめまして.
株式会社オプティマインドにて,GISエンジニアをしている@tkmbnです.
Qiitaへの初投稿です.

概要

時間枠(日時の組み合わせ,開始日時〜終了日時)のあれやこれをしてくれるライブラリtime-windowの使い方を解説します.
Screen Shot 2020-03-02 at 11.29.07.png

複雑な時間枠をスッキリまとめてくれたりします!←このライブラリを使って一番やりたいこと.

なぜ書いたか

Screen Shot 2020-03-01 at 23.09.29.png
DBから時間枠つきのデータを取得する際に,時間枠に重なりがあればまとめてほしいという依頼がありました.
どうにかこうにか自力で実装しようとしたんですが,混乱しだして,「なんか良いツールないかなぁ...」と探していたところ上記のライブラリに出会いました.
readme以外にもいろいろと便利そうな機能もあったので,自分への覚書も含め,記事にしました.

まるまる解説!というわけではないので,あしからず...

本題

インストール方法

pip install time-window

具体的な使い方

最初の方は,readmeの日本語訳的なものと思ってください笑

TimeWindow オブジェクト

作り方

2020年03月01日12:00:00 から 2020年03月01日15:00:00 のTimeWindowを作りたいときは...

from datetime import datetime
from time_window import TimeWindow
t1 = datetime(2020, 3, 1, 12, 00, 00)
t2 = datetime(2020, 3, 1, 15, 00, 00)
tw1 = TimewWindow(t1, t2)
tw1

-> TimeWindow(datetime.datetime(2020, 3, 1, 12, 0), datetime.datetime(2020, 3, 1, 15, 0))

このとき,時間枠は,[t1, t2) になることに注意!

また,timedeltaでも作成可能です.

from datetime import datetime, timedelta
from time_window import TimeWindow
t1 = datetime(2020, 3, 1, 12, 00, 00)
delta = timedelta(hours=3)
tw2 = TimeWindow.from_timedelta(t1, delta)
tw2

-> TimeWindow(datetime.datetime(2020, 3, 1, 12, 0), datetime.datetime(2020, 3, 1, 15, 0))

同じ結果が得られました.

delta, middle

時間枠の差分を知りたいときは,

tw1.delta

-> datetime.timedelta(0, 10800)

時間枠の中間の時点を知りたいときは,

tw1.middle

-> datetime.datetime(2020, 3, 1, 13, 30)
overlaps
tw = TimeWindow(datetime(2020, 3, 1, 12, 0), datetime(2020, 3, 1, 15, 0))
tw2 = TimeWindow(datetime(2020, 3, 1, 13, 0), datetime(2020, 3, 1, 18, 0))
tw.overlaps(tw2)

-> True

重なっていれば,True, そうでなければ,False.

contains(readme未掲載)
tw = TimeWindow(datetime(2020, 3, 1, 12, 0), datetime(2020, 3, 1, 15, 0))
tw4 = TimeWindow(datetime(2020, 3, 1, 13, 0), datetime(2020, 3, 1, 14, 0))
tw.contains(tw4)

-> True

含まれていれば,True, そうでなければ,False.

contiguous
tw = TimeWindow(datetime(2020, 3, 1, 12, 0), datetime(2020, 3, 1, 15, 0))
tw3 = TimeWindow(datetime(2020, 3, 1, 15, 0), datetime(2020, 3, 1, 18, 0))
tw.contiguous(tw3)

-> [TimeWindow(datetime.datetime(2020, 3, 1, 12, 0), datetime.datetime(2020, 3, 1, 15, 0)), 
TimeWindow(datetime.datetime(2020, 3, 1, 15, 0), datetime.datetime(2020, 3, 1, 18, 0))]

接している場合は,TimeWindowのリストが,接していない場合は,Falseが返ってくる.

set型みたいな事もできる
積集合
tw = TimeWindow(datetime(2020, 3, 1, 12, 0), datetime(2020, 3, 1, 15, 0))
tw2 = TimeWindow(datetime(2020, 3, 1, 13, 0), datetime(2020, 3, 1, 18, 0))
tw.intersection(tw2)

-> TimeWindow(datetime.datetime(2020, 3, 1, 13, 0), datetime.datetime(2020, 3, 1, 15, 0))
和集合
tw.union(tw2)

-> TimeWindow(datetime.datetime(2020, 3, 1, 12, 0), datetime.datetime(2020, 3, 1, 18, 0))

TimeWindowsCollection オブジェクト (readme未掲載)

作り方
from datetime import datetime, timedelta
from time_window import TimeWindow, TimeWindowsCollection
tw = TimeWindow(datetime(2020, 3, 1, 13, 0), datetime(2020, 3, 1, 18, 0))
tw2 = TimeWindow(datetime(2020, 3, 1, 12, 0), datetime(2020, 3, 1, 15, 0))
twc = TimeWindowsCollection([tw, tw2])
twc

-> [TimeWindow(datetime.datetime(2020, 3, 1, 13, 0), datetime.datetime(2020, 3, 1, 18, 0)), 
TimeWindow(datetime.datetime(2020, 3, 1, 12, 0), datetime.datetime(2020, 3, 1, 15, 0))]

##開始時刻で並べ替えたい!
twc.time_windows_sorted_by_since

-> [TimeWindow(datetime.datetime(2020, 3, 1, 12, 0), datetime.datetime(2020, 3, 1, 15, 0)), 
TimeWindow(datetime.datetime(2020, 3, 1, 13, 0), datetime.datetime(2020, 3, 1, 18, 0))]
複数の時間枠をまとめたい

これで自分のやりたいことは,完璧にできました.

tw = TimeWindow(datetime(2020, 3, 1, 13, 0), datetime(2020, 3, 1, 18, 0))
tw2 = TimeWindow(datetime(2020, 3, 1, 12, 0), datetime(2020, 3, 1, 15, 0))
tw3 = TimeWindow(datetime(2020, 3, 1, 19, 0), datetime(2020, 3, 1, 21, 0))
twc = TimeWindowsCollection([tw, tw2, tw3])
twc

-> [TimeWindow(datetime.datetime(2020, 3, 1, 13, 0), datetime.datetime(2020, 3, 1, 18, 0)), 
TimeWindow(datetime.datetime(2020, 3, 1, 12, 0), datetime.datetime(2020, 3, 1, 15, 0)), 
TimeWindow(datetime.datetime(2020, 3, 1, 19, 0), datetime.datetime(2020, 3, 1, 21, 0))]


twc.compressed()

-> [TimeWindow(datetime.datetime(2020, 3, 1, 12, 0), datetime.datetime(2020, 3, 1, 18, 0)), 
TimeWindow(datetime.datetime(2020, 3, 1, 19, 0), datetime.datetime(2020, 3, 1, 21, 0))]

重なり合っている時間枠はまとまり,重なっていないものは別の時間枠となっています.

Screen Shot 2020-03-01 at 23.41.07.png

しかし,落とし穴がありました.
普通にインデックス指定して,TimeWindowを取り出そうとしたところ,

twc.compressed()[0]   

-> Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'TimeWindowsCollection' object does not support indexing

返ってくる形見ると,普通のリストなんですが,どうやら違うみたいです...
TimeWindowsCollectionオブジェクトをTimeWindowのリストに戻してやる必要があるので,

twc.compressed().time_windows

-> [TimeWindow(datetime.datetime(2020, 3, 1, 12, 0), datetime.datetime(2020, 3, 1, 18, 0)), 
TimeWindow(datetime.datetime(2020, 3, 1, 19, 0), datetime.datetime(2020, 3, 1, 21, 0))]

twc.compressed().time_windows[0]  
TimeWindow(datetime.datetime(2020, 3, 1, 12, 0), datetime.datetime(2020, 3, 1, 18, 0))

無事取り出せることができました!!

参考文献

最後に

最後まで読んでいただきありがとうございます!
なにか疑問点,間違っている点,等ございましたら,コメントお願いいたします.

11
1
0

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
11
1