mirror of
https://github.com/go-gitea/gitea
synced 2024-12-25 06:35:58 +01:00
936665bf85
Redesign the time tracker side bar, and add "time estimate" support (in "1d 2m" format) Closes #23112 --------- Co-authored-by: stuzer05 <stuzer05@gmail.com> Co-authored-by: Yarden Shoham <hrsi88@gmail.com> Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
86 lines
2.1 KiB
Go
86 lines
2.1 KiB
Go
// Copyright 2024 Gitea. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package util
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
type timeStrGlobalVarsType struct {
|
|
units []struct {
|
|
name string
|
|
num int64
|
|
}
|
|
re *regexp.Regexp
|
|
}
|
|
|
|
// When tracking working time, only hour/minute/second units are accurate and could be used.
|
|
// For other units like "day", it depends on "how many working hours in a day": 6 or 7 or 8?
|
|
// So at the moment, we only support hour/minute/second units.
|
|
// In the future, it could be some configurable options to help users
|
|
// to convert the working time to different units.
|
|
|
|
var timeStrGlobalVars = sync.OnceValue[*timeStrGlobalVarsType](func() *timeStrGlobalVarsType {
|
|
v := &timeStrGlobalVarsType{}
|
|
v.re = regexp.MustCompile(`(?i)(\d+)\s*([hms])`)
|
|
v.units = []struct {
|
|
name string
|
|
num int64
|
|
}{
|
|
{"h", 60 * 60},
|
|
{"m", 60},
|
|
{"s", 1},
|
|
}
|
|
return v
|
|
})
|
|
|
|
func TimeEstimateParse(timeStr string) (int64, error) {
|
|
if timeStr == "" {
|
|
return 0, nil
|
|
}
|
|
var total int64
|
|
matches := timeStrGlobalVars().re.FindAllStringSubmatchIndex(timeStr, -1)
|
|
if len(matches) == 0 {
|
|
return 0, fmt.Errorf("invalid time string: %s", timeStr)
|
|
}
|
|
if matches[0][0] != 0 || matches[len(matches)-1][1] != len(timeStr) {
|
|
return 0, fmt.Errorf("invalid time string: %s", timeStr)
|
|
}
|
|
for _, match := range matches {
|
|
amount, err := strconv.ParseInt(timeStr[match[2]:match[3]], 10, 64)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("invalid time string: %v", err)
|
|
}
|
|
unit := timeStr[match[4]:match[5]]
|
|
found := false
|
|
for _, u := range timeStrGlobalVars().units {
|
|
if strings.ToLower(unit) == u.name {
|
|
total += amount * u.num
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
return 0, fmt.Errorf("invalid time unit: %s", unit)
|
|
}
|
|
}
|
|
return total, nil
|
|
}
|
|
|
|
func TimeEstimateString(amount int64) string {
|
|
var timeParts []string
|
|
for _, u := range timeStrGlobalVars().units {
|
|
if amount >= u.num {
|
|
num := amount / u.num
|
|
amount %= u.num
|
|
timeParts = append(timeParts, fmt.Sprintf("%d%s", num, u.name))
|
|
}
|
|
}
|
|
return strings.Join(timeParts, " ")
|
|
}
|