pymongo date类型处理

查询字符串:

query = '{ "ord_date": { "$gte": { "$date": "2020-03-20T" } } }'

使用json_util.loads将查询字符串转换成字典时出错。

from bson import json_util
query = '{ "ord_date": { "$gte": { "$date": "2020-03-20" } } }'

try:
    query = json_util.loads(query)
except Exception as e:
    print(e)

打印出来的错误:

time data '2020-03' does not match format '%Y-%m-%dT%H:%M:%S'

需求:希望json_util.loads能解析'%Y-%m-%d'这样的date类型。

解决:

改写json_util的_parse_canonical_datetime,对应下面代码中的_parse_canonical_datetime_new

使用dateutil模块的parser.parse方法对字符串进行解析,随后 使用datetime.datetime.strftime方法将datetime类型转换成"%Y-%m-%dT%H:%M:%SZ"格式的字符串。

def loads_new(s, *args, **kwargs):
    """Helper function that wraps :func:`json.loads`.

    Automatically passes the object_hook for BSON type conversion.

    Raises ``TypeError``, ``ValueError``, ``KeyError``, or
    :exc:`~bson.errors.InvalidId` on invalid MongoDB Extended JSON.

    :Parameters:
      - `json_options`: A :class:`JSONOptions` instance used to modify the
        decoding of MongoDB Extended JSON types. Defaults to
        :const:`DEFAULT_JSON_OPTIONS`.

    .. versionchanged:: 3.5
       Parses Relaxed and Canonical Extended JSON as well as PyMongo's legacy
       format. Now raises ``TypeError`` or ``ValueError`` when parsing JSON
       type wrappers with values of the wrong type or any extra keys.

    .. versionchanged:: 3.4
       Accepts optional parameter `json_options`. See :class:`JSONOptions`.
    """
    json_options = kwargs.pop("json_options", DEFAULT_JSON_OPTIONS)
    kwargs["object_pairs_hook"] = lambda pairs: object_pairs_hook(
        pairs, json_options)
    return json.loads(s, *args, **kwargs)


def object_pairs_hook(pairs, json_options=DEFAULT_JSON_OPTIONS):
    return object_hook_new(json_options.document_class(pairs), json_options)


def object_hook_new(dct, json_options=DEFAULT_JSON_OPTIONS):
    if "$date" in dct:
        return _parse_canonical_datetime_new(dct, json_options)
    else:
        return object_hook(dct, json_options=DEFAULT_JSON_OPTIONS)


def _parse_canonical_datetime_new(doc, json_options):
    """Decode a JSON datetime to python datetime.datetime."""
    dtm = doc["$date"]
    parse_date = parser.parse(dtm)

    dtm = datetime.datetime.strftime(parse_date, "%Y-%m-%dT%H:%M:%SZ")
    if len(doc) != 1:
        raise TypeError('Bad $date, extra field(s): %s' % (doc,))
    # mongoexport 2.6 and newer
    if isinstance(dtm, string_type):
        # Parse offset
        if dtm[-1] == 'Z':
            dt = dtm[:-1]
            offset = 'Z'
        elif dtm[-6] in ('+', '-') and dtm[-3] == ':':
            # (+|-)HH:MM
            dt = dtm[:-6]
            offset = dtm[-6:]
        elif dtm[-5] in ('+', '-'):
            # (+|-)HHMM
            dt = dtm[:-5]
            offset = dtm[-5:]
        elif dtm[-3] in ('+', '-'):
            # (+|-)HH
            dt = dtm[:-3]
            offset = dtm[-3:]
        else:
            dt = dtm
            offset = ''

        # Parse the optional factional seconds portion.
        dot_index = dt.rfind('.')
        microsecond = 0
        if dot_index != -1:
            microsecond = int(float(dt[dot_index:]) * 1000000)
            dt = dt[:dot_index]

        aware = datetime.datetime.strptime(
            dt, "%Y-%m-%dT%H:%M:%S").replace(microsecond=microsecond,
                                             tzinfo=utc)

        if offset and offset != 'Z':
            if len(offset) == 6:
                hours, minutes = offset[1:].split(':')
                secs = (int(hours) * 3600 + int(minutes) * 60)
            elif len(offset) == 5:
                secs = (int(offset[1:3]) * 3600 + int(offset[3:]) * 60)
            elif len(offset) == 3:
                secs = int(offset[1:3]) * 3600
            if offset[0] == "-":
                secs *= -1
            aware = aware - datetime.timedelta(seconds=secs)

        if json_options.tz_aware:
            if json_options.tzinfo:
                aware = aware.astimezone(json_options.tzinfo)
            return aware
        else:
            return aware.replace(tzinfo=None)
    return bson._millis_to_datetime(int(dtm), json_options)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值