mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-12 05:59:14 +00:00
Relative time, fixes.
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
package sql3util
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NamedArg splits an named arg into a key and value,
|
||||
// around an equals sign.
|
||||
@@ -63,3 +66,115 @@ func ParseBool(s string) (b, ok bool) {
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
// ParseTimeShift parses a time shift modifier,
|
||||
// also the output of timediff.
|
||||
//
|
||||
// https://sqlite.org/lang_datefunc.html
|
||||
func ParseTimeShift(s string) (years, months, days int, duration time.Duration, ok bool) {
|
||||
// Sign part: ±
|
||||
neg := strings.HasPrefix(s, "-")
|
||||
sign := neg || strings.HasPrefix(s, "+")
|
||||
if sign {
|
||||
s = s[1:]
|
||||
}
|
||||
|
||||
if ok = len(s) >= 5; !ok {
|
||||
return // !ok
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if neg {
|
||||
years = -years
|
||||
months = -months
|
||||
days = -days
|
||||
duration = -duration
|
||||
}
|
||||
}()
|
||||
|
||||
// Date part: YYYY-MM-DD
|
||||
if s[4] == '-' {
|
||||
if ok = sign && len(s) >= 10 && s[7] == '-'; !ok {
|
||||
return // !ok
|
||||
}
|
||||
if years, ok = parseInt(s[0:4]); !ok {
|
||||
return // !ok
|
||||
}
|
||||
if months, ok = parseInt(s[5:7]); !ok {
|
||||
return // !ok
|
||||
}
|
||||
if days, ok = parseInt(s[8:10]); !ok {
|
||||
return // !ok
|
||||
}
|
||||
if len(s) == 10 {
|
||||
return
|
||||
}
|
||||
if ok = s[10] == ' '; !ok {
|
||||
return // !ok
|
||||
}
|
||||
s = s[11:]
|
||||
}
|
||||
|
||||
// Time part: HH:MM
|
||||
if ok = len(s) >= 5 && s[2] == ':'; !ok {
|
||||
return // !ok
|
||||
}
|
||||
|
||||
var hours, minutes int
|
||||
if hours, ok = parseInt(s[0:2]); !ok {
|
||||
return
|
||||
}
|
||||
if minutes, ok = parseInt(s[3:5]); !ok {
|
||||
return
|
||||
}
|
||||
duration = time.Duration(hours)*time.Hour + time.Duration(minutes)*time.Minute
|
||||
|
||||
if len(s) == 5 {
|
||||
return
|
||||
}
|
||||
if ok = len(s) >= 8 && s[5] == ':'; !ok {
|
||||
return // !ok
|
||||
}
|
||||
|
||||
// Seconds part: HH:MM:SS
|
||||
var seconds int
|
||||
if seconds, ok = parseInt(s[6:8]); !ok {
|
||||
return
|
||||
}
|
||||
duration += time.Duration(seconds) * time.Second
|
||||
|
||||
if len(s) == 8 {
|
||||
return
|
||||
}
|
||||
if ok = len(s) >= 10 && s[8] == '.'; !ok {
|
||||
return // !ok
|
||||
}
|
||||
s = s[9:]
|
||||
|
||||
// Nanosecond part: HH:MM:SS.SSS
|
||||
var nanos int
|
||||
if nanos, ok = parseInt(s[0:min(9, len(s))]); !ok {
|
||||
return
|
||||
}
|
||||
for i := len(s); i < 9; i++ {
|
||||
nanos *= 10
|
||||
}
|
||||
duration += time.Duration(nanos)
|
||||
|
||||
// Subnanosecond part.
|
||||
if len(s) > 9 {
|
||||
_, ok = parseInt(s[9:])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseInt(s string) (i int, _ bool) {
|
||||
for _, r := range []byte(s) {
|
||||
r -= '0'
|
||||
if r > 9 {
|
||||
return
|
||||
}
|
||||
i = i*10 + int(r)
|
||||
}
|
||||
return i, true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user