【问题标题】:Create datetime.time() object in yaml?在 yaml 中创建 datetime.time() 对象?
【发布时间】:2015-11-19 16:46:56
【问题描述】:

我知道我可以创建一个datetime.datetime 对象,然后使用.time() 方法,像这样:

my_file.yaml

MyDateTime: 2015-08-11 10:08:37

然后:

In [58]: f = open("my_file.yaml", "rU")

In [59]: temp = yaml.safe_load(f)

In [60]: f.close()

In [61]: temp['MyDateTime'].time()
Out[61]: datetime.time(10, 8, 37)

但这似乎有点多余,有没有办法创建datetime.time() 对象?

【问题讨论】:

标签: python yaml


【解决方案1】:

您可以修补 SafeLoader 以进行投标,但最好制作一个与 safe_load() 使用的 SafeLoader 相同的新 Loader。 您唯一需要提供的是一个在时间戳标量匹配时调用的方法 (construct_yaml_time()),并通过调用 add_constructor 指定它。

import ruamel.yaml as yaml

from ruamel.yaml.loader import Reader, Scanner, Composer, SafeConstructor, \
     Resolver, Parser

class TimeConstructor(SafeConstructor):
    def __init__(self):
        SafeConstructor.__init__(self)

    def construct_yaml_time(self, node):
        x = SafeConstructor.construct_yaml_timestamp(self, node)
        return x.time()


TimeConstructor.add_constructor(
    u'tag:yaml.org,2002:timestamp',
    TimeConstructor.construct_yaml_time)

class TimeLoader(Reader, Scanner, Parser, Composer, TimeConstructor, Resolver):
    def __init__(self, stream):
        Reader.__init__(self, stream)
        Scanner.__init__(self)
        Parser.__init__(self)
        Composer.__init__(self)
        TimeConstructor.__init__(self)
        Resolver.__init__(self)

yaml_str = """\
MyDateTime: 2015-08-11 10:08:37
x: 23423
"""

data = yaml.load(yaml_str, Loader=TimeLoader)
print data

给你:

<type 'datetime.time'>
{'x': 23423, 'MyDateTime': datetime.time(10, 8, 37)}

您也可以将时间对象指定为10:08:37,但这会将它们加载为六十进制数字,并将它们转换为整数(在本例中为 36517)。当然,您也可以更改此行为:

import ruamel.yaml as yaml

from ruamel.yaml.loader import Reader, Scanner, Composer, SafeConstructor, \
     Resolver, Parser

import datetime

class TimeConstructor(SafeConstructor):
    def __init__(self):
        SafeConstructor.__init__(self)

    def construct_yaml_time(self, node):
        value = self.construct_scalar(node)
        if ':' not in value:
            return SafeConstructor.construct_yaml_int(self, node)
        return datetime.time(*[int(x) for x in value.split(':')])



TimeConstructor.add_constructor(
    u'tag:yaml.org,2002:int',
    TimeConstructor.construct_yaml_time)

class TimeLoader(Reader, Scanner, Parser, Composer, TimeConstructor, Resolver):
    def __init__(self, stream):
        Reader.__init__(self, stream)
        Scanner.__init__(self)
        Parser.__init__(self)
        Composer.__init__(self)
        TimeConstructor.__init__(self)
        Resolver.__init__(self)

yaml_str = """\
MyDateTime: 10:08:37
x: 12345
"""

data = yaml.load(yaml_str, Loader=TimeLoader)
print data

给出:

{'x': 12345, 'MyDateTime': datetime.time(10, 8, 37)}

这取决于普通int 识别器识别的时间。您也可以识别六十进制本身,但根据我的经验,这实现起来更复杂。


存在其他替代方法,包括通过显式标记datetime.time 对象提供加载(和可能的保存)例程。

【讨论】:

  • 我犯了同样的错误。他问的是获取datetime.time 对象,而不是datetime.datetime 对象。幸运的是,这个问题原来是一个骗子,有一个很好的答案@@stackoverflow.com/questions/26744956/…
  • @larsks 谢谢,我不应该在漫长的一天工作后尝试在深夜回答问题
  • 谢谢,鉴于您的回答和 larsks 所链接的问题,似乎没有简单的方法可以做到这一点。
  • @Akavall 不,没有,我提供了一个替代方案,它允许您在没有前一个日期的情况下编写时间,但是没有对时间对象的内置支持,就像对日期时间戳和时间一样持续时间(六十进制)。
  • 感谢您的帮助!
猜你喜欢
  • 2018-05-25
  • 1970-01-01
  • 2018-08-08
  • 1970-01-01
  • 2022-11-21
  • 2017-07-24
  • 2019-10-02
  • 1970-01-01
相关资源
最近更新 更多