# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import datetime from pyasn1 import error from pyasn1.type import char from pyasn1.type import tag from pyasn1.type import univ __all__ = ['ObjectDescriptor', 'GeneralizedTime', 'UTCTime'] NoValue = univ.NoValue noValue = univ.noValue class ObjectDescriptor(char.GraphicString): __doc__ = char.GraphicString.__doc__ #: Default :py:class:`~pyasn1.type.tag.TagSet` object for |ASN.1| objects tagSet = char.GraphicString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 7) ) # Optimization for faster codec lookup typeId = char.GraphicString.getTypeId() class TimeMixIn(object): _yearsDigits = 4 _hasSubsecond = False _optionalMinutes = False _shortTZ = False class FixedOffset(datetime.tzinfo): """Fixed offset in minutes east from UTC.""" # defaulted arguments required # https: // docs.python.org / 2.3 / lib / datetime - tzinfo.html def __init__(self, offset=0, name='UTC'): self.__offset = datetime.timedelta(minutes=offset) self.__name = name def utcoffset(self, dt): return self.__offset def tzname(self, dt): return self.__name def dst(self, dt): return datetime.timedelta(0) UTC = FixedOffset() @property def asDateTime(self): """Create :py:class:`datetime.datetime` object from a |ASN.1| object. Returns ------- : new instance of :py:class:`datetime.datetime` object """ text = str(self) if text.endswith('Z'): tzinfo = TimeMixIn.UTC text = text[:-1] elif '-' in text or '+' in text: if '+' in text: text, plusminus, tz = text.partition('+') else: text, plusminus, tz = text.partition('-') if self._shortTZ and len(tz) == 2: tz += '00' if len(tz) != 4: raise error.PyAsn1Error('malformed time zone offset %s' % tz) try: minutes = int(tz[:2]) * 60 + int(tz[2:]) if plusminus == '-': minutes *= -1 except ValueError: raise error.PyAsn1Error('unknown time specification %s' % self) tzinfo = TimeMixIn.FixedOffset(minutes, '?') else: tzinfo = None if '.' in text or ',' in text: if '.' in text: text, _, ms = text.partition('.') else: text, _, ms = text.partition(',') try: ms = int(ms) * 1000 except ValueError: raise error.PyAsn1Error('bad sub-second time specification %s' % self) else: ms = 0 if self._optionalMinutes and len(text) - self._yearsDigits == 6: text += '0000' elif len(text) - self._yearsDigits == 8: text += '00' try: dt = datetime.datetime.strptime(text, self._yearsDigits == 4 and '%Y%m%d%H%M%S' or '%y%m%d%H%M%S') except ValueError: raise error.PyAsn1Error('malformed datetime format %s' % self) return dt.replace(microsecond=ms, tzinfo=tzinfo) @classmethod def fromDateTime(cls, dt): """Create |ASN.1| object from a :py:class:`datetime.datetime` object. Parameters ---------- dt: :py:class:`datetime.datetime` object The `datetime.datetime` object to initialize the |ASN.1| object from Returns ------- : new instance of |ASN.1| value """ text = dt.strftime(cls._yearsDigits == 4 and '%Y%m%d%H%M%S' or '%y%m%d%H%M%S') if cls._hasSubsecond: text += '.%d' % (dt.microsecond // 1000) if dt.utcoffset(): seconds = dt.utcoffset().seconds if seconds < 0: text += '-' else: text += '+' text += '%.2d%.2d' % (seconds // 3600, seconds % 3600) else: text += 'Z' return cls(text) class GeneralizedTime(char.VisibleString, TimeMixIn): __doc__ = char.VisibleString.__doc__ #: Default :py:class:`~pyasn1.type.tag.TagSet` object for |ASN.1| objects tagSet = char.VisibleString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 24) ) # Optimization for faster codec lookup typeId = char.VideotexString.getTypeId() _yearsDigits = 4 _hasSubsecond = True _optionalMinutes = True _shortTZ = True class UTCTime(char.VisibleString, TimeMixIn): __doc__ = char.VisibleString.__doc__ #: Default :py:class:`~pyasn1.type.tag.TagSet` object for |ASN.1| objects tagSet = char.VisibleString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 23) ) # Optimization for faster codec lookup typeId = char.VideotexString.getTypeId() _yearsDigits = 2 _hasSubsecond = False _optionalMinutes = False _shortTZ = False