Skip to content

Commit

Permalink
Add commonly used models
Browse files Browse the repository at this point in the history
  • Loading branch information
markuswustenberg committed Sep 12, 2024
1 parent b4f6dee commit 6060739
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 0 deletions.
35 changes: 35 additions & 0 deletions model/email.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package model

import (
"regexp"
"strings"
)

// emailAddressMatcher for valid email addresses.
// See https://regex101.com/r/1BEPJo/latest for an interactive breakdown of the regexp.
// See https://html.spec.whatwg.org/#valid-e-mail-address for the definition.
var emailAddressMatcher = regexp.MustCompile(
// Start of string
`^` +
// Local part of the address. Note that \x60 is a backtick (`) character.
`(?P<local>[a-zA-Z0-9.!#$%&'*+/=?^_\x60{|}~-]+)` +
`@` +
// Domain of the address
`(?P<domain>[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+)` +
// End of string
`$`,
)

type Email string

func (e Email) IsValid() bool {
return emailAddressMatcher.MatchString(string(e))
}

func (e Email) String() string {
return string(e)
}

func (e Email) ToLower() Email {
return Email(strings.TrimSpace(strings.ToLower(string(e))))
}
31 changes: 31 additions & 0 deletions model/email_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package model_test

import (
"testing"

"maragu.dev/is"

"maragu.dev/goo/model"
)

func TestEmail_IsValid(t *testing.T) {
tests := []struct {
address string
valid bool
}{
{"[email protected]", true},
{"@example.com", false},
{"me@", false},
{"@", false},
{"", false},
{"me@example", false},
}
t.Run("reports valid email addresses", func(t *testing.T) {
for _, test := range tests {
t.Run(test.address, func(t *testing.T) {
e := model.Email(test.address)
is.Equal(t, test.valid, e.IsValid())
})
}
})
}
7 changes: 7 additions & 0 deletions model/model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package model

type ID string

func (i ID) String() string {
return string(i)
}
60 changes: 60 additions & 0 deletions model/time.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package model

import (
"database/sql/driver"
"fmt"
"time"
)

// rfc3339Milli is like time.RFC3339Nano, but with millisecond precision, and fractional seconds do not have trailing
// zeros removed.
const rfc3339Milli = "2006-01-02T15:04:05.000Z07:00"

type Time struct {
T time.Time
}

func (t *Time) String() string {
if t == nil {
return ""
}
return t.T.UTC().Format(rfc3339Milli)
}

func ParseTime(v string) (Time, error) {
t, err := time.Parse(rfc3339Milli, v)
if err != nil {
return Time{}, err
}
return Time{T: t}, nil
}

// Value satisfies driver.Valuer interface.
func (t Time) Value() (driver.Value, error) {
return t.T.UTC().Format(rfc3339Milli), nil
}

// Scan satisfies sql.Scanner interface.
func (t *Time) Scan(src any) error {
if src == nil {
return nil
}

s, ok := src.(string)
if !ok {
return fmt.Errorf("error scanning time, got %+v", src)
}

parsedT, err := time.Parse(rfc3339Milli, s)
if err != nil {
return err
}

t.T = parsedT.UTC()

return nil
}

func Now() *Time {
return &Time{T: time.Now()}
}

0 comments on commit 6060739

Please sign in to comment.