this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

syntax: datetime lenient method; TID parse helper CLI (#455)

authored by

Whyrusleeping and committed by
GitHub
15938d4e f8ba20dc

+99
+44
atproto/syntax/cmd/atp-syntax/main.go
··· 1 + package main 2 + 3 + import ( 4 + "fmt" 5 + "log/slog" 6 + "os" 7 + 8 + "github.com/bluesky-social/indigo/atproto/syntax" 9 + 10 + "github.com/urfave/cli/v2" 11 + ) 12 + 13 + func main() { 14 + app := cli.App{ 15 + Name: "atp-syntax", 16 + Usage: "informal debugging CLI tool for atproto syntax (identifiers)", 17 + } 18 + app.Commands = []*cli.Command{ 19 + &cli.Command{ 20 + Name: "parse-tid", 21 + Usage: "parse a TID and output timestamp", 22 + Action: runParseTID, 23 + }, 24 + } 25 + h := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelDebug}) 26 + slog.SetDefault(slog.New(h)) 27 + app.RunAndExitOnError() 28 + } 29 + 30 + func runParseTID(cctx *cli.Context) error { 31 + s := cctx.Args().First() 32 + if s == "" { 33 + return fmt.Errorf("need to provide identifier as an argument") 34 + } 35 + 36 + tid, err := syntax.ParseTID(s) 37 + if err != nil { 38 + return err 39 + } 40 + fmt.Printf("TID: %s\n", tid) 41 + fmt.Printf("Time: %s\n", tid.Time()) 42 + 43 + return nil 44 + }
+26
atproto/syntax/datetime.go
··· 50 50 return d.Time(), nil 51 51 } 52 52 53 + // Similar to ParseDatetime, but more flexible about some parsing. 54 + // 55 + // 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. 56 + func ParseDatetimeLenient(raw string) (Datetime, error) { 57 + // fast path: it is a valid overall datetime 58 + valid, err := ParseDatetime(raw) 59 + if nil == err { 60 + return valid, nil 61 + } 62 + 63 + if strings.HasSuffix(raw, "-00:00") { 64 + return ParseDatetime(strings.Replace(raw, "-00:00", "+00:00", 1)) 65 + } 66 + 67 + // try adding timezone if it is missing 68 + var hasTimezoneRegex = regexp.MustCompile(`^.*(([+-]\d\d:?\d\d)|[a-zA-Z])$`) 69 + if !hasTimezoneRegex.MatchString(raw) { 70 + withTZ, err := ParseDatetime(raw + "Z") 71 + if nil == err { 72 + return withTZ, nil 73 + } 74 + } 75 + 76 + return "", fmt.Errorf("Datetime could not be parsed, even leniently: %v", err) 77 + } 78 + 53 79 // Parses the Datetime string in to a golang [time.Time]. 54 80 // 55 81 // 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.
+29
atproto/syntax/datetime_test.go
··· 74 74 assert.NoError(scanner.Err()) 75 75 } 76 76 77 + func TestParseDatetimeLenient(t *testing.T) { 78 + assert := assert.New(t) 79 + 80 + valid := []string{ 81 + "1985-04-12T23:20:50.123Z", 82 + "1985-04-12T23:20:50.123", 83 + "2023-08-27T19:07:00.186173", 84 + "1985-04-12T23:20:50.123-00:00", 85 + "1985-04-12T23:20:50.123+00:00", 86 + } 87 + for _, s := range valid { 88 + _, err := ParseDatetimeLenient(s) 89 + assert.NoError(err) 90 + if err != nil { 91 + fmt.Println(s) 92 + } 93 + } 94 + 95 + invalid := []string{ 96 + "1985-04-", 97 + "", 98 + "blah", 99 + } 100 + for _, s := range invalid { 101 + _, err := ParseDatetimeLenient(s) 102 + assert.Error(err) 103 + } 104 + } 105 + 77 106 func TestDatetimeNow(t *testing.T) { 78 107 assert := assert.New(t) 79 108