Skip to content

Commit d575969

Browse files
committed
Add the library
1 parent c2df0bf commit d575969

File tree

6 files changed

+180
-0
lines changed

6 files changed

+180
-0
lines changed

.gitignore

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
### https://raw.github.com/github/gitignore/18e28746b0862059dbee8694fd366a679cb812fb/Go.gitignore
2+
3+
# Binaries for programs and plugins
4+
*.exe
5+
*.exe~
6+
*.dll
7+
*.so
8+
*.dylib
9+
10+
# Test binary, build with `go test -c`
11+
*.test
12+
13+
# Output of the go coverage tool, specifically when used with LiteIDE
14+
*.out
15+
bin/
16+

Makefile

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
build:
2+
GO111MODULE=on go build -v -o bin/dateparse src/*.go
3+
4+
go_lint:
5+
GO111MODULE=on go mod tidy
6+
GO111MODULE=on go vet ./src
7+
golint -set_exit_status ./src/...
8+
go tool fix src/
9+
golangci-lint run
10+
11+
lint: format go_lint
12+
13+
format:
14+
go fmt ./src/...
15+
16+
clean:
17+
GO111MODULE=on go clean --modcache
18+
rm -rf bin/*
19+
20+
test:
21+
GO111MODULE=on go test ./src/... -v

go.mod

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module dateparse
2+
3+
go 1.14

src/date_utils.go

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package dateparse
2+
3+
import (
4+
"strings"
5+
"time"
6+
)
7+
8+
// Remember the last successful format and reuse it to same time
9+
var lastSuccessfulFormat = time.RFC822Z
10+
11+
// GetParsedDate can handle date coming from email header as well as
12+
// Calendar's date and time.
13+
// Different email clients seems to be using different date formats.
14+
// TODO: store the last use date pattern and try it first the next time.
15+
func GetParsedDate(date string) (*time.Time, error) {
16+
// The expected time format is "Fri, 20 Mar 2020 17:05:25 +0000" but some email clients
17+
// add extraneous information at the end, for example,
18+
// "Fri, 20 Mar 2020 17:05:25 +0000 (UTC)"
19+
// Try again by removing that
20+
index := strings.Index(date, "(")
21+
if index > 0 {
22+
date = strings.TrimSpace(date[:index])
23+
}
24+
// Occasionally, dates have UT instead of UTC :/
25+
if strings.HasSuffix(date, "UT") {
26+
// Change to UT to UTC
27+
date += "C"
28+
}
29+
30+
//Another common case is when an extraneous GMT with timezone is present
31+
// Mon, 25 Nov 2019 18:18:47 +0100 GMT
32+
if strings.HasSuffix(date, "GMT") &&
33+
strings.Contains(date, "+") {
34+
date = strings.TrimSuffix(date, "GMT")
35+
}
36+
date = strings.TrimSpace(date)
37+
38+
// Remove commas
39+
date = strings.ReplaceAll(date, ", ", " ")
40+
date = strings.ReplaceAll(date, ",", " ")
41+
42+
formats := []string{
43+
lastSuccessfulFormat,
44+
"02 Jan 06 15:04 MST", // time.RFC822
45+
"2 Jan 06 15:04:05 -0700",
46+
"2 Jan 06 15:04:05 MST",
47+
"2 Jan 2006 15:04:05 -0700",
48+
"2 Jan 2006 15:04:05 MST",
49+
"02 Jan 06 15:04:05 -0700",
50+
"02 Jan 06 15:04:05 MST",
51+
"02 Jan 2006 15:04:05 -0700",
52+
"02 Jan 2006 15:04:05 MST",
53+
"02 Jan 06 15:04 -0700", // time.RFC822Z,
54+
// time.RFC1123 with comma removed
55+
"Mon 02 Jan 2006 15:04:05 MST",
56+
// time.RFC1123Z with comma removed
57+
"Mon 02 Jan 2006 15:04:05 -0700",
58+
"Mon 2 Jan 2006 15:04:05 -0700",
59+
"Mon 2 Jan 2006 15:04:05 MST",
60+
// time.RFC3339 with comma removed
61+
"2006-01-02T15:04:05Z07:00",
62+
"Jan _2 2006",
63+
"January _2 2006",
64+
"Monday, 02-Jan-06 15:04:05 MST", // time.RFC850
65+
// time.RFC850 with comma removed
66+
"Monday 02-Jan-06 15:04:05 MST",
67+
"Monday 02-Jan-2006 15:04:05 MST",
68+
}
69+
var tmpDate time.Time
70+
var err error
71+
for _, format := range formats {
72+
tmpDate, err = time.Parse(format, date)
73+
if err == nil {
74+
// For faster parsing in the future
75+
lastSuccessfulFormat = format
76+
return &tmpDate, nil
77+
}
78+
}
79+
return nil, err
80+
}

src/date_utils_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package dateparse
2+
3+
import (
4+
"io/ioutil"
5+
"path/filepath"
6+
"strings"
7+
"testing"
8+
)
9+
10+
var testDataFilename = filepath.Join("testdata", "date_entries.txt")
11+
12+
func TestGetParsedDate(t *testing.T) {
13+
data, err := ioutil.ReadFile(testDataFilename)
14+
if err != nil {
15+
t.Errorf("Failed to read file %s: %v", testDataFilename, err)
16+
t.Fail()
17+
}
18+
for _, dateEntry := range strings.Split(string(data), "\n") {
19+
if len(dateEntry) == 0 {
20+
continue
21+
}
22+
_, err := GetParsedDate(dateEntry)
23+
if err != nil {
24+
t.Errorf("Failed to parse date from \"%s\": %v", dateEntry, err)
25+
}
26+
// t.Logf(`Parsed date is "%v"`, parsedDate)
27+
}
28+
}

src/testdata/date_entries.txt

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
Sun, 10 Apr 2016 19:57:43 +0000
2+
Sat, 18 Apr 2020 16:32:33 -0700
3+
Sat, 18 Apr 2020 15:19:17 -0700
4+
Sat, 18 Apr 2020 09:24:59 +0000 (UTC)
5+
Sat, 18 Apr 2020 02:31:32 -0700
6+
Sat, 18 Apr 2020 02:31:54 -0700
7+
Mon, 20 Apr 2020 16:44:50 -0700
8+
Sat, 18 Apr 2020 04:45:08 +0000
9+
Sat, 18 Apr 2020 00:42:45 -0700
10+
Sat, 18 Apr 2020 11:05:42 -0700
11+
Sun, 19 Apr 2020 17:25:31 +0000 (UTC)
12+
Sun, 19 Apr 2020 11:24:35 -0700
13+
Sun, 19 Apr 2020 17:11:29 -0700
14+
Mon, 20 Apr 2020 16:50:47 +0000
15+
Sun, 10 Apr 2016 05:32:59 +0000
16+
Sun, 10 Apr 2016 05:35:08 +0000
17+
Sun, 10 Apr 2016 05:40:33 +0000
18+
Sun, 10 Apr 2016 05:41:09 +0000
19+
Sun, 10 Apr 2016 05:44:07 +0000
20+
Sun, 10 Apr 2016 05:52:17 +0000
21+
Sun, 10 Apr 2016 06:00:29 +0000
22+
Sun, 10 Apr 2016 06:04:22 +0000
23+
Sun, 10 Apr 2016 06:20:01 +0000
24+
Sun, 10 Apr 2016 06:33:58 +0000
25+
Sun, 10 Apr 2016 06:43:14 +0000
26+
Sun, 10 Apr 2016 06:49:24 +0000
27+
Sun, 10 Apr 2016 07:16:55 +0000
28+
Sun, 10 Apr 2016 07:29:06 +0000
29+
Sun, 10 Apr 2016 11:58:17 +0000
30+
Sun, 10 Apr 2016 19:57:43 +0000
31+
Mon, 25 Nov 2019 18:18:47 +0100 GMT
32+
Thursday 04-Jun-2020 20:45:05 UTC

0 commit comments

Comments
 (0)