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
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
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.
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
38from isodate.isostrf import strftime, TIME_EXT_COMPLETE, TZ_EXT
39from isodate.isoerror import ISO8601Error
40from isodate.isotzinfo import TZ_REGEX, build_tzinfo
42TIME_REGEX_CACHE = []
43# used to cache regular expressions to parse ISO time strings.
46def build_time_regexps():
47 '''
48 Build regular expressions to parse ISO time string.
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
96def parse_time(timestring):
97 '''
98 Parses ISO 8601 times into datetime.time objects.
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)
151def time_isoformat(ttime, format=TIME_EXT_COMPLETE + TZ_EXT):
152 '''
153 Format time strings.
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)