comparison env/lib/python3.7/site-packages/isodate/isotime.py @ 0:26e78fe6e8c4 draft

"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
author shellac
date Sat, 02 May 2020 07:14:21 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:26e78fe6e8c4
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 '''
28 This modules provides a method to parse an ISO 8601:2004 time string to a
29 Python datetime.time instance.
30
31 It supports all basic and extended formats including time zone specifications
32 as described in the ISO standard.
33 '''
34 import re
35 from decimal import Decimal
36 from datetime import time
37
38 from isodate.isostrf import strftime, TIME_EXT_COMPLETE, TZ_EXT
39 from isodate.isoerror import ISO8601Error
40 from isodate.isotzinfo import TZ_REGEX, build_tzinfo
41
42 TIME_REGEX_CACHE = []
43 # used to cache regular expressions to parse ISO time strings.
44
45
46 def 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
96 def 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
151 def 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)