def range_check_time(cls, hh=None, mm=None, ss=None, tz=None, rangedict=None): # Used for midnight and leap second handling midnight = False # Handle hh = '24' specially if rangedict is None: rangedict = cls.TIME_RANGE_DICT if "hh" in rangedict: try: hh = rangedict["hh"].rangefunc(hh, rangedict["hh"]) except HoursOutOfBoundsError as e: if float(hh) > 24 and float(hh) < 25: raise MidnightBoundsError( "Hour 24 may only represent midnight.") raise e if "mm" in rangedict: mm = rangedict["mm"].rangefunc(mm, rangedict["mm"]) if "ss" in rangedict: ss = rangedict["ss"].rangefunc(ss, rangedict["ss"]) if hh is not None and hh == 24: midnight = True # Handle midnight range if midnight is True and ((mm is not None and mm != 0) or (ss is not None and ss != 0)): raise MidnightBoundsError("Hour 24 may only represent midnight.") if cls.LEAP_SECONDS_SUPPORTED is True: if hh != 23 and mm != 59 and ss == 60: raise cls.TIME_SS_LIMIT.rangeexception( cls.TIME_SS_LIMIT.rangeerrorstring) else: if hh == 23 and mm == 59 and ss == 60: # https://bitbucket.org/nielsenb/aniso8601/issues/10/sub-microsecond-precision-in-durations-is raise LeapSecondError("Leap seconds are not supported.") if ss == 60: raise cls.TIME_SS_LIMIT.rangeexception( cls.TIME_SS_LIMIT.rangeerrorstring) return (hh, mm, ss, tz)
def _parse_minute_time(timestr): #Format must be hhmm, hhmm., hh:mm or hh:mm. if timestr.count(':') == 1: #hh:mm or hh:mm. timestrarray = timestr.split(':') isohour = int(timestrarray[0]) isominute = float(timestrarray[1]) #Minute may now be a fraction else: #hhmm or hhmm. isohour = int(timestr[0:2]) isominute = float(timestr[2:]) if isominute >= 60: raise MinutesOutOfBoundsError('Minutes must be less than 60.') if isohour == 24: if isominute != 0: raise MidnightBoundsError('Hour 24 may only represent midnight.') return datetime.time(hour=0, minute=0) #Since the time constructor doesn't handle fractional minutes, we put #the minutes in to a timedelta, and add it to the time before returning minutesdelta = datetime.timedelta(minutes=isominute) return _build_time(datetime.time(hour=isohour), minutesdelta)
def _parse_second_time(timestr): #Format must be hhmmss, hhmmss., hh:mm:ss or hh:mm:ss. if timestr.count(':') == 2: #hh:mm:ss or hh:mm:ss. timestrarray = timestr.split(':') isohour = int(timestrarray[0]) isominute = int(timestrarray[1]) #Since the time constructor doesn't handle fractional seconds, we put #the seconds in to a timedelta, and add it to the time before returning #The seconds value is truncated to microsecond resolution before #conversion: #https://bitbucket.org/nielsenb/aniso8601/issues/10/sub-microsecond-precision-in-durations-is secondsdelta = datetime.timedelta(seconds=float(timestrarray[2][:9])) else: #hhmmss or hhmmss. isohour = int(timestr[0:2]) isominute = int(timestr[2:4]) #Since the time constructor doesn't handle fractional seconds, we put #the seconds in to a timedelta, and add it to the time before returning #The seconds value is truncated to microsecond resolution before #conversion: #https://bitbucket.org/nielsenb/aniso8601/issues/10/sub-microsecond-precision-in-durations-is secondsdelta = datetime.timedelta(seconds=float(timestr[4:13])) if isohour == 23 and isominute == 59 and secondsdelta.seconds == 60: #https://bitbucket.org/nielsenb/aniso8601/issues/10/sub-microsecond-precision-in-durations-is raise LeapSecondError('Leap seconds are not supported.') elif secondsdelta.seconds >= 60: #https://bitbucket.org/nielsenb/aniso8601/issues/13/parsing-of-leap-second-gives-wildly raise SecondsOutOfBoundsError('Seconds must be less than 60.') if isominute >= 60: raise MinutesOutOfBoundsError('Minutes must be less than 60.') if isohour == 24: #Midnight, see 4.2.1, 4.2.3 if isominute != 0 or secondsdelta.total_seconds() != 0: raise MidnightBoundsError('Hour 24 may only represent midnight.') return datetime.time(hour=0, minute=0) return _build_time(datetime.time(hour=isohour, minute=isominute), secondsdelta)
def build_time(cls, hh=None, mm=None, ss=None, tz=None): # Builds a time from the given parts, handling fractional arguments # where necessary hours = 0 minutes = 0 seconds = 0 microseconds = 0 if hh is not None: if "." in hh: hours, remainingmicroseconds = cls._split_to_microseconds( hh, MICROSECONDS_PER_HOUR, "Invalid hour string.") microseconds += remainingmicroseconds else: hours = cls.cast(hh, int, thrownmessage="Invalid hour string.") if mm is not None: if "." in mm: minutes, remainingmicroseconds = cls._split_to_microseconds( mm, MICROSECONDS_PER_MINUTE, "Invalid minute string.") microseconds += remainingmicroseconds else: minutes = cls.cast(mm, int, thrownmessage="Invalid minute string.") if ss is not None: if "." in ss: seconds, remainingmicroseconds = cls._split_to_microseconds( ss, MICROSECONDS_PER_SECOND, "Invalid second string.") microseconds += remainingmicroseconds else: seconds = cls.cast(ss, int, thrownmessage="Invalid second string.") ( hours, minutes, seconds, microseconds, ) = PythonTimeBuilder._distribute_microseconds( microseconds, (hours, minutes, seconds), (MICROSECONDS_PER_HOUR, MICROSECONDS_PER_MINUTE, MICROSECONDS_PER_SECOND), ) # Range checks if hours == 23 and minutes == 59 and seconds == 60: # https://bitbucket.org/nielsenb/aniso8601/issues/10/sub-microsecond-precision-in-durations-is raise LeapSecondError("Leap seconds are not supported.") if hours == 24 and (minutes != 0 or seconds != 0): raise MidnightBoundsError("Hour 24 may only represent midnight.") if hours > 24: raise HoursOutOfBoundsError("Hour must be between 0..24 with " "24 representing midnight.") if minutes >= 60: raise MinutesOutOfBoundsError("Minutes must be less than 60.") if seconds >= 60: raise SecondsOutOfBoundsError("Seconds must be less than 60.") # Fix ranges that have passed range checks if hours == 24: hours = 0 minutes = 0 seconds = 0 # Datetimes don't handle fractional components, so we use a timedelta if tz is not None: return (datetime.datetime(1, 1, 1, hour=hours, minute=minutes, tzinfo=cls._build_object(tz)) + datetime.timedelta(seconds=seconds, microseconds=microseconds)).timetz() return (datetime.datetime(1, 1, 1, hour=hours, minute=minutes) + datetime.timedelta(seconds=seconds, microseconds=microseconds)).time()
def build_time(cls, hh=None, mm=None, ss=None, tz=None): # Builds a time from the given parts, handling fractional arguments # where necessary hours = 0 minutes = 0 seconds = 0 floathours = float(0) floatminutes = float(0) floatseconds = float(0) if hh is not None: if "." in hh: floathours = BaseTimeBuilder.cast( hh, float, thrownmessage="Invalid hour string.") hours = 0 else: hours = BaseTimeBuilder.cast( hh, int, thrownmessage="Invalid hour string.") if mm is not None: if "." in mm: floatminutes = BaseTimeBuilder.cast( mm, float, thrownmessage="Invalid minute string.") minutes = 0 else: minutes = BaseTimeBuilder.cast( mm, int, thrownmessage="Invalid minute string.") if ss is not None: if "." in ss: # Truncate to maximum supported precision floatseconds = BaseTimeBuilder.cast( ss[0:ss.index(".") + 7], float, thrownmessage="Invalid second string.", ) seconds = 0 else: seconds = BaseTimeBuilder.cast( ss, int, thrownmessage="Invalid second string.") # Range checks if (hours == 23 and floathours == 0 and minutes == 59 and floatminutes == 0 and seconds == 60 and floatseconds == 0): # https://bitbucket.org/nielsenb/aniso8601/issues/10/sub-microsecond-precision-in-durations-is raise LeapSecondError("Leap seconds are not supported.") if (hours == 24 and floathours == 0 and (minutes != 0 or floatminutes != 0 or seconds != 0 or floatseconds != 0)): raise MidnightBoundsError("Hour 24 may only represent midnight.") if hours > 24 or floathours > 24: raise HoursOutOfBoundsError("Hour must be between 0..24 with " "24 representing midnight.") if minutes >= 60 or floatminutes >= 60: raise MinutesOutOfBoundsError("Minutes must be less than 60.") if seconds >= 60 or floatseconds >= 60: raise SecondsOutOfBoundsError("Seconds must be less than 60.") # Fix ranges that have passed range checks if hours == 24: hours = 0 minutes = 0 seconds = 0 # Datetimes don't handle fractional components, so we use a timedelta if tz is not None: return (datetime.datetime( 1, 1, 1, hour=hours, minute=minutes, second=seconds, tzinfo=cls._build_object(tz), ) + datetime.timedelta(hours=floathours, minutes=floatminutes, seconds=floatseconds)).timetz() return (datetime.datetime( 1, 1, 1, hour=hours, minute=minutes, second=seconds) + datetime.timedelta(hours=floathours, minutes=floatminutes, seconds=floatseconds)).time()
def build_time(cls, hh=None, mm=None, ss=None, tz=None): #Builds a time from the given parts, handling fractional arguments #where necessary hours = 0 minutes = 0 seconds = 0 floathours = float(0) floatminutes = float(0) floatseconds = float(0) if hh is not None: if '.' in hh: hours, floathours = cls._split_and_cast( hh, 'Invalid hour string.') else: hours = cls.cast(hh, int, thrownmessage='Invalid hour string.') if mm is not None: if '.' in mm: minutes, floatminutes = cls._split_and_cast( mm, 'Invalid minute string.') else: minutes = cls.cast(mm, int, thrownmessage='Invalid minute string.') if ss is not None: if '.' in ss: seconds, floatseconds = cls._split_and_cast( ss, 'Invalid second string.') else: seconds = cls.cast(ss, int, thrownmessage='Invalid second string.') if floathours != 0: remainderhours, remainderminutes = cls._split_and_convert( floathours, 60) hours += remainderhours floatminutes += remainderminutes if floatminutes != 0: remainderminutes, remainderseconds = cls._split_and_convert( floatminutes, 60) minutes += remainderminutes floatseconds += remainderseconds if floatseconds != 0: totalseconds = float(seconds) + floatseconds #Truncate to maximum supported precision seconds = cls._truncate(totalseconds, 6) #Range checks if hours == 23 and minutes == 59 and seconds == 60: #https://bitbucket.org/nielsenb/aniso8601/issues/10/sub-microsecond-precision-in-durations-is raise LeapSecondError('Leap seconds are not supported.') if (hours == 24 and (minutes != 0 or seconds != 0)): raise MidnightBoundsError('Hour 24 may only represent midnight.') if hours > 24: raise HoursOutOfBoundsError('Hour must be between 0..24 with ' '24 representing midnight.') if minutes >= 60: raise MinutesOutOfBoundsError('Minutes must be less than 60.') if seconds >= 60: raise SecondsOutOfBoundsError('Seconds must be less than 60.') #Fix ranges that have passed range checks if hours == 24: hours = 0 minutes = 0 seconds = 0 #Datetimes don't handle fractional components, so we use a timedelta if tz is not None: return (datetime.datetime(1, 1, 1, hour=hours, minute=minutes, tzinfo=cls._build_object(tz)) + datetime.timedelta(seconds=seconds)).timetz() return (datetime.datetime(1, 1, 1, hour=hours, minute=minutes) + datetime.timedelta(seconds=seconds)).time()