我正在寻找一种将相当不寻常的时间戳字符串解析为Python datetime对象的方法。这里的问题是,此字符串包含相应的四分之一,而datetime.strptime函数似乎不支持该四分之一。字符串的格式如下:YYYY/qq/mm/dd/HH/MM例如1970/Q1/01/01/00/00。我正在寻找一个函数,该函数可以让我以这种格式解析字符串,包括有效性检查(如果季度对日期正确)。

最佳答案

问题:带Python的四分之一的日期时间字符串datetime


这实现了OOP解决方案,该解决方案使用指令datetime扩展了Python %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)



  输出:

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源验证

关于python - 将带有季度的时间戳字符串解析为Python日期时间,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58928739/

10-11 22:27
查看更多