Skip to content

Instantly share code, notes, and snippets.

@kaimingguo
Created March 28, 2023 08:09
Show Gist options
  • Save kaimingguo/2593bcd9d09aeea0b2588eaaab8729cc to your computer and use it in GitHub Desktop.
Save kaimingguo/2593bcd9d09aeea0b2588eaaab8729cc to your computer and use it in GitHub Desktop.
ISO8601 duration format parser
package main
import (
"fmt"
"regexp"
"strconv"
"time"
)
func main() {
durationString := "P2YT1H8.001S"
fmt.Println("duration: ", durationString)
re := regexp.MustCompile(`^(-?)P(?:T*|\d)(?:(-?\d+)Y)?(?:(-?\d+)M)?(?:(-?\d+)([DW]))?(?:T(?:(-?\d+)H)?(?:(-?\d+)M)?(?:(-?\d+(?:\.\d+)?)S)?)?$`)
matches := re.FindStringSubmatch(durationString)
if len(matches) == 0 {
panic(fmt.Errorf("your regular expression does not match the subject string"))
}
var (
numOffset int
years int
months int
days int
hours int
minutes int
seconds float64
)
if s := matches[1]; s != "" {
numOffset = -1
} else {
numOffset = 1
}
if i32, err := strconv.Atoi(matches[2]); err == nil {
years = numOffset * i32
}
if i32, err := strconv.Atoi(matches[3]); err == nil {
months = numOffset * i32
}
if i32, err := strconv.Atoi(matches[4]); err == nil {
switch matches[5] {
case "W":
days = numOffset * i32 * 7
case "D":
days = numOffset * i32
}
}
if i32, err := strconv.Atoi(matches[6]); err == nil {
hours = numOffset * i32
}
if i32, err := strconv.Atoi(matches[7]); err == nil {
minutes = numOffset * i32
}
if f64, err := strconv.ParseFloat(matches[8], 64); err == nil {
seconds = float64(numOffset) * f64
}
fmt.Println("Group 1 (offset)", numOffset)
fmt.Println("Group 2 (year)", years)
fmt.Println("Group 3 (month)", months)
fmt.Println("Group 4 (day)", days)
fmt.Println("Group 6 (hour)", hours)
fmt.Println("Group 7 (minute)", minutes)
fmt.Println("Group 8 (second)", seconds)
now := time.Now()
fmt.Println("current time: ", now.Format(time.RFC3339))
result := now.AddDate(years, months, days)
result = result.Add(time.Hour * time.Duration(hours))
result = result.Add(time.Minute * time.Duration(minutes))
result = result.Add(time.Second * time.Duration(seconds))
fmt.Println("expiration time: ", result.Format(time.RFC3339))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment