示例#1
0
    def testGetDateAndTimeFormatDictionary(self):
        formatDic = DateTimeUtil.getDateAndTimeFormatDictionary('DD/MM/YY HH:mm')

        self.assertEqual('DD/MM/YY', formatDic[DateTimeUtil.LONG_DATE_FORMAT_KEY])
        self.assertEqual('DD/MM', formatDic[DateTimeUtil.SHORT_DATE_FORMAT_KEY])
        self.assertEqual('HH:mm', formatDic[DateTimeUtil.TIME_FORMAT_KEY])

        formatDic = DateTimeUtil.getDateAndTimeFormatDictionary('YYYY.MM.DD HH.mm')

        self.assertEqual('YYYY.MM.DD', formatDic[DateTimeUtil.LONG_DATE_FORMAT_KEY])
        self.assertEqual('MM.DD', formatDic[DateTimeUtil.SHORT_DATE_FORMAT_KEY])
        self.assertEqual('HH.mm', formatDic[DateTimeUtil.TIME_FORMAT_KEY])

        formatDic = DateTimeUtil.getDateAndTimeFormatDictionary('YYYY.MM.DD HH-mm')

        self.assertEqual('YYYY.MM.DD', formatDic[DateTimeUtil.LONG_DATE_FORMAT_KEY])
        self.assertEqual('MM.DD', formatDic[DateTimeUtil.SHORT_DATE_FORMAT_KEY])
        self.assertEqual('HH-mm', formatDic[DateTimeUtil.TIME_FORMAT_KEY])

        formatDic = DateTimeUtil.getDateAndTimeFormatDictionary('MM-DD-YYYY HH.mm')

        self.assertEqual('MM-DD-YYYY', formatDic[DateTimeUtil.LONG_DATE_FORMAT_KEY])
        self.assertEqual('MM-DD', formatDic[DateTimeUtil.SHORT_DATE_FORMAT_KEY])
        self.assertEqual('HH.mm', formatDic[DateTimeUtil.TIME_FORMAT_KEY])
示例#2
0
    def _validateDateTimeData(self, localNow):
        '''
        Ensures that date/time info contained in the parsedParmData dic are valid and in
        a right format. If everything is ok, returns True.

        ['1', '10', '0', '2', '58'] #btc usd 1/10/0 2:58
        [None, None, None, '2', '57'] # btc usd 1 2:57
        ['11', '10', None, None, None] # neo btc 11/10
        :param localNow:
        :return: True if date/time values stored in the parsedParmData dic are valid. If an
                 error was detected, a new ResultData with a meaningfull error msg is
                 returned.
        '''

        dtFormatDic = DateTimeUtil.getDateAndTimeFormatDictionary(
            self.configManager.dateTimeFormat)

        dateShortFormat = dtFormatDic[DateTimeUtil.SHORT_DATE_FORMAT_KEY]
        dateLongFormat = dtFormatDic[DateTimeUtil.LONG_DATE_FORMAT_KEY]
        timeFormat = dtFormatDic[DateTimeUtil.TIME_FORMAT_KEY]

        resultData = True

        dayStr = self.parsedParmData[self.DAY]
        monthStr = self.parsedParmData[self.MONTH]
        yearStr = self.parsedParmData[self.YEAR]
        hourStr = self.parsedParmData[self.HOUR]
        minuteStr = self.parsedParmData[self.MINUTE]

        if (yearStr == '0' and monthStr == '0' and dayStr == '0'):
            # RT price asked
            return True
        else:
            # Here, the three date components are not all equal to 0 !
            if (yearStr == None and monthStr == None and dayStr == None
                    and hourStr != None and minuteStr != None):
                # Here, only time was specified in the full request, which is now possible.
                # Current day, month and year are fornatted into the parsed parm data
                # and True is returned
                self.parsedParmData[self.DAY] = localNow.format('DD')
                self.parsedParmData[self.MONTH] = localNow.format('MM')
                self.parsedParmData[self.YEAR] = localNow.format('YYYY')
                return True
            elif (yearStr == None and monthStr == None and dayStr != None
                  and hourStr != None and minuteStr != None):
                # Here, only day and time were specified in the full request, which is now possible.
                # Current month and year are fornatted into the parsed parm data
                # and True is returned
                self.parsedParmData[self.MONTH] = localNow.format('MM')
                self.parsedParmData[self.YEAR] = localNow.format('YYYY')
                return True
            elif (yearStr == '0' or
                  # yearStr is None when only day/month specified -> valid !
                  monthStr == '0' or monthStr == None or dayStr == '0'
                  or dayStr == None):
                # only when user enters -d0 for RT price,
                # is yearStr equal to '0' since 0 is put
                # by Requesèer into day, month and year !
                resultData = ResultData()
                resultData.setValue(ResultData.RESULT_KEY_ERROR_MSG,
                                    "ERROR - date not valid")
                return resultData
            elif len(monthStr) > 2:
                resultData = ResultData()
                resultData.setValue(
                    ResultData.RESULT_KEY_ERROR_MSG,
                    "ERROR - {} not conform to accepted month format (MM or M)"
                    .format(monthStr))
                return resultData
            elif yearStr != None:
                yearStrLen = len(yearStr)
                if yearStrLen != 2 and yearStrLen != 4:
                    resultData = ResultData()
                    resultData.setValue(
                        ResultData.RESULT_KEY_ERROR_MSG,
                        "ERROR - {} not conform to accepted year format (YYYY, YY or '')"
                        .format(yearStr))

                    # avoiding that invalid year will pollute next price requests
                    self.parsedParmData[self.YEAR] = None
                    return resultData

            # validating full date. Catch inval day or inval month,
            # like day == 123 or day == 32 or month == 31
            if yearStr == None:
                yearStr = str(localNow.year)

            if hourStr == None:
                hourStr = str(localNow.hour)

            if minuteStr == None:
                minuteStr = str(localNow.minute)

            dateTimeTupleList = [('day', dayStr, dateShortFormat),
                                 ('month', monthStr, dateShortFormat),
                                 ('year', yearStr, dateLongFormat),
                                 ('hour', hourStr, timeFormat),
                                 ('minute', minuteStr, timeFormat)]

            try:
                for name, value, format in dateTimeTupleList:
                    int(value)
            except ValueError as e:
                resultData = ResultData()
                resultData.setValue(
                    ResultData.RESULT_KEY_ERROR_MSG,
                    "ERROR - invalid value: {} violates format for {} ({})".
                    format(value, name, format))
                return resultData

            try:
                date = DateTimeUtil.dateTimeComponentsToArrowLocalDate(
                    int(dayStr), int(monthStr), int(yearStr), int(hourStr),
                    int(minuteStr), 0, self.configManager.localTimeZone)
            except ValueError as e:
                resultData = ResultData()
                resultData.setValue(ResultData.RESULT_KEY_ERROR_MSG,
                                    "ERROR - " + str(e))

        return resultData
示例#3
0
    def _parseAndFillCommandPrice(self, inputStr):
        '''
        This method try parsing a full or a partial request.

        :param inputStr:
        :seqdiag_return CommandPrice or CommandError
        :return: self.commandPrice or self.commandError or None, which will cause an error to be raised
        '''
        groupList = self._tryMatchFullPriceCommand(inputStr)

        requestType = None

        if groupList == (
        ):  #full command pattern not matched --> try match partial command pattern
            groupList = self._tryMatchPartialPriceCommand(inputStr)
            if groupList != ():
                # partial request entered. Here, parms are associated to parrm tag (i.e -c or -d).
                # Means they have been entered in any order and are all optional ensuring
                # command price temporary data like unsupported command data from previous
                # request are purged. Necessary here when handling partial command(s) since, unlike
                # when a full command is processed, the command price is not reinitialized !
                requestType = REQUEST_TYPE_PARTIAL
                self.commandPrice.resetTemporaryData()

                keys = self.inputParmParmDataDicKeyDic.keys()
                it = iter(groupList)

                for command in it:
                    value = next(it)
                    if value != None:
                        commandUpper = command.upper()
                        if commandUpper in keys:
                            self.commandPrice.parsedParmData[
                                self.inputParmParmDataDicKeyDic[
                                    commandUpper]] = value
                        else:
                            # unknown partial command symbol
                            self.commandPrice.parsedParmData[
                                self.commandPrice.
                                UNSUPPORTED_COMMAND] = command
                            self.commandPrice.parsedParmData[
                                self.commandPrice.
                                UNSUPPORTED_COMMAND_DATA] = value

                if self.commandPrice.parsedParmData[
                        CommandPrice.DAY_MONTH_YEAR] == '0':
                    #-d0 which means RT entered. In this case, the previous
                    #date/time info are no longer relevant !
                    self.commandPrice.parsedParmData[
                        CommandPrice.PRICE_TYPE] = CommandPrice.PRICE_TYPE_RT
                    hourMinute, dayMonthYear = self._wipeOutDateTimeInfoFromCommandPrice(
                    )
                elif self.commandPrice.parsedParmData[
                        CommandPrice.
                        DAY_MONTH_YEAR] == None and self.commandPrice.parsedParmData[
                            CommandPrice.HOUR_MINUTE] == None:
                    #here, partial command(s) which aren't date/time related were entered: the previous request price type must be considered !
                    if self.commandPrice.parsedParmData[
                            CommandPrice.
                            PRICE_TYPE] == CommandPrice.PRICE_TYPE_RT:
                        hourMinute, dayMonthYear = self._wipeOutDateTimeInfoFromCommandPrice(
                        )
                    else:
                        #here, since previous request was not RT, hourMinute and dayRonthYear must be rebuilt
                        #from the date/time values of the previous request. Don't forget that OAY_MONTH_YEAR
                        #and HOUR_MINUTE are set to None once date/time values have been acquired !
                        if self._isMinimalDateTimeInfoFromPreviousRequestAvailable(
                        ):
                            dayMonthYear, hourMinute = self._rebuildPreviousRequestDateTimeValues(
                            )
                        else:
                            return None  # will cause an error. This occurs in a special situation when the previous request
                            # was in error, which explains why the date/time info from previous request is
                            # incoherent. Such a case is tested by TestController.
                            # testControllerHistoDayPriceIncompleteCommandScenario
                else:
                    hourMinute = self.commandPrice.parsedParmData[
                        CommandPrice.HOUR_MINUTE]
                    dayMonthYear = self.commandPrice.parsedParmData[
                        CommandPrice.DAY_MONTH_YEAR]

            else:  #neither full nor parrial pattern matched
                return None  # will cause an error.
        else:  #full request entered. Here, parms were entered in an order reflected in the
            # pattern: crypto fiat in this mandatory order, then date time exchange, of which order
            # can be different.
            requestType = REQUEST_TYPE_FULL
            self.commandPrice.initialiseParsedParmData()
            self.commandPrice.parsedParmData[CommandPrice.CRYPTO] = groupList[
                0]  #mandatory crrypto parm, its order is fixed
            self.commandPrice.parsedParmData[CommandPrice.FIAT] = groupList[
                1]  #mandatory fiat parm, its order is fixed
            optionalParsedParmDataDic = self._buildFullCommandPriceOptionalParmsDic(
                groupList[2:])

            if optionalParsedParmDataDic != None:
                self.commandPrice.parsedParmData.update(
                    optionalParsedParmDataDic)
            else:
                # invalid full command format
                self.commandError.parsedParmData[
                    self.commandError.
                    COMMAND_ERROR_TYPE_KEY] = self.commandError.COMMAND_ERROR_TYPE_FULL_REQUEST

                return self.commandError

            hourMinute = self.commandPrice.parsedParmData[
                CommandPrice.HOUR_MINUTE]
            dayMonthYear = self.commandPrice.parsedParmData[
                CommandPrice.DAY_MONTH_YEAR]

        if hourMinute != None:
            hourMinuteList = hourMinute.split(':')
            if len(hourMinuteList) == 1:
                #supplied time is invalid: does not respect expected format of 0:10 or 12:01 etc
                # invalid time partial command format
                invalidPartialCommand, invalidValue = self._wholeParmAndInvalidValue(
                    '-t', inputStr)
                dtFormatDic = DateTimeUtil.getDateAndTimeFormatDictionary(
                    self.configMgr.dateTimeFormat)
                timeFormat = dtFormatDic[DateTimeUtil.TIME_FORMAT_KEY]
                self.commandError.parsedParmData[
                    self.commandError.
                    COMMAND_ERROR_TYPE_KEY] = self.commandError.COMMAND_ERROR_TYPE_PARTIAL_REQUEST
                self.commandError.parsedParmData[
                    self.commandError.
                    COMMAND_ERROR_MSG_KEY] = self.commandError.PARTIAL_PRICE_COMMAND_TIME_FORMAT_INVALID_MSG.format(
                        invalidPartialCommand, invalidValue, timeFormat)

                # remove invalid time specification form parsedParData to avoid polluting next partial
                # request !
                self.commandPrice.parsedParmData[
                    CommandPrice.HOUR_MINUTE] = None

                return self.commandError
            else:
                minute = hourMinuteList[1]
                hour = hourMinuteList[
                    0]  #in both cases, first item in hourMinuteList is hour
        else:
            hour = self.commandPrice.parsedParmData[CommandPrice.HOUR]
            minute = self.commandPrice.parsedParmData[CommandPrice.MINUTE]

        self._fillHourMinuteInfo(hour, minute)

        if dayMonthYear != None:
            if dayMonthYear == '0':
                day = '0'
                month = '0'
                year = '0'
                self.commandPrice.parsedParmData[
                    CommandPrice.PRICE_TYPE] = CommandPrice.PRICE_TYPE_RT
            else:
                dayMonthYearList = dayMonthYear.split('/')
                if len(
                        dayMonthYearList
                ) == 1:  #only day specified, the case for -d12 for example (12th of current month)
                    day = dayMonthYearList[0]
                    if CommandPrice.DAY in self.commandPrice.parsedParmData:
                        month = self.commandPrice.parsedParmData[
                            CommandPrice.MONTH]
                        year = self.commandPrice.parsedParmData[
                            CommandPrice.YEAR]
                    else:
                        month = None
                        year = None
                    self.commandPrice.parsedParmData[
                        CommandPrice.
                        PRICE_TYPE] = CommandPrice.PRICE_TYPE_HISTO
                elif len(dayMonthYearList) == 2:
                    day = dayMonthYearList[0]
                    month = dayMonthYearList[1]
                    if CommandPrice.YEAR in self.commandPrice.parsedParmData:
                        year = self.commandPrice.parsedParmData[
                            CommandPrice.YEAR]
                    else:  # year not provided and not obtained from previous full price command input.
                        # Will be set by PriceRequester which knows in which timezone we are
                        year = None
                    self.commandPrice.parsedParmData[
                        CommandPrice.
                        PRICE_TYPE] = CommandPrice.PRICE_TYPE_HISTO
                elif len(dayMonthYearList) == 3:
                    day = dayMonthYearList[0]
                    month = dayMonthYearList[1]
                    year = dayMonthYearList[2]
                    self.commandPrice.parsedParmData[
                        CommandPrice.
                        PRICE_TYPE] = CommandPrice.PRICE_TYPE_HISTO
                else:  #invalid date format here !
                    if CommandPrice.DAY in self.commandPrice.parsedParmData:
                        day = self.commandPrice.parsedParmData[
                            CommandPrice.DAY]
                        month = self.commandPrice.parsedParmData[
                            CommandPrice.MONTH]
                        year = self.commandPrice.parsedParmData[
                            CommandPrice.YEAR]
                    else:
                        day = None
                        month = None
                        year = None
        else:
            if CommandPrice.DAY in self.commandPrice.parsedParmData:
                day = self.commandPrice.parsedParmData[CommandPrice.DAY]
                month = self.commandPrice.parsedParmData[CommandPrice.MONTH]
                year = self.commandPrice.parsedParmData[CommandPrice.YEAR]

                if day == '0' and month == '0' and year == '0':
                    self.commandPrice.parsedParmData[
                        CommandPrice.PRICE_TYPE] = CommandPrice.PRICE_TYPE_RT
                else:
                    self.commandPrice.parsedParmData[
                        CommandPrice.
                        PRICE_TYPE] = CommandPrice.PRICE_TYPE_HISTO
            else:
                day = None
                month = None
                year = None

        self._fillDayMonthYearInfo(day, month, year)

        priceValueData = self.commandPrice.parsedParmData[
            CommandPrice.PRICE_VALUE_DATA]

        if priceValueData != None:
            return self._fillPriceValueInfo(priceValueData, requestType)
        else:
            #no partial command -v specified here !
            return self.commandPrice