File: //lib/python3/dist-packages/pyasn1/type/useful.py
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import datetime
from pyasn1 import error
from pyasn1.compat import dateandtime
from pyasn1.compat import string
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 = string.partition(text, '+')
            else:
                text, plusminus, tz = string.partition(text, '-')
            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 = string.partition(text, '.')
            else:
                text, _, ms = string.partition(text, ',')
            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 = dateandtime.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