whoissdk/date_parse.go
2026-03-19 11:53:07 +08:00

133 lines
2.6 KiB
Go

package whois
import (
"fmt"
"strconv"
"strings"
"time"
)
func parseDateAuto(s string) time.Time {
s = strings.TrimSpace(s)
if s == "" {
return time.Time{}
}
withZoneLayouts := []string{
time.RFC3339Nano,
time.RFC3339,
"2006-01-02T15:04:05.999999999-0700",
"2006-01-02T15:04:05-0700",
"2006-01-02 15:04:05 -0700",
"2006-01-02 15:04:05 -07:00",
"2006-01-02 15:04:05 MST",
"2006/01/02 15:04:05 (MST)",
"02-Jan-2006 15:04:05 MST",
"02-01-2006 15:04:05 -0700",
}
localLayouts := []string{
"2006-01-02T15:04:05.999999999",
"2006-01-02T15:04:05",
"2006-01-02 15:04:05",
"2006-01-02",
"2006/01/02 15:04:05",
"2006/01/02",
"2006.01.02 15:04:05",
"2006.01.02",
"02-Jan-2006",
"02.01.2006 15:04:05",
"02.01.2006",
"2.1.2006 15:04:05",
"2.1.2006",
"02-01-2006 15:04:05",
"02-01-2006",
"Mon Jan 2 15:04:05 2006",
}
for _, candidate := range normalizeDateCandidates(s) {
for _, l := range withZoneLayouts {
if t, err := time.Parse(l, candidate); err == nil {
return t.In(time.Local)
}
}
for _, l := range localLayouts {
if t, err := time.ParseInLocation(l, candidate, time.Local); err == nil {
return t
}
}
}
return time.Time{}
}
func normalizeDateCandidates(s string) []string {
seen := map[string]struct{}{}
out := make([]string, 0, 6)
push := func(v string) {
v = strings.TrimSpace(v)
if v == "" {
return
}
if _, ok := seen[v]; ok {
return
}
seen[v] = struct{}{}
out = append(out, v)
}
push(s)
push(strings.Trim(s, "\"'"))
if i := strings.Index(s, " ("); i > 0 && strings.HasSuffix(s, ")") {
push(s[:i])
}
if strings.HasSuffix(strings.ToUpper(s), " UTC") {
push(strings.TrimSpace(s[:len(s)-4]) + " +0000")
}
if gmt := normalizeGMTOffsetSuffix(s); gmt != "" {
push(gmt)
}
return out
}
func normalizeGMTOffsetSuffix(s string) string {
trimmed := strings.TrimSpace(s)
upper := strings.ToUpper(trimmed)
idx := strings.LastIndex(upper, " GMT")
if idx <= 0 {
return ""
}
base := strings.TrimSpace(trimmed[:idx])
offset := strings.TrimSpace(trimmed[idx+4:])
if len(offset) < 2 {
return ""
}
sign := offset[0]
if sign != '+' && sign != '-' {
return ""
}
offset = offset[1:]
hourText := offset
minText := "00"
if p := strings.Index(offset, ":"); p >= 0 {
hourText = offset[:p]
minText = offset[p+1:]
}
if hourText == "" {
return ""
}
hour, err := strconv.Atoi(hourText)
if err != nil {
return ""
}
mins := 0
if minText != "" {
mins, err = strconv.Atoi(minText)
if err != nil {
return ""
}
}
return fmt.Sprintf("%s %c%02d%02d", base, sign, hour, mins)
}