Python日付型

今回は、Pythonの日付型について紹介していきたいと思います。
バージョンは、Python3です。

#はじめに
Pythonではどのように日付型が実現されているのでしょうか。
Pythonでは標準ライブラリ「datetime」を使用して日付を利用します。
「datetime」は以下のようにインポートして利用します。

```py
import datetime
```

#日付の宣言方法

##現在の日付
現在の日付は、today()関数を利用して取得することができます。

```py
print(datetime.date.today()) # 2017-11-08
print(datetime.datetime.today()) # 2017-11-08 23:58:55.230456
```
ちなみに、datetime.dateは日付を表現する型で、年月日を保有しています。
datetime.datetimeは、時間まで保持している型で、年月日に加えて時分秒ミリ秒を保有しています。

##任意の日付
任意の日付は、datetime.dateもしくは、datetime.datetimeのコンストラクタを利用して宣言可能です。

```py
print(datetime.date(2017, 11, 12)) # 2017-11-12
print(datetime.datetime(2017, 11, 12, 9, 55, 28)) # 2017-11-12 09:55:28
```
datetime.dateの宣言では、引数に年、月、日を指定可能です。
datetime.datetimeの宣言では、引数に年、月、日、時、分、秒、ミリ秒、タイムゾーンを指定可能です。

#年、月、日、時、分、秒を取得
日付の年、月、日、時、分、秒を取得するには、日付型の属性にアクセスして取得できます。

```py
now = datetime.datetime(2017, 11, 12, 9, 55, 28)
print(now.year) #2017
print(now.month) #11
print(now.day) #12
print(now.hour) #9
print(now.minute) #55
print(now.second) #28
```
#曜日の取得
曜日を取得するには、weekday()関数を利用します。
返却される値は、0～6でそれぞれ以下の通りの意味になっています。
0 : 月曜日, 1 : 火曜日, 2 : 水曜日, 3 : 木曜日, 4 : 金曜日, 5 : 土曜日, 6 : 日曜日

```py
print(datetime.date(2017, 11, 11).weekday()) #5
print(datetime.date(2017, 11, 12).weekday()) #6
print(datetime.date(2017, 11, 13).weekday()) #0
```

#日付情報をタプルで取得
日付の各属性をまとめて取得可能です。time.struct_timeというクラスで返却されます。
だいたい見たとおりの値が返却されますが、見慣れないものが少しありますので説明します。
tm_yday：年はじめから何日たっているかです。この例の場合、1月1日から316日たっています。
tm_isdst：夏時間が有効な場合は 1、そうでない場合は 0 。-1は不明。

```py
now = datetime.datetime(2017, 11, 12, 9, 55, 28)
print(now.timetuple()) # time.struct_time(tm_year=2017, tm_mon=11, tm_mday=12, tm_hour=9, tm_min=55, tm_sec=28, tm_wday=6, tm_yday=316, tm_isdst=-1)
```

#日付のみ取得
datetime型で日付を宣言したときに時間が不要になることもあると思います。
そういった場合に、date()関数を利用して、date型の日付に変更できます。

```py
now = datetime.datetime(2017, 11, 12, 9, 55, 28)
print(now.date()) # 2017-11-12
```

#時間のみ取得
時間のみ必要な場合にtime()関数を利用して取得できます。

```py
now = datetime.datetime(2017, 11, 12, 9, 55, 28)
print(now.time()) # 09:55:28
```

#日付計算
timedeltaを使用して日付計算を行います。
週、日、時、分、秒の計算が可能です。年の計算、月の計算はdatetimeではできないようです。

```py
calc_source = datetime.datetime(2017, 11, 12, 9, 55, 28)
print(calc_source + datetime.timedelta(weeks=3)) # 2017-12-03 09:55:28
print(calc_source + datetime.timedelta(days=20)) # 2017-12-02 09:55:28
print(calc_source + datetime.timedelta(hours=5)) # 2017-11-12 14:55:28
print(calc_source + datetime.timedelta(minutes=10)) # 2017-11-12 10:05:28
print(calc_source + datetime.timedelta(seconds=15)) # 2017-11-12 09:55:43

print(calc_source - datetime.timedelta(weeks=3)) # 2017-10-22 09:55:28
print(calc_source - datetime.timedelta(days=20)) # 2017-10-23 09:55:28
print(calc_source - datetime.timedelta(hours=5)) # 2017-11-12 04:55:28
print(calc_source - datetime.timedelta(minutes=10)) # 2017-11-12 09:45:28
print(calc_source - datetime.timedelta(seconds=15)) # 2017-11-12 09:55:13
```

