如何将描述时间的字符串转换为秒?

How to convert a string describing time into seconds?

我正在尝试创建一个函数将时间字符串(来自用户)转换为秒数。

我想做的是让用户以字符串形式输入时间,例如:

"one hour and forty five minutes" 

然后将其分解为秒。所以上面的输出将是

6300 seconds

这不是一件容易的事,没有特定的方法可以做到,或者我不知道。但我分享了一段代码,可以给你一个想法。 首先,您需要读取输入字符串并拆分它。拆分数据时,您应该搜索关键字符串,例如“小时”或“分钟”。在此之后,您需要获取此值并在您已经定义数字字符串版本的数据集中搜索。然后,你需要定义一些规则,例如(四十,五十,它们都以ty结尾,你可以在字符串中搜索这些东西。)

但是,用户可以输入的可能性是无限的,因此您应该定义限制。我刚刚分享了我对如何解决此类问题的看法,但我可能会漏掉一些要点。

def convertSeconds(n_hours,n_minutes):
        return n_hours * 3600 + n_minutes *60
    
    dataSet = {
        "one": 1,
        "two": 2,
        "three": 3,
        "four": 4,
        "five": 5,
        "six": 6,
        "seven":7,
        "eight":8,
        "nine":9,
        "hundred":100,
        "hundreds":100,
        "thousand" : 1000,
        "millions" : 1000000
        #etc...
    }
    
    time = input('Please Enter Date As String : ')
    word_array = time.split()
    idx = 0
    idx_hour = 0
    for word in word_array:
        if word == "hour":
            n_hours = word_array[0:idx]
            idx_hour = idx
        if word == "hours":
            n_hours = word_array[0:idx]
            idx_hour = idx
        if word == "and":
            idx_hour = idx_hour +1
        if word == "minute":
            n_minutes = word_array[idx_hour+1:idx]
        if word == "minutes":
            n_minutes = word_array[idx_hour+1:idx]
        idx = idx + 1
    total_hours = 0
    total_minutes = 0
    for counter in range(len(n_hours)):
        value = dataSet[n_hours[counter]]
        if n_hours[counter] == "hundreds" or n_hours[counter] == "hundred":
                 value = dataSet[n_hours[counter-1]] * 100
                 total_hours = total_hours - dataSet[n_hours[counter-1]]
        total_hours = total_hours + value
    
    
    for counter in range(len(n_minutes)):
        value = dataSet[n_minutes[counter]]
        total_minutes = total_minutes + value
    
    print("Your Time in Seconds : ",convertSeconds(total_hours,total_minutes))

Please Enter Date As String : two hundred hours and five minutes
Your Time in Seconds :  720300

parsedatetime 库可以完成一些工作。

from parsedatetime import Calendar, Constants

c = Calendar(Constants(usePyICU=False))
c.parse("1 minute and 3 hours")

将 return 一个时间结构,不幸的是包含了整个日期。如果您输入超过 24 小时,将尝试重新计算日期。 并且,数字必须以数字而不是单词的形式呈现,但您可以使用 replace() 提前格式化您的字符串。

一旦你有了一个时间结构,你可以使用time.mktime()将它转换成Unix以来的秒数,然后你可以减去当前时间的秒数,或者更安全,在[=13中输入开始日期=] 方法并减去它。

这是不完美的,但我使用 dateutil.parser.parser.parse()parsedatetime.Calendar.parse() 的组合从用户那里获得 datetime.datetime()。如果 dateutil 失败,那么我会尝试 parsedatetime。用户了解如何输入日期和时间以正确识别它们。

你可以用很长的数字字典来做到这一点:

