133 lines
2.6 KiB
Go
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)
|
||
|
|
}
|