日付と時刻
項目一覧
Overview
このガイドでは、PyMongo で Python datetime
オブジェクトを処理する方法を学習できます。
用語
Python は日付と時刻を表すために専用のデータ型datetime.datetime
を使用します。 MongoDB は、英国ロード フィールドを対象としたグローバル タイム標準(UTC)にdatetime
値を保存します。
ネイティブ日時
UTC オフセットやタイムゾーンに関する追加情報が含まれていない場合、 datetime
値はネイティブではありません。 以下は、ネイティブのdatetime
オブジェクトの例です。
datetime(2002, 10, 27, 14, 0, 0)
認識済み日時
datetime
値は、 tzinfo
属性が含まれている場合に認識されます。 この属性は、UTC 時間からの値のオフセット、そのタイムゾーン、夏時間が有効になっているかどうかを示します。 以下は、認識されているdatetime
オブジェクトの例です。
datetime(2002, 10, 27, 6, 0, tzinfo=<DstTzInfo 'US/Pacific' PST-1 day, 16:00:00 STD>)
ローカライズ
ローカライズとは、 datetime
の値に時間を追加したり、その値から時間を減算してその値を別のタイムゾーンに変換するプロセスです。 datetime
値をローカライズするには、次の手順を実行します。
pip を使用して、Python 環境に
pytz
ライブラリをインストールします。pip install pytz
pytz.timezone
オブジェクトを作成します。 ターゲット タイム ゾーンを string としてコンストラクターに渡します。ローカライズするための
datetime
値を渡して、timezone
オブジェクトでlocalize()
メソッドを呼び出します。
次のコード例では、 datetime
値を"US/Pacific"
タイムゾーン(8 時間のオフセット)にローカライズします。
from datetime import datetime from pytz import timezone utc_datetime = datetime(2002, 10, 27, 6, 0, 0) pacific = timezone("US/Pacific") local_datetime = pacific.localize(utc_datetime) print(f"UTC datetime: {utc_datetime}") print(f"Local datetime: {local_datetime}")
UTC datetime: 2002-10-27 06:00:00 Local datetime: 2002-10-27 06:00:00-08:00
タイムゾーン文字列の標準リストについては、 タイムゾーン データベース または Wikipedia の対応する記事を参照してください。
重要
PyMongo では、時刻のない日付の BSON 型がないため、 datetime.date
インスタンスを保存できません。 MongoDB に保存する前に、すべてのdate
オブジェクトをdatetime
オブジェクトに変換します。
日時の読み取り
PyMongo を使用してdatetime
値を取得する場合、ドライバーはネイティブ UTC、認識済み UTC、またはローカライズされた値としてそれを形式できます。 次のセクションでは、各種類の値を取得する方法について説明します。
これらのセクションでは、 sample_collection
という名前の MongoDB コレクションに次のドキュメントが含まれていることを前提としています。 "date"
フィールドの値は UTC datetime
値です。
{"date": datetime(2002, 10, 27, 14, 0, 0)}
ネイティブ UTC 日時
デフォルトでは、PyMongo は追加情報のない UTC datetime
値を検索します。 次のコード例では、サンプル ドキュメントを取得し、 datetime
値を出力します。 出力される値は、サンプルドキュメントの と同じです。
from datetime import datetime collection = database["sample_collection"] find_result = collection.find_one()["date"] print(f"datetime: {find_result}") print(f"datetime.tzinfo: {find_result.tzinfo}")
datetime: 2002-10-27 14:00:00 datetime.tzinfo: None
認識済み UTC 日時
PyMongo に認識済みのdatetime
値を取得するよう指示するには、 CodecOptions
オブジェクトを作成し、 tz_aware = True
をコンストラクターに渡します。 次に、 CodecOptions
オブジェクトをget_collection()
メソッドに渡します。
次のコード例では、サンプル ドキュメントからdatetime
の値を認識済みのdatetime
として取得します。
from pymongo import MongoClient from datetime import datetime from bson.codec_options import CodecOptions options = CodecOptions(tz_aware = True) collection = database.get_collection("sample_collection", options) find_result = collection.find_one()["date"] print(f"datetime: {find_result}") print(f"datetime.tzinfo: {find_result.tzinfo}")
datetime: 2002-10-27 14:00:00+00:00 datetime.tzinfo: <bson.tz_util.FixedOffset object at 0x104db2b80>
ローカライズされた日時
ユーザーにdatetime
値を表示する予定の場合は、MongoDB から読み取られたすべての時間を特定のタイムゾーンに自動的に変換するように PyMongo に指示できます。 そのためには、「用語」セクションで説明されているように、ターゲット タイムゾーン用のtimezone
オブジェクトを作成します。 Then, create a CodecOptions
object and pass the following arguments to the constructor:
tz_aware
:True
に設定します。tzinfo
:timezone
オブジェクト。
次のコード例では、サンプルドキュメントを取得していますが、 tz_aware
とtzinfo
引数を使用してdatetime
の値を"US/Pacific"
タイムゾーンに自動的にローカライズします。
from pymongo import MongoClient from datetime import datetime from bson.codec_options import CodecOptions import pytz from pytz import timezone pacific = timezone("US/Pacific") options = CodecOptions(tz_aware = True, tzinfo = pacific) collection = database.get_collection("sample_collection", options) find_result = collection.find_one()["date"] print(f"datetime: {find_result}") print(f"datetime.tzinfo: {find_result.tzinfo}")
datetime: 2002-10-27 06:00:00-08:00 datetime.tzinfo: US/Pacific
Tip
上記の例では、コレクション レベルでコーデック オプションを指定しています。 クライアント レベルまたはデータベース レベルでコーデック オプションを指定することもできます。
日時の保存
整合性のために、UTC datetime
値のみを MongoDB に保存します。 PyMongo を使用してdatetime
値を含むフィールドを作成または更新すると、ドライバーは最初にdatetime
値がネイティブか認識されているかを確認します。
datetime
がネイティブの場合、PyMongo はdatetime
が UTC であると想定し、それを変更せずに MongoDB に保存します。datetime
が認識されている場合、PyMongo は MongoDB に保存する前に時間を自動的に UTC に変換します。
次のコード例では、 "US/Pacific"
タイムゾーンにローカライズされたdatetime
値を含むドキュメントを挿入します。 PyMongo は、付属のタイムゾーンを使用してローカル時間を UTC に変換します。 ドキュメントが MongoDB から取得された場合、 datetime
値は UTC です。
from pymongo import MongoClient from datetime import datetime from pytz import timezone utc_datetime = datetime(2002, 10, 27, 6, 0, 0) pacific = timezone("US/Pacific") local_datetime = pacific.localize(utc_datetime) print(f"datetime before storage: {local_datetime}") collection.insert_one({"date": local_datetime}) find_result = collection.find_one()["date"] print(f"datetime after storage: {find_result}")
datetime before storage: 2002-10-27 06:00:00-08:00 datetime after storage: 2002-10-27 14:00:00
重要
datetime.now()
引数なしでdatetime.now()
メソッドを呼び出すのは避けてください。 これにより、現在のローカル時間が返されます。
代わりに、UTC で現在時刻を返すdatetime.now(tz=datetime.timezone.utc)
メソッドを常に呼び出します。
範囲外の日時の処理
Python のdatetime
クラスは、 datetime.min
からdatetime.max
までのdatetime
値のみを表すことができます( 1 - 9999年)。 BSON を使用すると、はるかに大きな日付と時刻の範囲を表すことができます。これにより、64 Unix エポック からの任意の ビット ミリ秒値が利用できます。
PyMongo で BSON 時間を表すには、Python の組み込みint
型のラッパーであるdatetime_ms.DatetimeMS
オブジェクトを作成します。 次のいずれかの値を渡すことで、 DatetimeMS
オブジェクトを手動で作成できます。
UNIX エポックからのミリ秒数を表す
int
datetime
オブジェクト
次のコード例では、年 - 146136543 ( datetime
の範囲外の日付)を表すint
値を渡してDatetimeMS
オブジェクトを構築します。
from bson.datetime_ms import DatetimeMS out_of_range = DatetimeMS(-(2**62))
また、UTC datetime
値をDatetimeMS
オブジェクトとして自動的にデコードするように PyMongo に指示することもできます。 そのためには、 CodecOptions
のdatetime_conversion
パラメータをdatetime_ms.DatetimeConversion
列挙型の値に設定します。 次のセクションでは、これらの値について説明します。
Tip
DatetimeMS
オブジェクトは、 DatetimeMS
の他のインスタンスに対する豊富な比較メソッドをサポートします。 また、 DatetimeMS.to_datetime()
メソッドを使用してこれらをdatetime
オブジェクトに変換することもできます。
DatetimeConversion.DATETIME
DatetimeConversion.DATETIME
は、デフォルト値です。 この値により、次の例に示すように、PyMongo は範囲外の日付をデコードしようとするとエラーを発生させます。
from datetime import datetime from bson import encode, decode from bson.datetime_ms import DatetimeMS out_of_range = DatetimeMS(-(2**62)) val = encode({"date": out_of_range}) decoded = decode(val) print(decoded)
... bson.errors.InvalidBSON: year -146136543 is out of range (Consider Using CodecOptions(datetime_conversion=DATETIME_AUTO) or MongoClient(datetime_conversion='DATETIME_AUTO')). ...
DatetimeConversion.DATETIME_MS
この値は、日付がdatetime
の範囲内であっても、 DatetimeMS
オブジェクトのみを返すように PyMongo に指示します。
from datetime import datetime from bson import encode, decode from bson.datetime_ms import DatetimeMS from bson.codec_options import CodecOptions, DatetimeConversion val = encode({"date": datetime(1970, 1, 2)}) codec_ms = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_MS) decoded = decode(val, codec_options=codec_ms) print(decoded)
{"date": DatetimeMS(86400000)}
DatetimeConversion.DATETIME_Auto
この値は、値がdatetime
の範囲内にある場合はdatetime
オブジェクトを返し、それ以外の場合はDatetimeMS
オブジェクトを返すように PyMongo に指示します。 次のコード例では、 datetime
範囲内の 1 つの日時と範囲外の日時をエンコードおよびデコードします。
from datetime import datetime from bson import encode, decode from bson.datetime_ms import DatetimeMS from bson.codec_options import CodecOptions, DatetimeConversion in_range = encode({"date": datetime(1970, 1, 1)}) out_of_range = encode({"date": DatetimeMS(-(2**62))}) codec_auto = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_AUTO) in_decoded = decode(in_range, codec_options=codec_auto) out_decoded = decode(out_of_range, codec_options=codec_auto) print(f"in-range date: {in_decoded}") print(f"out-of-range date: {out_decoded}")
in-range date: {"date": datetime.datetime(1970, 1, 1, 0, 0)} out-of-range date: {'x': DatetimeMS(-4611686018427387904)}
DatetimeConversion.DATETIME_CLAMP
この値は結果のdatetime
オブジェクトを「ロック」し、それらをdatetime
の範囲( 999 、 000マイクロ秒に削除)内に収まるようにします。
次のコード例では、 datetime
範囲より前の 1 つの日時とdatetime
範囲より後の 1 つの日時をエンコードおよびデコードします。 結果の値は、許可された範囲の先頭と末尾にあります。
from datetime import datetime from bson import encode, decode from bson.datetime_ms import DatetimeMS from bson.codec_options import CodecOptions, DatetimeConversion before = encode({"date": DatetimeMS(-(2**62))}) after = encode({"date": DatetimeMS(2**62)}) codec_clamp = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_CLAMP) before_decoded = decode(before, codec_options=codec_clamp) after_decoded = decode(after, codec_options=codec_clamp) print(f"datetime before the range: {before_decoded}") print(f"datetime after the range: {after_decoded}")
datetime before the range: {"date": datetime.datetime(1, 1, 1, 0, 0)} datetime after the range: {"date": datetime.datetime(9999, 12, 31, 23, 59, 59, 999000)}
API ドキュメント
PyMongo での日付と時刻の操作の詳細については、次の API ドキュメントを参照してください。
datetime
( docs.python.org)pytz
( pypi.org)