Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/isodate/isotime.py: 25%

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

44 statements  

1############################################################################## 

2# Copyright 2009, Gerhard Weis 

3# All rights reserved. 

4# 

5# Redistribution and use in source and binary forms, with or without 

6# modification, are permitted provided that the following conditions are met: 

7# 

8# * Redistributions of source code must retain the above copyright notice, 

9# this list of conditions and the following disclaimer. 

10# * Redistributions in binary form must reproduce the above copyright notice, 

11# this list of conditions and the following disclaimer in the documentation 

12# and/or other materials provided with the distribution. 

13# * Neither the name of the authors nor the names of its contributors 

14# may be used to endorse or promote products derived from this software 

15# without specific prior written permission. 

16# 

17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 

18# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 

19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 

20# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 

21# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 

22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 

23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 

24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 

25# CONTRACT, STRICT LIABILITY, OR TORT 

26############################################################################## 

27''' 

28This modules provides a method to parse an ISO 8601:2004 time string to a 

29Python datetime.time instance. 

30 

31It supports all basic and extended formats including time zone specifications 

32as described in the ISO standard. 

33''' 

34import re 

35from decimal import Decimal 

36from datetime import time 

37 

38from isodate.isostrf import strftime, TIME_EXT_COMPLETE, TZ_EXT 

39from isodate.isoerror import ISO8601Error 

40from isodate.isotzinfo import TZ_REGEX, build_tzinfo 

41 

42TIME_REGEX_CACHE = [] 

43# used to cache regular expressions to parse ISO time strings. 

44 

45 

46def build_time_regexps(): 

47 ''' 

48 Build regular expressions to parse ISO time string. 

49 

50 The regular expressions are compiled and stored in TIME_REGEX_CACHE 

51 for later reuse. 

52 ''' 

53 if not TIME_REGEX_CACHE: 

54 # ISO 8601 time representations allow decimal fractions on least 

55 # significant time component. Command and Full Stop are both valid 

56 # fraction separators. 

57 # The letter 'T' is allowed as time designator in front of a time 

58 # expression. 

59 # Immediately after a time expression, a time zone definition is 

60 # allowed. 

61 # a TZ may be missing (local time), be a 'Z' for UTC or a string of 

62 # +-hh:mm where the ':mm' part can be skipped. 

63 # TZ information patterns: 

64 # '' 

65 # Z 

66 # +-hh:mm 

67 # +-hhmm 

68 # +-hh => 

69 # isotzinfo.TZ_REGEX 

70 # 1. complete time: 

71 # hh:mm:ss.ss ... extended format 

72 TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2}):" 

73 r"(?P<minute>[0-9]{2}):" 

74 r"(?P<second>[0-9]{2}" 

75 r"([,.][0-9]+)?)" + TZ_REGEX)) 

76 # hhmmss.ss ... basic format 

77 TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2})" 

78 r"(?P<minute>[0-9]{2})" 

79 r"(?P<second>[0-9]{2}" 

80 r"([,.][0-9]+)?)" + TZ_REGEX)) 

81 # 2. reduced accuracy: 

82 # hh:mm.mm ... extended format 

83 TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2}):" 

84 r"(?P<minute>[0-9]{2}" 

85 r"([,.][0-9]+)?)" + TZ_REGEX)) 

86 # hhmm.mm ... basic format 

87 TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2})" 

88 r"(?P<minute>[0-9]{2}" 

89 r"([,.][0-9]+)?)" + TZ_REGEX)) 

90 # hh.hh ... basic format 

91 TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2}" 

92 r"([,.][0-9]+)?)" + TZ_REGEX)) 

93 return TIME_REGEX_CACHE 

94 

95 

96def parse_time(timestring): 

97 ''' 

98 Parses ISO 8601 times into datetime.time objects. 

99 

100 Following ISO 8601 formats are supported: 

101 (as decimal separator a ',' or a '.' is allowed) 

102 hhmmss.ssTZD basic complete time 

103 hh:mm:ss.ssTZD extended compelte time 

104 hhmm.mmTZD basic reduced accuracy time 

105 hh:mm.mmTZD extended reduced accuracy time 

106 hh.hhTZD basic reduced accuracy time 

107 TZD is the time zone designator which can be in the following format: 

108 no designator indicates local time zone 

109 Z UTC 

110 +-hhmm basic hours and minutes 

111 +-hh:mm extended hours and minutes 

112 +-hh hours 

113 ''' 

114 isotimes = build_time_regexps() 

115 for pattern in isotimes: 

116 match = pattern.match(timestring) 

117 if match: 

118 groups = match.groupdict() 

119 for key, value in groups.items(): 

120 if value is not None: 

121 groups[key] = value.replace(',', '.') 

122 tzinfo = build_tzinfo(groups['tzname'], groups['tzsign'], 

123 int(groups['tzhour'] or 0), 

124 int(groups['tzmin'] or 0)) 

125 if 'second' in groups: 

126 # round to microseconds if fractional seconds are more precise 

127 second = Decimal(groups['second']).quantize(Decimal('.000001')) 

128 microsecond = (second - int(second)) * int(1e6) 

129 # int(...) ... no rounding 

130 # to_integral() ... rounding 

131 return time(int(groups['hour']), int(groups['minute']), 

132 int(second), int(microsecond.to_integral()), 

133 tzinfo) 

134 if 'minute' in groups: 

135 minute = Decimal(groups['minute']) 

136 second = (minute - int(minute)) * 60 

137 microsecond = (second - int(second)) * int(1e6) 

138 return time(int(groups['hour']), int(minute), int(second), 

139 int(microsecond.to_integral()), tzinfo) 

140 else: 

141 microsecond, second, minute = 0, 0, 0 

142 hour = Decimal(groups['hour']) 

143 minute = (hour - int(hour)) * 60 

144 second = (minute - int(minute)) * 60 

145 microsecond = (second - int(second)) * int(1e6) 

146 return time(int(hour), int(minute), int(second), 

147 int(microsecond.to_integral()), tzinfo) 

148 raise ISO8601Error('Unrecognised ISO 8601 time format: %r' % timestring) 

149 

150 

151def time_isoformat(ttime, format=TIME_EXT_COMPLETE + TZ_EXT): 

152 ''' 

153 Format time strings. 

154 

155 This method is just a wrapper around isodate.isostrf.strftime and uses 

156 Time-Extended-Complete with extended time zone as default format. 

157 ''' 

158 return strftime(ttime, format)