Golang解析时间持续时间(time.Duration)

huangapple go评论91阅读模式
英文:

Golang parse time.Duration

问题

我想解析 time.Duration。持续时间是 "PT15M"(字符串/字节),我想将其转换为有效的 time.Duration


如果这是一个 time.Time 的东西,我会使用:

t, err := time.Parse(time.RFC3339Nano, "2013-06-05T14:10:43.678Z")

但是这个函数不存在(ParseDuration 只接受一个参数):

d, err := time.ParseDuration(time.RFC3339Nano, "PT15M")


我该如何解析这个 ISO 8601 duration

英文:

I would like to parse time.Duration. The duration is "PT15M" (string/bytes) and would like to convert it to a valid time.Duration.


If this were a time.Time thing, I would use:

But this doesn't exist (ParseDuration only takes one parameter):


How can I parse this ISO 8601 duration?

答案1

得分: 3

这是一个用于解析时间持续的正则表达式的代码示例:

package main

import "fmt"
import "regexp"
import "strconv"
import "time"

func main() {
    fmt.Println(ParseDuration("PT15M"))
    fmt.Println(ParseDuration("P12Y4MT15M"))
}

func ParseDuration(str string) time.Duration {
    durationRegex := regexp.MustCompile(`P(?P<years>\d+Y)?(?P<months>\d+M)?(?P<days>\d+D)?T?(?P<hours>\d+H)?(?P<minutes>\d+M)?(?P<seconds>\d+S)?`)
    matches := durationRegex.FindStringSubmatch(str)

    years := ParseInt64(matches[1])
    months := ParseInt64(matches[2])
    days := ParseInt64(matches[3])
    hours := ParseInt64(matches[4])
    minutes := ParseInt64(matches[5])
    seconds := ParseInt64(matches[6])

    hour := int64(time.Hour)
    minute := int64(time.Minute)
    second := int64(time.Second)
    return time.Duration(years*24*365*hour + months*30*24*hour + days*24*hour + hours*hour + minutes*minute + seconds*second)
}

func ParseInt64(value string) int64 {
    if len(value) == 0 {
        return 0
    }
    parsed, err := strconv.Atoi(value[:len(value)-1])
    if err != nil {
        return 0
    }
    return int64(parsed)
}

这段代码使用正则表达式解析时间持续字符串,并将其转换为Go语言中的time.Duration类型。它可以解析包含年、月、日、小时、分钟和秒的时间持续字符串,并将其转换为对应的持续时间。

英文:

It's not exactly "out of the box" but a regular expression does the job:

package main

import &quot;fmt&quot;
import &quot;regexp&quot;
import &quot;strconv&quot;
import &quot;time&quot;

func main() {
	fmt.Println(ParseDuration(&quot;PT15M&quot;))
	fmt.Println(ParseDuration(&quot;P12Y4MT15M&quot;))
}

func ParseDuration(str string) time.Duration {
	durationRegex := regexp.MustCompile(`P(?P&lt;years&gt;\d+Y)?(?P&lt;months&gt;\d+M)?(?P&lt;days&gt;\d+D)?T?(?P&lt;hours&gt;\d+H)?(?P&lt;minutes&gt;\d+M)?(?P&lt;seconds&gt;\d+S)?`)
	matches := durationRegex.FindStringSubmatch(str)

	years := ParseInt64(matches[1])
	months := ParseInt64(matches[2])
	days := ParseInt64(matches[3])
	hours := ParseInt64(matches[4])
	minutes := ParseInt64(matches[5])
	seconds := ParseInt64(matches[6])

	hour := int64(time.Hour)
	minute := int64(time.Minute)
	second := int64(time.Second)
	return time.Duration(years*24*365*hour + months*30*24*hour + days*24*hour + hours*hour + minutes*minute + seconds*second)
}

func ParseInt64(value string) int64 {
	if len(value) == 0 {
		return 0
	}
	parsed, err := strconv.Atoi(value[:len(value)-1])
	if err != nil {
		return 0
	}
	return int64(parsed)
}

答案2

得分: 1

以下是处理分数时间单位(如PT3.001S)的代码。

var durationRegex = regexp.MustCompile(`P([\d\.]+Y)?([\d\.]+M)?([\d\.]+D)?T?([\d\.]+H)?([\d\.]+M)?([\d\.]+?S)?`)

// ParseDuration将ISO8601持续时间转换为time.Duration
func ParseDuration(str string) time.Duration {
    matches := durationRegex.FindStringSubmatch(str)

    years := parseDurationPart(matches[1], time.Hour*24*365)
    months := parseDurationPart(matches[2], time.Hour*24*30)
    days := parseDurationPart(matches[3], time.Hour*24)
    hours := parseDurationPart(matches[4], time.Hour)
    minutes := parseDurationPart(matches[5], time.Second*60)
    seconds := parseDurationPart(matches[6], time.Second)

    return time.Duration(years + months + days + hours + minutes + seconds)
}

func parseDurationPart(value string, unit time.Duration) time.Duration {
    if len(value) != 0 {
        if parsed, err := strconv.ParseFloat(value[:len(value)-1], 64); err == nil {
            return time.Duration(float64(unit) * parsed)
        }
    }
    return 0
}

希望对你有帮助!

英文:

Here is code that handles fractional time units like PT3.001S.

var durationRegex = regexp.MustCompile(`P([\d\.]+Y)?([\d\.]+M)?([\d\.]+D)?T?([\d\.]+H)?([\d\.]+M)?([\d\.]+?S)?`)

// ParseDuration converts a ISO8601 duration into a time.Duration
func ParseDuration(str string) time.Duration {
   matches := durationRegex.FindStringSubmatch(str)

   years := parseDurationPart(matches[1], time.Hour*24*365)
   months := parseDurationPart(matches[2], time.Hour*24*30)
   days := parseDurationPart(matches[3], time.Hour*24)
   hours := parseDurationPart(matches[4], time.Hour)
   minutes := parseDurationPart(matches[5], time.Second*60)
   seconds := parseDurationPart(matches[6], time.Second)

   return time.Duration(years + months + days + hours + minutes + seconds)
}

func parseDurationPart(value string, unit time.Duration) time.Duration {
   if len(value) != 0 {
       if parsed, err := strconv.ParseFloat(value[:len(value)-1], 64); err == nil {
           return time.Duration(float64(unit) * parsed)
       }
   }
   return 0
}

huangapple
  • 本文由 发表于 2015年1月24日 21:28:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/28125963.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定