How do I parse an ISO 8601-formatted date?

后端 未结 27 2399
小鲜肉
小鲜肉 2020-11-21 06:08

I need to parse RFC 3339 strings like \"2008-09-03T20:56:35.450686Z\" into Python\'s datetime type.

I have found strptime in the Python sta

27条回答
  •  遥遥无期
    2020-11-21 06:31

    Thanks to great Mark Amery's answer I devised function to account for all possible ISO formats of datetime:

    class FixedOffset(tzinfo):
        """Fixed offset in minutes: `time = utc_time + utc_offset`."""
        def __init__(self, offset):
            self.__offset = timedelta(minutes=offset)
            hours, minutes = divmod(offset, 60)
            #NOTE: the last part is to remind about deprecated POSIX GMT+h timezones
            #  that have the opposite sign in the name;
            #  the corresponding numeric value is not used e.g., no minutes
            self.__name = '<%+03d%02d>%+d' % (hours, minutes, -hours)
        def utcoffset(self, dt=None):
            return self.__offset
        def tzname(self, dt=None):
            return self.__name
        def dst(self, dt=None):
            return timedelta(0)
        def __repr__(self):
            return 'FixedOffset(%d)' % (self.utcoffset().total_seconds() / 60)
        def __getinitargs__(self):
            return (self.__offset.total_seconds()/60,)
    
    def parse_isoformat_datetime(isodatetime):
        try:
            return datetime.strptime(isodatetime, '%Y-%m-%dT%H:%M:%S.%f')
        except ValueError:
            pass
        try:
            return datetime.strptime(isodatetime, '%Y-%m-%dT%H:%M:%S')
        except ValueError:
            pass
        pat = r'(.*?[+-]\d{2}):(\d{2})'
        temp = re.sub(pat, r'\1\2', isodatetime)
        naive_date_str = temp[:-5]
        offset_str = temp[-5:]
        naive_dt = datetime.strptime(naive_date_str, '%Y-%m-%dT%H:%M:%S.%f')
        offset = int(offset_str[-4:-2])*60 + int(offset_str[-2:])
        if offset_str[0] == "-":
            offset = -offset
        return naive_dt.replace(tzinfo=FixedOffset(offset))
    

提交回复
热议问题