Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pyasn1/type/useful.py: 46%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

98 statements  

1# 

2# This file is part of pyasn1 software. 

3# 

4# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com> 

5# License: https://pyasn1.readthedocs.io/en/latest/license.html 

6# 

7import datetime 

8 

9from pyasn1 import error 

10from pyasn1.type import char 

11from pyasn1.type import tag 

12from pyasn1.type import univ 

13 

14__all__ = ['ObjectDescriptor', 'GeneralizedTime', 'UTCTime'] 

15 

16NoValue = univ.NoValue 

17noValue = univ.noValue 

18 

19 

20class ObjectDescriptor(char.GraphicString): 

21 __doc__ = char.GraphicString.__doc__ 

22 

23 #: Default :py:class:`~pyasn1.type.tag.TagSet` object for |ASN.1| objects 

24 tagSet = char.GraphicString.tagSet.tagImplicitly( 

25 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 7) 

26 ) 

27 

28 # Optimization for faster codec lookup 

29 typeId = char.GraphicString.getTypeId() 

30 

31 

32class TimeMixIn(object): 

33 

34 _yearsDigits = 4 

35 _hasSubsecond = False 

36 _optionalMinutes = False 

37 _shortTZ = False 

38 

39 class FixedOffset(datetime.tzinfo): 

40 """Fixed offset in minutes east from UTC.""" 

41 

42 # defaulted arguments required 

43 # https: // docs.python.org / 2.3 / lib / datetime - tzinfo.html 

44 def __init__(self, offset=0, name='UTC'): 

45 self.__offset = datetime.timedelta(minutes=offset) 

46 self.__name = name 

47 

48 def utcoffset(self, dt): 

49 return self.__offset 

50 

51 def tzname(self, dt): 

52 return self.__name 

53 

54 def dst(self, dt): 

55 return datetime.timedelta(0) 

56 

57 UTC = FixedOffset() 

58 

59 @property 

60 def asDateTime(self): 

61 """Create :py:class:`datetime.datetime` object from a |ASN.1| object. 

62 

63 Returns 

64 ------- 

65 : 

66 new instance of :py:class:`datetime.datetime` object 

67 """ 

68 text = str(self) 

69 if text.endswith('Z'): 

70 tzinfo = TimeMixIn.UTC 

71 text = text[:-1] 

72 

73 elif '-' in text or '+' in text: 

74 if '+' in text: 

75 text, plusminus, tz = text.partition('+') 

76 else: 

77 text, plusminus, tz = text.partition('-') 

78 

79 if self._shortTZ and len(tz) == 2: 

80 tz += '00' 

81 

82 if len(tz) != 4: 

83 raise error.PyAsn1Error('malformed time zone offset %s' % tz) 

84 

85 try: 

86 minutes = int(tz[:2]) * 60 + int(tz[2:]) 

87 if plusminus == '-': 

88 minutes *= -1 

89 

90 except ValueError: 

91 raise error.PyAsn1Error('unknown time specification %s' % self) 

92 

93 tzinfo = TimeMixIn.FixedOffset(minutes, '?') 

94 

95 else: 

96 tzinfo = None 

97 

98 if '.' in text or ',' in text: 

99 if '.' in text: 

100 text, _, ms = text.partition('.') 

101 else: 

102 text, _, ms = text.partition(',') 

103 

104 try: 

105 # Normalize variable-length fraction to microseconds 

106 ms = int(ms.ljust(6, '0')[:6]) 

107 

108 except ValueError: 

109 raise error.PyAsn1Error('bad sub-second time specification %s' % self) 

110 

111 else: 

112 ms = 0 

113 

114 if self._optionalMinutes and len(text) - self._yearsDigits == 6: 

115 text += '0000' 

116 elif len(text) - self._yearsDigits == 8: 

117 text += '00' 

118 

119 try: 

120 dt = datetime.datetime.strptime(text, self._yearsDigits == 4 and '%Y%m%d%H%M%S' or '%y%m%d%H%M%S') 

121 

122 except ValueError: 

123 raise error.PyAsn1Error('malformed datetime format %s' % self) 

124 

125 return dt.replace(microsecond=ms, tzinfo=tzinfo) 

126 

127 @classmethod 

128 def fromDateTime(cls, dt): 

129 """Create |ASN.1| object from a :py:class:`datetime.datetime` object. 

130 

131 Parameters 

132 ---------- 

133 dt: :py:class:`datetime.datetime` object 

134 The `datetime.datetime` object to initialize the |ASN.1| object 

135 from 

136 

137 Returns 

138 ------- 

139 : 

140 new instance of |ASN.1| value 

141 """ 

142 text = dt.strftime(cls._yearsDigits == 4 and '%Y%m%d%H%M%S' or '%y%m%d%H%M%S') 

143 if cls._hasSubsecond and dt.microsecond: 

144 text += ('.%06d' % dt.microsecond).rstrip('0') 

145 

146 if dt.utcoffset(): 

147 seconds = dt.utcoffset().seconds 

148 if seconds < 0: 

149 text += '-' 

150 else: 

151 text += '+' 

152 text += '%.2d%.2d' % (seconds // 3600, seconds % 3600) 

153 else: 

154 text += 'Z' 

155 

156 return cls(text) 

157 

158 

159class GeneralizedTime(char.VisibleString, TimeMixIn): 

160 __doc__ = char.VisibleString.__doc__ 

161 

162 #: Default :py:class:`~pyasn1.type.tag.TagSet` object for |ASN.1| objects 

163 tagSet = char.VisibleString.tagSet.tagImplicitly( 

164 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 24) 

165 ) 

166 

167 # Optimization for faster codec lookup 

168 typeId = char.VideotexString.getTypeId() 

169 

170 _yearsDigits = 4 

171 _hasSubsecond = True 

172 _optionalMinutes = True 

173 _shortTZ = True 

174 

175 

176class UTCTime(char.VisibleString, TimeMixIn): 

177 __doc__ = char.VisibleString.__doc__ 

178 

179 #: Default :py:class:`~pyasn1.type.tag.TagSet` object for |ASN.1| objects 

180 tagSet = char.VisibleString.tagSet.tagImplicitly( 

181 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 23) 

182 ) 

183 

184 # Optimization for faster codec lookup 

185 typeId = char.VideotexString.getTypeId() 

186 

187 _yearsDigits = 2 

188 _hasSubsecond = False 

189 _optionalMinutes = False 

190 _shortTZ = False