zoukankan      html  css  js  c++  java
  • Python实现ParseDuration-支持解析字符串格式的时间单位,例如将小时或者分钟数转换为秒

    python的time模块不支持单独将字符串格式的分钟数和小时数转换为秒,比如将“5m”转换为“300”(秒),不支持将“0.2h5.1m12.123s”转换为“1038.123”(秒)。

    但是这种字符串格式的分钟数或者小时数写法,在一些配置或者用户交互中还是比较有用的。

    为了实现这种功能,通过模拟golang的`time`模块中的`ParseDuration(s string) (duration, error)`函数,使用Python代码实现如下:

    #-*- coding:utf-8 -*-
    import sys
    import logging
    
    reload(sys)                      # reload 才能调用 setdefaultencoding 方法
    sys.setdefaultencoding('utf-8')  # 设置 'utf-8'
    
    from cfg import config
    
    class TimeTool(object):
        def __init__(self):
            handler = logging.StreamHandler()
            formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
            handler.setFormatter(formatter)
            self.logger = logging.getLogger("HistoryReader")
            self.logger.addHandler(handler)
            self.logger.setLevel(config.LOG_LEVEL)
            self.Nanosecond  = 1
            self.Microsecond = 1000 * self.Nanosecond
            self.Millisecond = 1000 * self.Microsecond
            self.Second      = 1000 * self.Millisecond
            self.Minute      = 60 * self.Second
            self.Hour        = 60 * self.Minute
            self.unitMap = {
                                "ns": int(self.Nanosecond),
                                "us": int(self.Microsecond),
                                "µs": int(self.Microsecond), # U+00B5 = micro symbol
                                "μs": int(self.Microsecond), # U+03BC = Greek letter mu
                                "ms": int(self.Millisecond),
                                "s":  int(self.Second),
                                "m":  int(self.Minute),
                                "h":  int(self.Hour),
            }
            pass
    
        def leadingInt(self, s):
            x, rem, err = int(0), str(""), "time: bad [0-9]*"
            i = 0
            while i < len(s):
                c = s[i]
                if c < '0' or c > '9':
                    break
                #print x
                if x > (1 << 63-1)/10:
                    #print "x > (1 << 63-1)/10 => %s > %s" %(x, (1 << 63-1)/10)
                    return 0, "", err
                x = x * 10 + int(c) - int('0')
                if x < 0:
                    #print "x < 0 => %s < 0" %(x)
                    return 0, "", err
                i+=1
            return x, s[i:], None
    
        def leadingFraction(self, s):
            x, scale, rem = int(0), float(1), ""
            i, overflow = 0, False
            while i < len(s):
                c = s[i]
                if c < '0' or c > '9':
                    break
                if overflow:
                    continue
                if x > (1<<63-1)/10 :
                    overflow = True
                    continue
                y = x*10 + int(c) - int('0')
                if y < 0:
                    overflow = True
                    continue
                x = y
                scale *= 10
                i += 1
            return x, scale, s[i:]
    
        """
        将小时,分钟,转换为秒
        比如: 5m 转换为 300秒;5m20s 转换为320秒
        time 单位支持:"ns", "us" (or "µs"), "ms", "s", "m", "h"
        """
        def ParseDuration(self, s):
            if s == "" or len(s) < 1:
                return 0
    
            orig = s
            neg = False
            d = float(0)
    
            if s != "":
                if s[0] == "-" or s[0] == "+":
                    neg = s[0] == "-"
                    s = s[1:]
    
            if s == "0" or s == "":
                return 0
    
            while s != "":
                v, f, scale = int(0), int(0), float(1)
    
                print "S: %s" %s
                # the next character must be [0-9.]
                if not (s[0] == "." or '0' <= s[0] and s[0] <= '9'):
                    self.logger.error("time1: invalid duration %s, s:%s" % (orig, s))
                    return 0
    
                # Consume [0-9]*
                pl = len(s)
                v, s, err = self.leadingInt(s)
                if err != None:
                    self.logger.error("time2, invalid duration %s" %orig)
                    return 0
                pre = pl != len(s)
    
                # consume (.[0-9]*)?
                post = False
                if s != "" and s[0] == ".":
                    s = s[1:]
                    pl = len(s)
                    f, scale, s = self.leadingFraction(s)
                    post = pl != len(s)
                if not pre and not post:
                    self.logger.error("time3, invalid duration %s" %orig)
                    return 0
    
                # Consume unit.
                i = 0
                while i < len(s):
                    c = s[i]
                    if c == '.' or '0' <= c and c <= '9':
                        break
                    i+=1
                if i == 0:
                    self.logger.error("time4: unkonw unit in duration: %s" %orig)
                    return 0
                print "s:%s, i:%s, s[:i]:%s" %(s, i, s[:i])
                u = s[:i]
                s = s[i:]
                if not self.unitMap.has_key(u):
                    self.logger.error("time5: unknow unit %s in duration %s" %(u, orig))
                    return 0
                unit = self.unitMap[u]
                if v > (1<<63-1)/unit:
                    self.logger.error("time6: invalid duration %s" %orig)
                    return 0
                v *= unit
                if f > 0 :
                    v += int(float(f) * (float(unit) / scale))
                    if v < 0:
                        self.logger.error("time7: invalid duration %s" %orig)
                        return 0
                d += v
                if d < 0 :
                    self.logger.error("time8: invalid duration %s" %orig)
                    return 0
    
            if neg :
                d = -d
            return float(d)
    

     

    使用实例:

    #-*- coding:utf-8 -*-
    from timeTools import TimeTool
    
    if __name__ == "__main__":
        tools = TimeTool()
        s = tools.ParseDuration("1m20.123s")
        print s
    

    默认打印单位是“Nanosecond”,如果想要打印单位为“second”的话,只需要将parse结果除以`TimeTool.Second`即可,例如:

    ```python

    tools = TimeTool()

    s = tools.ParseDuration("1m20.123s")
    print s/tools.Second

    ```

  • 相关阅读:
    PLSQL导入导出oracle表 表空间
    IDL(Interactive Data Language——交互式数据语言)
    easyui更改messager的OkCancel按钮为(中文)确定取消
    java 中判断字符串相等
    hql实现对表的某几个(部分)字段查询
    MyEclipse 断点打不上 提示 absent line number information
    cocos2dx-3.x 导出自定义类到 lua 过程
    cocos2d-x中DrawNode常见的图像绘制函数
    cocos2d环境及创建一个自己的项目
    cocos2d基本类介绍 director/scene/layer/sprite
  • 原文地址:https://www.cnblogs.com/yzhch/p/9098764.html
Copyright © 2011-2022 走看看