在yaml中创建datetime.time()对象?

时间:2015-08-25 20:10:43

标签: python yaml

我知道我可以创建一个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()对象开始?

1 个答案:

答案 0 :(得分:1)

您可以修补SafeLoader以进行出价,但制作与SafeLoader使用的safe_load()相同的新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识别器识别的时间。你也可以识别出sexagesimal本身,但根据我的经验,这实现起来会更复杂。

存在其他替代方案,包括通过明确标记标记来创建datetime.time对象,以提供加载(和可能的保存)例程。