Skip to content

Commit

Permalink
syntax: add ParseDatetimeLenient method
Browse files Browse the repository at this point in the history
  • Loading branch information
bnewbold committed Nov 28, 2023
1 parent 60c686e commit 320dbcd
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 0 deletions.
26 changes: 26 additions & 0 deletions atproto/syntax/datetime.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,32 @@ func ParseDatetimeTime(raw string) (time.Time, error) {
return d.Time(), nil
}

// Similar to ParseDatetime, but more flexible about some parsing.
//
// Note that this may mutate the internal string, so a round-trip will fail. This is intended for working with legacy/broken records, not to be used in an ongoing way.
func ParseDatetimeLenient(raw string) (Datetime, error) {
// fast path: it is a valid overall datetime
valid, err := ParseDatetime(raw)
if nil == err {
return valid, nil
}

if strings.HasSuffix(raw, "-00:00") {
return ParseDatetime(strings.Replace(raw, "-00:00", "+00:00", 1))
}

// try adding timezone if it is missing
var hasTimezoneRegex = regexp.MustCompile(`^.*(([+-]\d\d:?\d\d)|[a-zA-Z])$`)
if !hasTimezoneRegex.MatchString(raw) {
withTZ, err := ParseDatetime(raw + "Z")
if nil == err {
return withTZ, nil
}
}

return "", fmt.Errorf("Datetime could not be parsed, even leniently: %v", err)
}

// Parses the Datetime string in to a golang [time.Time].
//
// This method assumes that [ParseDatetime] was used to create the Datetime, which already verified parsing, and thus that [time.Parse] will always succeed. In the event of an error, zero/nil will be returned.
Expand Down
29 changes: 29 additions & 0 deletions atproto/syntax/datetime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,35 @@ func TestInteropDatetimeTimeInvalid(t *testing.T) {
assert.NoError(scanner.Err())
}

func TestParseDatetimeLenient(t *testing.T) {
assert := assert.New(t)

valid := []string{
"1985-04-12T23:20:50.123Z",
"1985-04-12T23:20:50.123",
"2023-08-27T19:07:00.186173",
"1985-04-12T23:20:50.123-00:00",
"1985-04-12T23:20:50.123+00:00",
}
for _, s := range valid {
_, err := ParseDatetimeLenient(s)
assert.NoError(err)
if err != nil {
fmt.Println(s)
}
}

invalid := []string{
"1985-04-",
"",
"blah",
}
for _, s := range invalid {
_, err := ParseDatetimeLenient(s)
assert.Error(err)
}
}

func TestDatetimeNow(t *testing.T) {
assert := assert.New(t)

Expand Down

0 comments on commit 320dbcd

Please sign in to comment.