また、dateutil.relativedeltaを使用すると年の計算、月の計算もできるようになります。

```py
from dateutil.relativedelta import relativedelta

calc_source = datetime.datetime(2017, 11, 12, 9, 55, 28)
print(calc_source + relativedelta(years=3)) # 2020-11-12 09:55:28
print(calc_source + relativedelta(months=2)) # 2018-01-12 09:55:28
print(calc_source + relativedelta(weeks=3)) # 2017-12-03 09:55:28
print(calc_source + relativedelta(days=20)) # 2017-12-02 09:55:28
print(calc_source + relativedelta(hours=5)) # 2017-11-12 14:55:28
print(calc_source + relativedelta(minutes=10)) # 2017-11-12 10:05:28
print(calc_source + relativedelta(seconds=15)) # 2017-11-12 09:55:43

print(calc_source - relativedelta(years=3)) # 2014-11-12 09:55:28
print(calc_source - relativedelta(months=2)) # 2017-09-12 09:55:28
print(calc_source - relativedelta(weeks=3)) # 2017-10-22 09:55:28
print(calc_source - relativedelta(days=20)) # 2017-10-23 09:55:28
print(calc_source - relativedelta(hours=5)) # 2017-11-12 04:55:28
print(calc_source - relativedelta(minutes=10)) # 2017-11-12 09:45:28
print(calc_source - relativedelta(seconds=15)) # 2017-11-12 09:55:13
```

#日付同士の比較
数値と同じように、>, >=, <, <=, ==で比較可能です。

```py
comp1 = datetime.datetime(2017, 11, 12, 9, 55, 28)
comp2 = datetime.datetime(2017, 11, 12, 9, 55, 29)
print((comp1 > comp2)) # False
print((comp1 >= comp2)) # False
print((comp1 < comp2)) # True
print((comp1 <= comp2)) # True
print((comp1 == comp2)) # False
```

気を付ける点は、日時(datetime)と日（date）の比較はできないことです。

```py
comp3 = datetime.date(2017, 11, 12)
comp4 = datetime.datetime(2017, 11, 12, 9, 55, 29)
print((comp3 > comp4)) # TypeError
```

#日付変換
##文字列⇒日付型
datetime.datetime.strptimeを使用します。
第一引数は、文字列の日付で、第二引数は日付フォーマットです。

```py
date_str = "2017/11/06"
date_formatted = datetime.datetime.strptime(date_str, "%Y/%m/%d")
print(date_formatted) # 2017-11-06 00:00:00

datetime_str = "2017/11/06 23:59:20"
datetime_formatted = datetime.datetime.strptime(datetime_str, "%Y/%m/%d %H:%M:%S")
print(datetime_formatted) # 2017-11-06 23:59:20
```

##日付型⇒文字列
strftimeを使用します。
引数に出力する文字列のフォーマットを指定します。

```py
datetime_format = datetime.datetime(2017, 11, 12, 9, 55, 28)
print(datetime_format.strftime("%Y/%m/%d")) # 2017/11/12
print(datetime_format.strftime("%Y/%m/%d %H:%M:%S")) # 2017/11/12 09:55:28
```

フォーマットで使用する。%～を少々紹介します。
%Y：西暦 ( 4桁) の 10 進表記を表します。
%m：0埋めした10進数で表記した月。
%d：0埋めした10進数で表記した月中の日にち。
%H：0埋めした10進数で表記した時 (24時間表記)。
%I：0埋めした10進数で表記した時 (12時間表記)。
%M：0埋めした10進数で表記した分。
%S：0埋めした10進数で表記した秒。
%b：ロケールの月名を短縮形で表示します。
%B：ロケールの月名を表示します。

以上で、日付に関する紹介を終わります。
Javaと比較しても結構使用しやすいと思いました。