【python】datetimeモジュールのクラス種類と使い方

#【備忘録】pythonのdatetimeモジュールのクラス種類と使い方

pythonのdatetimeモジュールで利用できるクラスの種類と違いを実例で確認する。

[公式サイト](https://docs.python.org/ja/3/library/datetime.html#datetime.datetime)


##クラスの種類

6種類のクラス（データ型）が用意されている

1. `datetime.date`：日付(年、月、日)
2. `datetime.time`：時刻(時、分、秒、マイクロ秒)
3. `datetime.datetime`：日付＋時刻
4. `datetime.timedelta`：時間差分
5. `datetime.timezone`：タイムゾーンの設定
6. `datetime.tzinfo`：タイムゾーン情報



##各クラスの中身
###0. 補足条件
datetimeモジュールはdtとして呼び出す。

```python:datetimeモジュールの呼び出し
import datetime as dt
```

▼実際の使用例
`datetime.date`は`dt.date`として記述
>※datetime.datetime.dateはエラーになる
（name 'datetime' is not defined）



###1. datetime.date

`dt.date.today()`の実行結果
**datetime.date(2020, 3, 18)**
 　└ datetime.date型
　 └ (2020, 3, 18)＝(年, 月, 日)

⇒ **年、月、日の3つ**のデータが取得できる。
(属性：year, month, day)


<br>
###2. datetime.time
`dt.time`でメソッドは使えなさそう。。
dt.dateのように、現在時刻を取得しようと思ってもできない。

- dt.time.now()： エラー
- dt.time.today() ：エラー

>type object 'datetime.time' has no attribute 'today'


**■使い方**
時刻を自分で指定する。

日付データが不要で、時刻データのみ呼び出したり、変更したい場合に有効。

- datetime.time型がもつ、hours, minute, second, microsecondを個別に指定。
- 指定したデータを呼び出す。（例：`.hour`）
- 指定したデータを変更する （例：`.replace(hour=1)`）

指定した数値

```python:時刻の指定と呼び出し（datetime.time）

#時刻を設定
timeA = dt.time(10, 30, 45, 123456) 

#時刻を呼び出す
timeA.hour  #実行結果：10
timeA.minute #実行結果：30
timeA.second #実行結果：45
timeA.microsecond #実行結果：123456
```


```python:時刻の変更（replace()）
#時刻を設定
timeA = dt.time(10, 30, 45, 123456) 

#(1)個別に変更する
timeA = timeA.replace(hour=5)  
timeA

#実行結果
# →　datetime.time(5, 30, 45, 123456) 


#(2)まとめて変更する
timeA = timeA.replace(hour=1, minute=2, second=30, microsecond=400)
timeA

#出力結果
# → datetime.time(1, 2, 30, 400)
```


<br>
###3. datetime.datetime

`dt.datetime.today()`の実行結果
**datetime.datetime(2020, 3, 18, 7, 42, 54, 95450)**
 　└ datetime.datetime型
　 └ (2020, 3, 18, 7, 42, 54, 95450)
　　 (年, 月, 日,時,分,秒,マイクロ秒)

⇒ **年、月、日、時、分、秒、マイクロ秒の7つ**のデータが取得できる。
(属性：year, month, day, hour, minute, microsecond)

>※裏側ではtzinfo（tz：タイムゾーン情報）も所持している。

**▼tzinfo（tz：タイムゾーン情報）**
カッコなしのnowなどでメソッドを実行した場合に情報が出力される。

```python:タイムゾーン情報を表示する
dt.datetime.now
<function datetime.now(tz=None)>
```



<br>
**■now()とtoday()**
datetime.datetimeでよく使うメソッド。
※どちらも同じ

```python:よく使うメソッドnowとtoday
#.now()
dtNow = dt.datetime.now()
dtNow  #datetime.datetime(2020, 3, 18, 21, 28, 13, 409431)

#.today()
dtToday = dt.datetime.today()
dtToday #datetime.datetime(2020, 3, 18, 22, 45, 10, 518281)

```

<br>
**■combine(A, B)**
日付の型と時刻の型を組み合わせることが可能。
`datetime.datetime.combine(A, B)`

```python:よく使うメソッドcombine
#.combine(A, B)
dateA = dt.date(2020,5,6)
timeA = dt.time(10,20,0)

dt.datetime.combine(dateA, timeA)

#出力結果
# → datetime.datetime(2020, 5, 6, 10, 30, 0)
```
※combine(A, B)は`A= datetime.date型`、`B= datetime.time型`と決まっている。

> cobmbine(timeA, dateB)など、指定の型と異なる場合はエラーになる。
>>combine() argument 1 must be datetime.date, not datetime.time

<br>
**■replace()**
引数で指定した数値を変更できる（複数指定可能）

```python:replace
#.replace()

dtNow =dt.datetime.now() 
dtNow # datetime.datetime(2020, 3, 18, 22, 10, 15, 517216)

dtNow = dtNow.replace(year=2018)
dtNow = dtNow.replace(hour=5, minute=30, second=30)
dtNow

#出力結果
# → datetime.datetime(2018, 3, 18, 5, 30, 30, 474609)
```


**■曜日を出力する**
`weekday()`　：0～6（月曜日0～日曜日6）
`isoweekday()`　：1～6（月曜日1~日曜日7）

|出力         | 月 | 火 | 水 | 木 | 金 | 土 | 日 |
|:-----------:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|weekday()    | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|isoweekday() | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 

```python:曜日の出力
today = dt.datetime.today()  #datetime.datetime(2020, 3, 18, 22, 30, 46, 646567)

#.weekday()
today.weekday() #出力：2　→ 水曜日

#.isoweekday()
today.weekday() #出力：3　→ 水曜日

```


**■日付 or 時刻のみ出力する**
`date()`　：year、month、day
`time()`　：hour、minute、second、microsecond


```python:日付・時刻の出力
now = dt.datetime.now()
#datetime.datetime(2020, 3, 18, 22, 35, 50, 177279)

#.time()
now.time() #出力：datetime.time(22, 38, 1, 997649)

#.date()
now.date() #datetime.date(2020, 3, 18)
```



<br>
###4. datetime.timedelta
・日付や時間の足し算・引き算ができる。
・日付同士をひいた結果がtimedeltaで表示される。

- timedeltaは足し算・引き算処理をするものではい。
- **★どの項目をいくつ足すか・引くかの指定**
    - dt.timedelta(days=2) ：2日足す
    - dttimedelta(hours=-5) :5時間引く
- 指定できる引数(7種類。**※複数形**
    - weeks （：7daysの倍数)
    - days
    - hours
    - minutes
    - seconds 
    - milliseconds
    - microseconds
- 指定できない引数（**年、月は不可**）
    - years
    - months
- デフォルトの引数は0

>指定できない引数や、間違った引数(単数形など)はエラーになる
>>'years' is an invalid keyword argument for \_\_new\_\_()


**使い方**
(1)2020年1月1日に2週間足す
`+ dt.timedelta(weeks=2)`

```python:timedeltaで足し算
newyear = dt.datetime(2020, 1, 1)  #datetime型で2020年1月1日を定義
newyear + dt.timedelta(weeks=2)

#実行結果
#datetime.datetime(2020, 1, 15, 0, 0)
#　→ 2020年1月15日
```

<br>
(2)2020年1月1日から25時間引く
`+ dt.timedelta(hours=-25)`

```python:timedeltaで引き算
newyear = dt.datetime(2020, 1, 1)  #datetime型で2020年1月1日を定義
newyear + dt.timedelta(hours=-25)

#実行結果
datetime.datetime(2019, 12, 30, 23, 0)
#　→ 2019年12月30日23時
```

<br>
**補足**
(3)所持していないデータ部分も**計算される**

**▼実例**
・date型(時間データを持たない)に時間足してもエラーにならない。
・結果は計算されたものが表示される
　　└ 非表示部で計算している

```python:型が所持していないデータの取扱
newyear2 = dt.date(2020, 1, 1)　　#datetime.date型（時間データを持たない）
newyear2 + dt.timedelta(hours=100) #100時間足す

#実行結果
#datetime.date(2020, 1, 5)
# → 2020年1月5日
```


<br>
(3)日付の差分の結果
ある日付同士の間隔を算出する。

- 使える型は`datetime.datetime`と`datetime.date`
- datetime.timeは使えない
- 比較する方は同じ必要がある
    - datetime.datetimeとdatetime.dateではエラーになる
- 足し算はできない（エラーになる）


```python:2つの日付の間隔を求める（事例①）
dateA = dt.date(2020,1,1)
dateB = dt.date(2020,1,9)

dateA - dateB  #出力：datetime.timedelta(days=-8)
dateB - dateA  #出力：datetime.timedelta(days=8)
```

```python:2つの日付の間隔を求める(事例②）
pastA = dt.datetime(2000, 1, 1)
now = dt.datetime.now()  #出力：datetime.datetime(2020, 3, 18, 22, 56, 50, 604259)

now - pastA

#出力結果
#datetime.timedelta(days=7382, seconds=82358, microseconds=594717)
```
※datetime.timedeltaにyears, monthsはない

>足し算はエラー(※「+」はサポートしてない）
>> unsupported operand type(s) for +



<br>
###5. datetime.timezone
自分でタイムゾーンを設定する場合に使用。

`dt.timezone(dt.timedelta(hours=AAA), 'BBB')`

設定する値は2つ。

- AAA：基準からどれだけズラすか
    - +/-0~24 ※24以下
        - 24はエラー
- BBB：設定したタイムゾーンにつける名称
    - 呼び出すときに引数で使う


**▼設定方法**
①イギリス(UCT。基準：+0時間)　[≒GMT]
`datetime.timezone(datetime.timedelta(0), 'UCT')`
   
②トロント（EDT。-4）
`datetime.timezone(datetime.timedelta(-4), 'EST')`

③日本（JST。+9）
`dt.timezone(dt.timedelta(hours=+9), 'JST')`



**▼実際の使い方の例**
トロントの時刻(EDT)を設定し、現在時刻を呼び出す。

```python:timezoneの使い方(トロントの時刻)
EDT = dt.timezone(dt.timedelta(hours=-4),'EDT')
EDT　#出力：datetime.timezone(datetime.timedelta(days=-1, seconds=72000), 'EDT')

dt.datetime.now(EDT)

#出力結果
# datetime.datetime(2020, 3, 18, 10, 34, 8, 685415, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000), 'EDT'))
```

<br>
**■補足:UTCとGMTの違い**

**①UTC：協定世界時間**（Coordinated Universal Time)
　└ 現在の世界標準時間
　└ セシウム原子の振動数から算出

**②GMT：グリニッジ標準時間**（Greenwich Mean Time）
　└ 過去の標準時間
　└ グリニッジ天文台の計測結果から算出
　└ グリニッジはロンドンのすぐ南の都市

>- どちらも大して変わらない（UTC≒GMT）
- イギリスの時間
    - イギリスが基準：hours=±０ 


<br>
###6. datetime.tzinfo
タイムゾーンや夏時間など、**カスタマイズ可能な時刻修正**の概念を提供する（とのこと）。