2018/12/04

[Python] date と datetime オブジェクトの相互変換まとめ

[datetime オブジェクト、Unix time、文字列の相互変換まとめ](https://kokufu.blogspot.com/2018/12/python-datetime-unix-time.html) を書いたので、ついでと言っては何ですが date と datetime の変換についてもまとめてみました。





なお、掲載コードは以下のように import 済みとします。
```python
from datetime import datetime, date, time
import pytz
```

## 1. date と datetime の相互変換
### datetime → date
datetime から date に変換するには [dateteime.date()](https://docs.python.org/3/library/datetime.html#datetime.date) を使用します。
```python
dt_native = datetime.utcfromtimestamp(1541030400)  # native
# 2018-11-01 00:00:00

dt_native.date()
# 2018-11-01 
```

aware な datetime オブジェクトにも使用できます。当然、タイムゾーンの影響は受けます。
```python
dt = datetime.fromtimestamp(1541030400, tz=pytz.timezone('America/New_York'))  # aware
# 2018-10-31 20:00:00-04:00

dt_aware.date()
# 2018-10-31
```

### date → datetime
date から datetime に変換するには [datetime.combine()](https://docs.python.org/3/library/datetime.html#datetime.datetime.combine) を使用します。

しかし、`combine()` にタイムゾーンを指定して aware なオブジェクトを作成するのは危険です。

一度、native に変換してから aware にした方が良いでしょう。
```python
d = date(2018, 11, 1)
dt_native = datetime.combine(d, time())
print(pytz.timezone('Asia/Tokyo').localize(dt_native))
# 2018-11-01 00:00:00+09:00

# tzinfo を指定すると +9:19 になってしまう
datetime.combine(d, time(), tzinfo=pytz.timezone('Asia/Tokyo'))
# 2018-11-01 00:00:00+09:19
```

> 参考
>
> [[Python] datetime.combine() でタイムゾーンは指定しない方がよい | 穀風](https://kokufu.blogspot.com/2018/12/python-datetimecombine.html)


## 2. date と文字列の変換
### date → 文字列
date から文字列に変換するには [date.strftime()](https://docs.python.org/3/library/datetime.html#datetime.date.strftime) を使用します。
```python
d = date(2018, 11, 1)
d.strftime("%Y/%m/%d")
# 2018/11/01
```

### 文字列 → date
date オブジェクトには `datetime.strptime()` 相当のメソッドが用意されていません。
そのため、一度 datetime を経由してから、date に変換するしかなさそうです。

```python
date_string = "2018/11/01"
dt = datetime.strptime(date_string, "%Y/%m/%d")
dt.date()
# 2018-11-01
```

## 3. ISO フォーマット文字列と date の相互変換
[ISO 8601 形式](https://ja.wikipedia.org/wiki/ISO_8601) と date の相互変換も提供されています。
### ISO フォーマット文字列 → date
ISOフォーマット文字列から date オブジェクトの変換は [date.fromisoformat()](https://docs.python.org/3/library/datetime.html#datetime.date.fromisoformat) を使用します。

"YYY-MM-DD" のみ対応。
Python 3.7 で導入されました。
```python
date.fromisoformat("2018-11-01")
# 2018-11-01
```

### date → ISO フォーマット文字列
```python
d = date(2018, 11, 1)
d.isoformat()
# 2018-11-01
```


## 4. Unix time から date への変換
[Unix time](https://ja.wikipedia.org/wiki/UNIX%E6%99%82%E9%96%93) から date オブジェクトの変換には [date.fromtimestamp()](https://docs.python.org/3/library/datetime.html#datetime.date.fromtimestamp) が使えます。

ただ、**ローカルタイムゾーンを適用**して変換されてしまうのでなるべく使わない方が良いでしょう。
```python
date.fromtimestamp(1541030400)
# 2018-11-01  (+09:00 のタイムゾーン設定されているマシンで実行した場合)
# 2018-10-31  (-05:00 のタイムゾーン設定されているマシンで実行した場合)
```

例外的に、 [datetime.now()](https://docs.python.org/3/library/datetime.html#datetime.datetime.now) 等を用いてローカルタイムを処理する場合などは使えると思います。
```python
now = datetime.now()
# 2018-11-30 10:44:35.469159

date.fromtimestamp(now.timestamp())
# 2018-11-30
```

0 件のコメント: