繁体   English   中英

将带季度的时间戳字符串解析为 Python 日期时间

[英]Parse Timestamp String with Quarter to Python datetime

我正在寻找一种将相当不寻常的时间戳字符串解析为 Python datetime时间 object 的方法。 这里的问题是,这个字符串包含相应的季度, datetime.strptime function 似乎不支持。 字符串的格式如下: YYYY/qq/mm/dd/HH/MM例如1970/Q1/01/01/00/00 我正在搜索 function,它允许我解析这种格式的字符串,包括有效性检查,如果季度对于日期是正确的。

问题:日期时间字符串与季度到 Python datetime时间

这实现了一个 OOP 解决方案,它使用指令扩展 Python datetime时间: %Q
可能的值: Q1|Q2|Q3|Q4 ,例如:

data_string = '1970/Q1/01/01/00/00'
#              '%Y/%Q/%m/%d/%H/%M'

注意:这取决于module _strptime class TimeRE ,如果内部实现发生变化,可能会失败!

from datetime import datetime

class Qdatetime(datetime):
    re_compile = None

    @classmethod        
    def _strptime(cls):
        import _strptime
        _class = _strptime.TimeRE

        if not 'strptime_compile' in _class.__dict__:
            setattr(_class, 'strptime_compile', getattr(_class, 'compile'))
            setattr(_class, 'compile', cls.compile)

    def compile(self, format):        
        import _strptime
        self = _strptime._TimeRE_cache

        # Add directive %Q
        if not 'Q' in self:
            self.update({'Q': r"(?P<Q>Q[1-4])"})

        Qdatetime.re_compile = self.strptime_compile(format)
        return Qdatetime.re_compile

    def validate(self, quarter):
        # 1970, 1, 1 is the lowest date used in timestamp
        month = [1, 4, 7, 10][quarter - 1]
        day = [31, 30, 30, 31][quarter - 1]
        q_start = datetime(self.year, month, 1).timestamp()
        q_end = datetime(self.year, month + 2, day).timestamp()
        dtt = self.timestamp()
        return dtt >= q_start and dtt<= q_end

    @property
    def quarter(self): return self._quarter
    @quarter.setter
    def quarter(self, data):
        found_dict = Qdatetime.re_compile.match(data).groupdict()
        self._quarter = int(found_dict['Q'][1])

    @property
    def datetime(self):
        return datetime(self.year, self.month, self.day,
                        hour=self.hour, minute=self.minute, second=self.second)

    def __str__(self):
        return 'Q{} {}'.format(self.quarter, super().__str__())

    @classmethod        
    def strptime(cls, data_string, _format):
        cls._strptime()

        dt = super().strptime(data_string, _format)
        dt.quarter = data_string

        if not dt.validate(dt.quarter):
            raise ValueError("time data '{}' does not match quarter 'Q{}'"\
                     .format(data_string, dt.quarter))
        return dt

用法

for data_string in ['1970/Q1/01/01/00/00', 
                    '1970/Q3/12/31/00/00',
                    '1970/Q2/05/05/00/00',
                    '1970/Q3/07/01/00/00',
                    '1970/Q4/12/31/00/00',
                   ]:
    try:
        d = Qdatetime.strptime(data_string, '%Y/%Q/%m/%d/%H/%M')
    except ValueError as e:
        print(e)
    else:
        print(d, d.datetime)

Output

 Q1 1970-01-01 00:00:00 1970-01-01 00:00:00 time data '1970/Q3/12/31/00/00' does not match quarter 'Q3' Q2 1970-05-05 00:00:00 1970-05-05 00:00:00 Q3 1970-07-01 00:00:00 1970-07-01 00:00:00 Q4 1970-12-31 00:00:00 1970-12-31 00:00:00

用 Python 测试:3.6 - 用 Python 3.8 源验证

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM