Java だったら、Jackson 使用で、jackson-datatype-jsr310 ライブラリを使った
デシリアライズを設定するだろう。
Jackson の 日付時刻の読込み - Oboe吹きプログラマの黙示録
jackson-datatype-jsr310 を使う - Oboe吹きプログラマの黙示録
Python の json.loads で JSON文字列 ⇒ dict で、value が文字列か数値に限定されるのではなく
日付時刻の文字列は、datetime にしたい時がある。
( dict への変換ではなく任意クラスに変換する時は、前に
JSONDecoder を継承してJSON→任意クラスへの変換 - Oboe吹きプログラマの黙示録
を書いていました。)
dict に変換したいJSON文字列、日付時刻が、%Y-%m-%d %H:%M:%S.%f の形式である。
jsonstr = """ { "date": "2023-11-03 16:27:26.015720" } """
必要なインポート
import json import datetime import re
json.loads で指定する object_hook を、日付時刻の書式 %Y-%m-%d %H:%M:%S.%f に、
正規表現で一致している値に限り datetime.strptime で変換する処理として用意する。
日付の正規表現:https://oboe2uran.hatenablog.com/entry/2015/04/14/225042
時刻の正規表現:https://oboe2uran.hatenablog.com/entry/2017/09/03/000539
を使う。
def dateTimeParser(dct): for k, v in dct.items(): if isinstance(v, str): if re.fullmatch(r'^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01]) (0[0-9]|1[0-9]|2[0-3]):(0[0-9]|[0-5][0-9]):(0[0-9]|[0-5][0-9])\.[0-9]{6}$', v): try: dct[k] = datetime.datetime.strptime(v, "%Y-%m-%d %H:%M:%S.%f") except: pass return dct
正規表現だけでは、存在しない日付、11月31日などはエラー
ValueError: day is out of range for month
となってしまうので、try~catch で捕捉する。
json.loads 実行
a = json.loads(jsonstr, object_hook=dateTimeParser) print(type(a.get('date'))) print(a.get('date'))
<class 'datetime.datetime'> 2023-11-03 16:27:26.015720
これには、欠点がある、1つの書式にしか対応できていない。
そこで、数種類の書式でも datetime に変換するようにする。
%Y-%m-%d %H:%M:%S.%f
%Y-%m-%d %H:%M:%S
%Y-%m-%d
この3つに対応させるようにすると、、
def dateTimeParser(dct): ptns = [ (r'^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01]) (0[0-9]|1[0-9]|2[0-3]):(0[0-9]|[0-5][0-9]):(0[0-9]|[0-5][0-9])\.[0-9]{6}$', '%Y-%m-%d %H:%M:%S.%f'), (r'^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01]) (0[0-9]|1[0-9]|2[0-3]):(0[0-9]|[0-5][0-9]):(0[0-9]|[0-5][0-9])$', '%Y-%m-%d %H:%M:%S'), (r'^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$', '%Y-%m-%d'), ] for k, v in dct.items(): if isinstance(v, str): r = [t for t in ptns if re.fullmatch(t[0], v)] if len(r)==1: try: dct[k] = datetime.datetime.strptime(v, r[0][1]) except: pass return dct