Python 日付・時刻ライブラリー 逆引きリファレンス

Pythonで日時を扱うライブラリーについて、逆引き風にまとめてみました。

この記事の内容は、正確を期するように注意して記述していますが、公式の情報ではありません。
正確な情報をお求めなら公式リファレンス（参考資料#1）を参照してください。


## 想定する読者

ほとんどが標準モジュールについてのことですので、Python初心者の方か、日時ライブラリーのことをあまりご存じない方向けです。
（私自身まだPython歴が浅いので。）


## 前提

Python2はv2.7.10、Python3はv3.5.1で確認しています。
（Anaconda 4.0.0 Windows 64bit版を使用。）

Python2とPython3を特に個別に扱っていないものは、共通で使えるものです。
その場合、`print`についてはカッコつき表記で統一し、実行結果はPython3のものを採用しています。
サンプルコードは、主に対話環境での結果を掲載しています。

拡張モジュールのバージョンは以下の通りです。

```
dateutil  2.5.1
pytz      2016.2
```


## APIの基本情報

日時に関する標準モジュールとそこに含まれる型について簡単に記載します。
詳しくは、公式リファレンス（参考資料#1）を参照してください。

本文中では、特に説明が無いものについては`from datetime import *`を施したものとします。


### 標準モジュール

| モジュール           | 説明                                                                   |
|----------------------|------------------------------------------------------------------------|
| `datetime`モジュール | 日時に関する標準の型と操作を提供します。                               |
| `time`モジュール     | 低レベル（システムレベル）の時間に関するユーティリティーが含まれます。 |
| `calendar`モジュール | 主に、テキストカレンダーに関するユーティリティーが含まれます。         |


### 拡張モジュール

| モジュール           | 説明                                                             |
|----------------------|------------------------------------------------------------------|
| `dateutil`           | 標準モジュールでは不足している日時処理を補ってくれるモジュール。 |
| `pytz`               | タイムゾーンを扱うモジュール。詳細は後述。                       |


### 型

| 型                   | 説明                                                             |
|----------------------|------------------------------------------------------------------|
| `datetime.date`      | 日付オブジェクト。                                               |
| `datetime.datetime`  | 日時オブジェクト。                                               |
| `datetime.time`      | 時刻オブジェクト。`time`モジュールと混同しないように。           |
| `datetime.timedelta` | 2つの日時の差を表すオブジェクト。                                |
| `datetime.tzinfo`    | タイムゾーン情報の抽象基底クラス。                               |
| `datetime.timezone`  | タイムゾーン情報の固定オフセットによる実装。                     |
| `time.struct_time`   | UNIXの`struct tm`（構造体）に相当する名前付きタプル。            |

`datetime`モジュールの型階層は以下の通り。
※注：Python3.2未満には`timezone`型は存在しません。

```
object
    timedelta
    tzinfo
        timezone
    time
    date
        datetime
```

以降、本文中では型のモジュール名を省略します。


### naiveとaware（タイムゾーン有無）

同じ`datetime`オブジェクトでも、タイムゾーンが付いているものと付いていないものがあります。
Pythonでは、タイムゾーンが付いている`datetime`を**aware**（な日時）、付いていない`datetime`を**naive**（な日時）と呼びます。

`date`オブジェクトは常にnaive、`time`オブジェクトはどちらにもなり得ます。

タイムゾーン(`tzinfo`)のインスタンスとして、Python3.2で追加された`timezone`オブジェクトが利用できます。
それ以前は`tzinfo`の実装は標準モジュールに存在しませんでした。
そのような場合は、`pytz`モジュールを使います。
`tzinfo`の実装には、`dateutil`モジュールのサブモジュール`tz`もあります。

また、任意のオフセット値（JSTなら+09:00）でタイムゾーンを示す場合には`timezone`で事足りますが、
タイムゾーンの処理を厳密に扱う必要がある場合は、`pytz`モジュールの使用が推奨されています。
`pytz`モジュールは、IANAタイムゾーンデータベース（オルソンデータベース）を参照します。
詳しくは、公式リファレンス（参考資料#1）を参照して下さい。

IANAタイムゾーンデータベースについては、以下の記事を参照して下さい。