def parse_int(string):
    numbers = {'zero': 0,
               'one': 1,
               'two': 2,
               'three': 3,
               'four': 4,
               'five': 5,
               'six': 6,
               'seven': 7,
               'eight': 8,
               'nine': 9,
               'ten': 10,
               'eleven': 11,
               'twelve': 12,
               'thirteen': 13,
               'fourteen': 14,
               'fifteen': 15,
               'sixteen': 16,
               'seventeen': 17,
               'eighteen': 18,
               'nineteen': 19,
               'twenty': 20,
               'twenty-one': 21,
               'twenty-two': 22,
               'twenty-three': 23,
               'twenty-four': 24,
               'twenty-five': 25,
               'twenty-six': 26,
               'twenty-seven': 27,
               'twenty-eight': 28,
               'twenty-nine': 29,
               'thirty': 30,
               'thirty-one': 31,
               'thirty-two': 32,
               'thirty-three': 33,
               'thirty-four': 34,
               'thirty-five': 35,
               'thirty-six': 36,
               'thirty-seven': 37,
               'thirty-eight': 38,
               'thirty-nine': 39,
               'forty': 40,
               'forty-one': 41,
               'forty-two': 42,
               'forty-three': 43,
               'forty-four': 44,
               'forty-five': 45,
               'forty-six': 46,
               'forty-seven': 47,
               'forty-eight': 48,
               'forty-nine': 49,
               'fifty': 50,
               'fifty-one': 51,
               'fifty-two': 52,
               'fifty-three': 53,
               'fifty-four': 54,
               'fifty-five': 55,
               'fifty-six': 56,
               'fifty-seven': 57,
               'fifty-eight': 58,
               'fifty-nine': 59,
               'sixty': 60,
               'sixty-one': 61,
               'sixty-two': 62,
               'sixty-three': 63,
               'sixty-four': 64,
               'sixty-five': 65,
               'sixty-six': 66,
               'sixty-seven': 67,
               'sixty-eight': 68,
               'sixty-nine': 69,
               'seventy': 70,
               'seventy-one': 71,
               'seventy-two': 72,
               'seventy-three': 73,
               'seventy-four': 74,
               'seventy-five': 75,
               'seventy-six': 76,
               'seventy-seven': 77,
               'seventy-eight': 78,
               'seventy-nine': 79,
               'eighty': 80,
               'eighty-one': 81,
               'eighty-two': 82,
               'eighty-three': 83,
               'eighty-four': 84,
               'eighty-five': 85,
               'eighty-six': 86,
               'eighty-seven': 87,
               'eighty-eight': 88,
               'eighty-nine': 89,
               'ninety': 90,
               'ninety-one': 91,
               'ninety-two': 92,
               'ninety-three': 93,
               'ninety-four': 94,
               'ninety-five': 95,
               'ninety-six': 96,
               'ninety-seven': 97,
               'ninety-eight': 98,
               'ninety-nine': 99}
    powers = {'hundred': 10 ** 2,
              'thousand': 10 ** 3,
              'million': 10 ** 6,
              'billion': 10 ** 9,
              'quadrillion': 10 ** 15,
              'quintillion': 10 ** 18,
              'sextillion': 10 ** 21,
              'septillion': 10 ** 24,
              'octillion': 10 ** 27,
              'nonillion': 10 ** 30,
              'decillion': 10 ** 33,
              'undecillion': 10 ** 36,
              'duodecillion': 10 ** 39,
              'tredecillion': 10 ** 42,
              'quattuordecillion': 10 ** 45,
              'quindecillion': 10 ** 48,
              'sexdecillion': 10 ** 51,
              'septemdecillion': 10 ** 54,
              'octodecillion': 10 ** 57,
              'novemdecillion': 10 ** 60,
              'vigintillion': 10 ** 63,
              'vigintunillion': 10 ** 66,
              'unvigintillion': 10 ** 66,
              'duovigintillion': 10 ** 69,
              'vigintiduoillion': 10 ** 69,
              'vigintitrillion': 10 ** 72,
              'trevigintillion': 10 ** 72,
              'vigintiquadrillion': 10 ** 75,
              'quattuorvigintillion': 10 ** 75,
              'quinvigintillion': 10 ** 78,
              'vigintiquintrillion': 10 ** 78,
              'vigintisextillion': 10 ** 81,
              'sexvigintillion': 10 ** 81,
              'vigintiseptillion': 10 ** 84,
              'septvigintillion': 10 ** 84,
              'octovigintillion': 10 ** 87,
              'vigintoctillion': 10 ** 87,
              'vigintinonillion': 10 ** 90,
              'nonvigintillion': 10 ** 90,
              'trigintillion': 10 ** 93,
              'untrigintillion': 10 ** 96,
              'duotrigintillion': 10 ** 99,
              'googol': 10 ** 100,
              'centillion': 10 ** 303}
    
    result = 0
    a = string.split(" ")
    b = []
    
    for c in a:
        if c in numbers:
            b.append(c)
        elif c in powers:
            b[-1] += " " + c
        elif c == "and":
            continue
        else:
            print("INVALID WORD:",c)
            return

    for d, e in enumerate(b):
        if len(e.split(" ")) == 1:
            b[d] = numbers[e]
        else:
            b[d] = e.split(" ")
            b[d][0] = numbers[b[d][0]]
            f = 1
            while f < len(b[d]):
                b[d][f] = powers[b[d][f]]
                f += 1
    
    if not(isinstance(b[0], int)):
       while len(b[0]) > 2:
           b[0][1] *= b[0][2]
           b[0].pop(2)
    
    while len(b):
        if len(b) == 1:
            if isinstance(b[0], int):
                result += b[0]
                b.pop(0)
            else:
                while len(b[0]) > 1:
                    b[0][0] *= b[0][1]
                    b[0].pop(1)
                result += b[0][0]
                b.pop(0)
        else:
            if isinstance(b[1], int):
                b[1] += b[0][0] * b[0][1]
                b.pop(0)
            else:
                while len(b[1]) > 2:
                    b[1][1] *= b[1][2]
                    b[1].pop(2)
                
                if b[0][1] < b[1][1]:
                    b[1][0] += b[0][0] * b[0][1]
                    b.pop(0)
                else:
                    result += b[0][0] * b[0][1]
                    b.pop(0)
    
    return result

hours, minutes = input(">>> ").split(" and ")
seconds = parse_int(hours.rsplit(' ', 1)[0]) * 3600 + \
          parse_int(minutes.rsplit(' ', 1)[0]) * 60
print(seconds)

测试运行:

>>> one billion hours and twelve minutes

输出:

3600000000720

致谢:https://codereview.stackexchange.com/a/253014/229550

如果您想从头开始,那么其他答案也不错。以下是您无需输入太多内容即可执行的操作:

您需要为该解决方案安装 word2number

from word2number import w2n
import re
def strTimeToSec(s):
    s = s.replace(' and', '')
    time = re.split(' hour| hours| minute| minutes| second| seconds', s)[:-1]
    if not('hour' in s):
        time = ['zero']+time
    elif not('minute' in s):
        time = [time[0]]+['zero']+[time[1]]
    elif not('second' in s):
        time = time+['zero']
    time = [w2n.word_to_num(x) for x in time]
    out = time[0]*3600+time[1]*60+time[2]
    return str(out)+' seconds'

>>> print(strTimeToSec('one hour and forty five minute'))

6300 seconds

>>> print(strTimeToSec('one hour forty five minute and thirty three seconds'))

6333 seconds