将带有四分之一的时间戳字符串解析为Python日期时间

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

hahaquanquan 回答:将带有四分之一的时间戳字符串解析为Python日期时间

  

问题:带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,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源进行验证

本文链接:https://www.f2er.com/3075561.html

大家都在问