tz database - Wikipedia
[https://ja.wikipedia.org/wiki/Tz_database](https://ja.wikipedia.org/wiki/Tz_database)

naiveとawareの変換方法については、本編中に説明があります。


## 任意の日時のオブジェクトを生成する

コンストラクターにより生成できます。`time`オブジェクトについては省略します。

```pycon
>>> from datetime import datetime, date, timezone, timedelta
>>>
>>> datetime(2016, 7)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Required argument 'day' (pos 3) not found
>>> datetime(2016, 7, 5)
datetime.datetime(2016, 7, 5, 0, 0)
>>> datetime(2016, 7, 5, 13)
datetime.datetime(2016, 7, 5, 13, 0)
>>> datetime(2016, 7, 5, 13, 45)
datetime.datetime(2016, 7, 5, 13, 45)
>>> datetime(2016, 7, 5, 13, 45, 27)
datetime.datetime(2016, 7, 5, 13, 45, 27)
>>> datetime(2016, 7, 5, 13, 45, 27, 123456)
datetime.datetime(2016, 7, 5, 13, 45, 27, 123456)
>>> datetime(2016, 7, 5, 13, 45, 27, 123456, timezone(timedelta(hours=+9)))
datetime.datetime(2016, 7, 5, 13, 45, 27, 123456, tzinfo=datetime.timezone(datetime.timedelta(0, 32400)))
>>>
>>> date(2016, 7)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Required argument 'day' (pos 3) not found
>>> date(2016, 7, 5)
datetime.date(2016, 7, 5)
>>> date(2016, 7, 5, 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: function takes at most 3 arguments (4 given)
```


`datetime`の7番目の要素は、マイクロ秒（1/1,000,000秒）です。

タイムスタンプから生成することもできます。
現在日時のタイムスタンプについては、次項を参照してください。

```pycon
>>> datetime.fromtimestamp(12345678901.234567)
datetime.datetime(2361, 3, 22, 4, 15, 1, 234568)
>>> date.fromtimestamp(12345678901.234567)
datetime.date(2361, 3, 22)
```

ここで言うタイムスタンプ(float)とは、**UNIX時間**またはエポック秒と呼ばれる値です。

UNIX時間 - Wikipedia
[https://ja.wikipedia.org/wiki/UNIX%E6%99%82%E9%96%93](https://ja.wikipedia.org/wiki/UNIX%E6%99%82%E9%96%93)

UNIX時間は整数値ですが、Python上では`float`で表されます。
小数点以下の値は、Python上ではマイクロ秒として扱われますが、例で分かる通り、`float`の小数部で表されるので、精度は落ちます。


`datetime.date()`メソッドで、日付部分だけを`date`として取り出すことができます。

```pycon
>>> from datetime import datetime, date
>>>
>>> dt = datetime.now()
>>> dt
datetime.datetime(2016, 7, 14, 14, 24, 46, 157000)
>>> dt.date()
datetime.date(2016, 7, 14)
```


## 現在日時のオブジェクトを生成する

`datetime.now()`は、現在日時を示す`datetime`オブジェクトを返します。
`date.today()`は、当日を示す`date`オブジェクトを返します。

```pycon
>>> from datetime import datetime, date
>>>
>>> datetime.now()
datetime.datetime(2016, 7, 14, 14, 14, 2, 900000)
>>> date.today()
datetime.date(2016, 7, 14)
```

`time`モジュールの`time()`関数で現在日時のタイムスタンプを取得できます。
タイムスタンプについては、前項を参照してください。

```pycon
>>> import time
>>>
>>> time.time()
1468473337.565 # 2016-07-14 14:15:37.565000
```

他にも、`time`モジュールに`struct_time`を返す（古風な）関数がいくつかありますが、今回は扱いません。
`time.gmtime()`関数あたりの説明を読んでみて下さい。


## 文字列から日時・日付へ変換

`datetime`モジュールでは、`datetime.strptime()`関数を使います。
ただし、以下の結果を見てもらうと分かる通り、この関数は融通が利きません。

```pycon
>>> from datetime import datetime, timezone, timedelta
>>> datetime.strptime("2016/07/05 13:45:06", "%Y/%m/%d %H:%M:%S")
datetime.datetime(2016, 7, 5, 13, 45, 6)
>>> datetime.strptime("2016/07/05 13:45", "%Y/%m/%d %H:%M:%S")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "...\lib\_strptime.py", line 500, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "...\lib\_strptime.py", line 337, in _strptime
    (data_string, format))
ValueError: time data '2016/07/05 13:45' does not match format '%Y/%m/%d %H:%M:%S'
```
（※トレース内容は一部加工しています。）


`dateutil`モジュールのサブモジュール`parser`の`parse()`関数が強力なので、そちらを使いましょう。

```pycon
>>> from dateutil.parser import parse
>>>
>>> parse("Tue Aug 23 17:00:35 JST 2016")
datetime.datetime(2016, 8, 23, 17, 0, 35)
>>> parse("2016-07-03T11:22:33Z")
datetime.datetime(2016, 7, 3, 11, 22, 33, tzinfo=tzutc())
>>> parse("2016/07/03 04:05:06")
datetime.datetime(2016, 7, 3, 4, 5, 6)
>>> parse("2016/07/03")
datetime.datetime(2016, 7, 3, 0, 0)
```

なお、Python2の場合、下記のようなエラーが出ました。

```
.../dateutil/parser.py:598: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
  elif res.tzname and res.tzname in time.tzname:
```

この↓記事に書いてあるissueに関係ありそうなんですが、`dateutil`のバージョンが2.5.1なのに発生しているんですよね。
同類だけど別の（fixされていない）バグなのでしょうか。

twitter - python dateutil unicode warning - Stack Overflow
[http://stackoverflow.com/questions/21296475/python-dateutil-unicode-warning](http://stackoverflow.com/questions/21296475/python-dateutil-unicode-warning)


## 日時・日付から文字列へ変換

ISO8601形式に変換する場合は、`date.isoformat()`メソッドを使います。
`datetime`オブジェクトや`date`オブジェクトを単純に文字列に変換する場合は、これが使われます。

任意のフォーマットで文字列に変換したい場合は、`strftime()`メソッドを使用します。

```pycon
>>> from datetime import datetime, timezone, timedelta
>>>
>>> dt1 = datetime(2016, 7, 5, 13, 45) # naive
>>> dt2 = datetime(2016, 7, 5, 13, 45, tzinfo=timezone(timedelta(hours=+9))) # aware
>>> d = dt1.date()
>>> dt1, dt2, d
(datetime.datetime(2016, 7, 5, 13, 45), datetime.datetime(2016, 7, 5, 13, 45, tzinfo=datetime.timezone(datetime.timedelta(0, 32400))), datetime.date(2016, 7, 5))
>>>
>>> dt1.isoformat()
'2016-07-05T13:45:00'
>>> str(dt1)
'2016-07-05 13:45:00'
>>>
>>> dt2.isoformat()
'2016-07-05T13:45:00+09:00'
>>> str(dt2)
'2016-07-05 13:45:00+09:00'
>>>
>>> d.isoformat()
'2016-07-05'
>>> str(d)
'2016-07-05'
>>>
>>> dt1.strftime("%Y/%m/%d %H:%M:%S")
'2016/07/05 13:45:00'
>>> dt1.strftime("%Y/%m/%d %H:%M:%S %Z %z")
'2016/07/05 13:45:00  '
>>> dt2.strftime("%Y/%m/%d %H:%M:%S %Z %z")
'2016/07/05 13:45:00 UTC+09:00 +0900'
```

フォーマットの書式については、下記リファレンスを参照してください。

8.1.8. strftime() と strptime() の振る舞い - 8.1. datetime — 基本的な日付型および時間型 — Python 3.5.1 ドキュメント
[http://docs.python.jp/3.5/library/datetime.html#strftime-strptime-behavior](http://docs.python.jp/3.5/library/datetime.html#strftime-strptime-behavior)


## 2つの日時を比較する

比較演算子`==`,`!=`,`<`,`<=`,`>`,`>=`による比較が可能です。

`datetime`と`date`では比較できません。
（`TypeError: can't compare datetime.datetime to datetime.date`）
また、`datetime`同士でもawareとnaive間では比較できません。
（`TypeError: can't compare offset-naive and offset-aware datetimes`）
どちらかの型にそろえてから比較する必要があります。

```pycon
>>> from datetime import datetime, date
>>>
>>> dt1 = datetime(2016, 7, 1, 22, 30)
>>> dt2 = datetime(2016, 7, 5, 13, 45)
>>>
>>> dt1 == datetime(2016, 7, 1, 22, 30, 0)
True
>>> dt1 == dt1, dt1 == dt2, dt1 != dt1, dt1 != dt2, dt1 < dt2, dt1 > dt2, dt1 <= dt1, dt2 <= dt1, dt2 >= dt2, dt1 >= dt2
(True, False, False, True, True, False, True, False, True, False)
>>>
>>> d1 = dt1.date()
>>> d2 = dt2.date()
>>>
>>> d1 == date(2016, 7, 1)
True
>>> d1 == d1, d1 == d2, d1 != d1, d1 != d2, d1 < d2, d1 > d2, d1 <= d1, d2 <= d1, d2 >= d2, d1 >= d2
(True, False, False, True, True, False, True, False, True, False)
```


## 2つの日時の間隔を計算する

Pythonでは、日時の間隔、差分を`timedelta`オブジェクトで表現します。
（`delta`は差分(difference⇒Δ)の意。）

`timedelta`は`datetime`同士または`date`同士の引き算（`-`演算）で得られます。

`datetime`と`date`では計算できません。
（`TypeError: unsupported operand type(s) for -`）
また、`datetime`同士でもawareとnaive間では計算できません。
（`TypeError: can't subtract offset-naive and offset-aware datetimes`）
どちらかの型にそろえてから計算する必要があります。

```pycon
>>> from datetime import datetime, date
>>>
>>> d1, d2 = date(2016, 7, 1), date(2016, 7, 3)
>>>
>>> type(d2 - d1)
<class 'datetime.timedelta'>
>>> d2 - d1
datetime.timedelta(2)
>>> str(d2 - d1)
'2 days, 0:00:00'
>>> str(d1 - d2)
'-2 days, 0:00:00'
>>>
>>> dt1, dt2 = datetime(2016, 7, 1, 10, 30), datetime(2016, 7, 3, 9, 10)
>>> dt2 - dt1
datetime.timedelta(1, 81600)
>>> str(dt2 - dt1)
'1 day, 22:40:00'
```


## 2つの日時の月数を計算する

前項で書いた通り、2つの日付の差分で返されるのは日数です。
2つの日付の間隔が「何か月間なのか」を知りたい場合はどうしたら良いでしょうか？

そういう場合は、`dateutil`モジュールのサブモジュール`relativedelta`を使ってみましょう。
基本的にはこれで解決できるはずです。

```pycon
>>> from datetime import date
>>> from dateutil.relativedelta import relativedelta
>>>
>>> d1, d2 = date(2014, 11, 22), date(2016, 3, 1)
>>> str(d2 - d1)
'465 days, 0:00:00'
>>> delta = relativedelta(d2, d1)
>>> delta
relativedelta(years=+1, months=+3, days=+8)
>>> month_count = delta.years * 12 + delta.months
>>> month_count
15
```

12か月以上は`years`になってしまいますが、`years * 12 + months`で月数を算出することができました。

ここで少し気になるのが、月末がからんでくる計算、特にうるう年の2月前後の場合です。
そこで、2つの日付をそれぞれ1日ずつずらしていって、その場合のdeltaがどうなるかを確認してみました。

- 2つの日付を1日ずつずらして`relativedelta`の結果を調べるスクリプト

```python
from datetime import date, timedelta
from dateutil.relativedelta import relativedelta

d1 = date(2016, 2, 26)
d2 = date(2016, 3, 26)
delta1day = timedelta(days=1)

for x in range(9):
    print(d1, d2, relativedelta(d2, d1))
    d1 += delta1day
    d2 += delta1day
```

- 実行結果

```
2016-02-26 2016-03-26 relativedelta(months=+1)
2016-02-27 2016-03-27 relativedelta(months=+1)
2016-02-28 2016-03-28 relativedelta(months=+1)
2016-02-29 2016-03-29 relativedelta(months=+1)
2016-03-01 2016-03-30 relativedelta(days=+29)
2016-03-02 2016-03-31 relativedelta(days=+29)
2016-03-03 2016-04-01 relativedelta(days=+29)
2016-03-04 2016-04-02 relativedelta(days=+29)
2016-03-05 2016-04-03 relativedelta(days=+29)
```

さらに先の日付まで見てみましたが、大雑把にいうとどうやら2月の月末をまたぐ場合にだけ特別扱いをしているようです。
それ以外はずっと同じ日数(+29)になりました。

2つの日付の間隔を1日増やしてみると、今度は30日の月の月末をまたいでいる場合とそうでない場合で日数が変わりました。
きっと、月末日で補正をかけているのでしょう。

この辺の性質を理解しておけば大丈夫そうですね。


## 日付・日時の増減

`datetime - datetime`や`date - date`が`timedelta`になることは既に書きましたが、
日付・日時の増減については、`timedelta`を足し引きすることで、増減された`datetime`や`date`を得ることができます。

```pycon
>>> from datetime import datetime, date, timedelta
>>>
>>> dt = datetime(2016, 7, 5, 13, 45)
>>> d = dt.date()
>>>
>>> dt + timedelta(days=5, minutes=168)
datetime.datetime(2016, 7, 10, 16, 33)
>>> d - timedelta(days=13)
datetime.date(2016, 6, 22)
```

月単位での加減は、月数計算のときと同じく、`dateutil`モジュールのサブモジュール`relativedelta`を使用します。

```pycon
>>> from datetime import date
>>> from dateutil.relativedelta import relativedelta
>>>
>>> date(2016, 7, 5) - relativedelta(months=32)
datetime.date(2013, 11, 5)
```


## naiveとawareの相互変換

以下の例は、Python3において、標準モジュールだけでnaiveとawareの相互変換を確認したものです。
Python2（正確にはPython3.2未満）には`timezone`型が存在しないので、代わりに`pytz`モジュールを使ってください。

naiveな`datetime`をawareな`datetime`にするには、`datetime.replace()`メソッドを使います。

```pycon
>>> from datetime import datetime, timezone, timedelta
>>>
>>> jst = timezone(timedelta(hours=+9)) # pytzを使う場合は pytz.timezone('Asia/Tokyo')
>>> jst
datetime.timezone(datetime.timedelta(0, 32400))
>>> dt = datetime(2016, 7, 5, 13, 45) # naive
>>> dt
datetime.datetime(2016, 7, 5, 13, 45)
>>> dt2 = dt.replace(tzinfo=jst) # aware
>>> dt2
datetime.datetime(2016, 7, 5, 13, 45, tzinfo=datetime.timezone(datetime.timedelta(0, 32400)))
>>> str(dt2)
'2016-07-05 13:45:00+09:00'
```

参考資料#4-2によると、`datetime.replace()`メソッドでタイムゾーンを付加した場合に、少しおかしな挙動をするという報告がありました。
代替案として、`jst.localize(datetime(...))`を使う方法が示されています。
私の環境では再現しませんでしたので、`pytz`の古いバージョンでのバグなのかも知れません。


逆に、awareな`datetime`をnaiveな`datetime`にするには、同じく`datetime.replace()`メソッドを使います。
タイムゾーンには、「無し」を意味する`None`を指定します。

```pycon
# （上記の続き）

>>> dt3 = dt2.replace(tzinfo=None)
>>> dt3
datetime.datetime(2016, 7, 5, 13, 45)
>>> str(dt3)
'2016-07-05 13:45:00'
```


## `struct_time`を`datetime`または`date`に変換

タイムスタンプ型を`struct_time`で表すことがありますが、これを`datetime`型に変換したい場合。

`time.mktime()`関数と`datetime.fromtimestamp()`関数を使って、
`struct_time`→`timestamp(float)`→`datetime`
の順に変換します。

```pycon
>>> from datetime import datetime, date
>>> from time import localtime, mktime
>>>
>>> tm = localtime() # struct_time
>>> t = mktime(tm) # タイムスタンプ(float)に変換
>>> datetime.fromtimestamp(t)
datetime.datetime(2016, 7, 12, 22, 31, 15)
>>> date.fromtimestamp(t)
datetime.date(2016, 7, 12)
```

`struct_time`がタプルであることを利用して、次のように書くこともできます。

```pycon
# （上記の続き）

>>> datetime(*tm[:6])
datetime.datetime(2016, 7, 12, 22, 31, 15)
```

`tm[:6]`は年月日時分秒のタプルが得られますので、それを`datetime`のコンストラクターに6つの引数として渡しています。
これは簡潔に書けますが、可読性が低下するので避けたほうが良いかも知れません。


## `datetime`または`date`を`struct_time`に変換

前項とは逆に、`datetime`オブジェクトや`date`オブジェクトを`struct_time`オブジェクトに変換したい場合は、
`date.timetuple()`メソッドを使うと`struct_time`が得られます。

```pycon
>>> from datetime import datetime
>>>
>>> dt = datetime(2016, 7, 3, 12, 25)
>>> d = dt.date()
>>>
>>> dt.timetuple()
time.struct_time(tm_year=2016, tm_mon=7, tm_mday=3, tm_hour=12, tm_min=25, tm_sec=0, tm_wday=6, tm_yday=185, tm_isdst=-1)
>>> d.timetuple()
time.struct_time(tm_year=2016, tm_mon=7, tm_mday=3, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=185, tm_isdst=-1)
```


## 日付・日時のリストを生成する

ここでは日付の例だけ書きます。
日時の場合でも、型と単位を変えればいずれの方法も同様に適用できるはずです。

有限の日付リストを生成するには、`timedelta`と`range`を組み合わせて、内包表記でリストを作る方法がすぐに思いつきました。

```pycon
>>> from datetime import date, timedelta
>>>
>>> start_date = date(2016, 7, 5)
>>> a = [start_date + timedelta(days=x) for x in range(5)]
>>> a
[datetime.date(2016, 7, 5), datetime.date(2016, 7, 6), datetime.date(2016, 7, 7), datetime.date(2016, 7, 8), datetime.date(2016, 7, 9)]
```

...が、これだと1行で書けないのが少し残念です。
（`start_date`の代わりに直接`date(2016, 7, 5)`を書けばできますが、もちろんそれは無し。）

`dateutil`モジュールの`rrule`サブモジュールを使うと、1行で書けます。

```pycon
>>> from datetime import date
>>> from dateutil.rrule import rrule, DAILY
>>>
>>> a = [x.date() for x in rrule(DAILY, count=5, dtstart=date(2016, 7, 5))]
>>> a
[datetime.date(2016, 7, 5), datetime.date(2016, 7, 6), datetime.date(2016, 7, 7), datetime.date(2016, 7, 8), datetime.date(2016, 7, 9)]
```

そうそう、こういう風に書きたかったんです。

場合によっては、Pandasモジュール（`pandas.date_range`）を使った方が便利かも知れません。
詳しくは参考資料#5を参照して下さい。


## 閏年（うるうどし）の判定

`calendar`モジュールの`isleap`関数を使います。

```pycon
>>> import calendar
>>>
>>> calendar.isleap(2016)
True
>>> calendar.isleap(2015)
False
>>>
>>> from datetime import date
>>>
>>> d = date(2016, 7, 5)
>>> calendar.isleap(d.year)
True
```


## `datetime`モジュールに属するオブジェクトのbool評価

`datetime`モジュール内の日時関連オブジェクトは、Python3.5の時点では、`timedelta(0)`と等価のものを除き、すべて`True`と評価されます。
（`timezone`については、ドキュメントに記載がありませんでしたので、「すべて」には含みません。）

```pycon
>>> from datetime import *
>>>
>>> bool(datetime.fromtimestamp(0))
True
>>> bool(date.fromtimestamp(0))
True
>>> bool(time(0, 0, 0))
True
>>> bool(timedelta(1))
True
>>> bool(timedelta(0))
False
>>> bool(timezone.utc)
True
```

ところで、Python2では、午前零時ちょうどの`time`オブジェクトは`False`と評価されます。

```pycon
>>> from datetime import *

>>> bool(time(0, 0, 0))
False
```

これは、Python2というよりも、Python3.5未満で存在したバグ（Issue13936）で、Python3.5で修正された挙動です。
Python3.4.3で確認したところ、やはり`False`となりました。


## 処理時間計算

他の言語でも使われる方法ですが、(処理後のタイムスタンプ － 処理前のタイムスタンプ)で算出します。

```python
import time

t = time.time()
time.sleep(3.1)
print(time.time() - t)
# => 3.0999999046325684
```

今回は扱いませんが、コード断片の実行時間を計測するには、下記のモジュールを利用する方法もあります。

27.5. timeit — 小さなコード断片の実行時間計測 — Python 3.5.1 ドキュメント
[http://docs.python.jp/3.5/library/timeit.html](http://docs.python.jp/3.5/library/timeit.html)


## 付録

### 直列化サンプル

各オブジェクトを`pickle`により直列化したしたときのイメージです。

- Python2での実行結果

```pycon
>>> from datetime import datetime
>>> import pickle
>>>
>>> dt = datetime(2016, 7, 5, 13, 45)
>>>
>>> pickle.dumps(dt) # datetime
"cdatetime\ndatetime\np0\n(S'\\x07\\xe0\\x07\\x05\\r-\\x00\\x00\\x00\\x00'\np1\ntp2\nRp3\n."
>>> pickle.dumps(dt.date()) # date
"cdatetime\ndate\np0\n(S'\\x07\\xe0\\x07\\x05'\np1\ntp2\nRp3\n."
>>> pickle.dumps(dt.timetuple()) # struct_time
'ctime\nstruct_time\np0\n((I2016\nI7\nI5\nI13\nI45\nI0\nI1\nI187\nI-1\ntp1\n(dp2\ntp3\nRp4\n.'
>>> pickle.dumps(dt - dt) # timedelta
'cdatetime\ntimedelta\np0\n(I0\nI0\nI0\ntp1\nRp2\n.'
```

- Python3での実行結果

```pycon
>>> from datetime import datetime
>>> import pickle
>>>
>>> dt = datetime(2016, 7, 5, 13, 45)
>>> pickle.dumps(dt) # datetime
b'\x80\x03cdatetime\ndatetime\nq\x00C\n\x07\xe0\x07\x05\r-\x00\x00\x00\x00q\x01\x85q\x02Rq\x03.'
>>> pickle.dumps(dt.date()) # date
b'\x80\x03cdatetime\ndate\nq\x00C\x04\x07\xe0\x07\x05q\x01\x85q\x02Rq\x03.'
>>> pickle.dumps(dt.timetuple()) # struct_time
b'\x80\x03ctime\nstruct_time\nq\x00(M\xe0\x07K\x07K\x05K\rK-K\x00K\x01K\xbbJ\xff\xff\xff\xfftq\x01}q\x02(X\x07\x00\x00\x00tm_zoneq\x03NX\t\x00\x00\x00tm_gmtoffq\x04Nu\x86q\x05Rq\x06.'
>>> pickle.dumps(dt - dt) # timedelta
b'\x80\x03cdatetime\ntimedelta\nq\x00K\x00K\x00K\x00\x87q\x01Rq\x02.'
```


### 参考資料

 #1.
（公式ドキュメント・標準ライブラリーリファレンス）

8.1. datetime — 基本的な日付型および時間型 — Python 3.5.1 ドキュメント
[http://docs.python.jp/3.5/library/datetime.html#module-datetime](http://docs.python.jp/3.5/library/datetime.html#module-datetime)
8.1. datetime — 基本的な日付型および時間型 — Python 2.7.x ドキュメント
[http://docs.python.jp/2/library/datetime.html#module-datetime](http://docs.python.jp/2/library/datetime.html#module-datetime)

（`datetime`以外のモジュールのリンクは冗長なので省きます。上記リンクのページのどこかにリンクがあるのでそこから飛んでください。）

 #2.
dateutil - powerful extensions to datetime — dateutil 2.5.3 documentation
[https://dateutil.readthedocs.io/en/stable/](https://dateutil.readthedocs.io/en/stable/)

 #3.
pytz 2016.4 : Python Package Index
[https://pypi.python.org/pypi/pytz/](https://pypi.python.org/pypi/pytz/)

 #4-1.
Pythonの日付処理とTimeZone | Nekoya Press
[http://nekoya.github.io/blog/2013/06/21/python-datetime/](http://nekoya.github.io/blog/2013/06/21/python-datetime/)

 #4-2.
Pythonでdatetimeにtzinfoを付与するのにreplaceを使ってはいけない | Nekoya Press
[http://nekoya.github.io/blog/2013/07/05/python-datetime-with-jst/](http://nekoya.github.io/blog/2013/07/05/python-datetime-with-jst/)

 #5.
Python pandas で日時関連のデータ操作をカンタンに - StatsFragments
[http://sinhrks.hatenablog.com/entry/2014/11/09/183603](http://sinhrks.hatenablog.com/entry/2014/11/09/183603)