Skip to content

Commit

Permalink
fix(date): use available timezone if any
Browse files Browse the repository at this point in the history
  • Loading branch information
ccoVeille committed Nov 29, 2024
1 parent 138eddd commit 39a04c1
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 25 deletions.
39 changes: 24 additions & 15 deletions registry/time/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ import (
//
// {{ "2023-05-04T15:04:05Z" | date "Jan 2, 2006" }} // Output: "May 4, 2023"
func (tr *TimeRegistry) Date(fmt string, date any) (string, error) {
return tr.DateInZone(fmt, date, "Local")
t := computeTimeFromFormat(date)

// compute the timezone from the date if it has one
loc := time.FixedZone(t.Zone())

return t.In(loc).Format(fmt), nil
}

// DateInZone formats a given date or current time into a specified format string in a specified timezone.
Expand All @@ -44,28 +49,32 @@ func (tr *TimeRegistry) Date(fmt string, date any) (string, error) {
//
// TODO: Change signature
func (tr *TimeRegistry) DateInZone(fmt string, date any, zone string) (string, error) {
var t time.Time
t := computeTimeFromFormat(date)
loc, err := time.LoadLocation(zone)
if err != nil {
return t.In(time.UTC).Format(fmt), err
}

return t.In(loc).Format(fmt), nil
}

// computeTimeFromFormat returns a time.Time object from the given date.
func computeTimeFromFormat(date any) time.Time {
switch date := date.(type) {
default:
t = time.Now()
case time.Time:
t = date
return date
case *time.Time:
t = *date
return *date
case int64:
t = time.Unix(date, 0)
return time.Unix(date, 0)
case int:
t = time.Unix(int64(date), 0)
return time.Unix(int64(date), 0)
case int32:
t = time.Unix(int64(date), 0)
return time.Unix(int64(date), 0)
}

loc, err := time.LoadLocation(zone)
if err != nil {
return t.In(time.UTC).Format(fmt), err
}

return t.In(loc).Format(fmt), nil
// otherwise, fallback to the current time, in current timezone
return time.Now()
}

// Duration converts seconds into a human-readable duration string.
Expand Down
86 changes: 76 additions & 10 deletions registry/time/functions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,83 @@ import (
"github.com/go-sprout/sprout/registry/time"
)

func TestDate(t *testing.T) {
timeTest := goTime.Date(2024, 5, 7, 15, 4, 5, 0, goTime.UTC)
// forceTimeLocal temporarily sets [time.Local] for test purpose
func forceTimeLocal(t *testing.T, local *goTime.Location) {
t.Helper()

tc := []pesticide.TestCase{
{Name: "TestTimeObject", Input: `{{ .V | date "02 Jan 06 15:04 -0700" }}`, ExpectedOutput: "07 May 24 15:04 +0000", Data: map[string]any{"V": timeTest}},
{Name: "TestTimeObjectPointer", Input: `{{ .V | date "02 Jan 06 15:04 -0700" }}`, ExpectedOutput: "07 May 24 15:04 +0000", Data: map[string]any{"V": &timeTest}},
{Name: "TestTimeObjectUnix", Input: `{{ .V | date "02 Jan 06 15:04 -0700" }}`, ExpectedOutput: "07 May 24 15:04 +0000", Data: map[string]any{"V": timeTest.Unix()}},
{Name: "TestTimeObjectUnixInt", Input: `{{ .V | date "02 Jan 06 15:04 -0700" }}`, ExpectedOutput: "07 May 24 15:04 +0000", Data: map[string]any{"V": int(timeTest.Unix())}},
}
originalLocal := goTime.Local
goTime.Local = local
t.Cleanup(func() { goTime.Local = originalLocal })
}

pesticide.RunTestCases(t, time.NewRegistry(), tc)
func TestDate(t *testing.T) {
t.Run("UTC", func(t *testing.T) {
timeTest := goTime.Date(2024, 5, 7, 15, 4, 5, 0, goTime.UTC)
tc := []pesticide.TestCase{
{Name: "TestTimeObject", Input: `{{ .V | date "02 Jan 06 15:04 -0700" }}`, ExpectedOutput: "07 May 24 15:04 +0000", Data: map[string]any{"V": timeTest}},
{Name: "TestTimeObjectPointer", Input: `{{ .V | date "02 Jan 06 15:04 -0700" }}`, ExpectedOutput: "07 May 24 15:04 +0000", Data: map[string]any{"V": &timeTest}},
}

pesticide.RunTestCases(t, time.NewRegistry(), tc)
})

t.Run("New York timezone", func(t *testing.T) {
local, err := goTime.LoadLocation("America/New_York")
if err != nil {
t.Fatal(err)
}
timeTest := goTime.Date(2024, 5, 7, 15, 4, 5, 0, local)

tc := []pesticide.TestCase{
{Name: "TestTimeObject", Input: `{{ .V | date "02 Jan 06 15:04 -0700" }}`, ExpectedOutput: "07 May 24 15:04 -0400", Data: map[string]any{"V": timeTest}},
{Name: "TestTimeObjectPointer", Input: `{{ .V | date "02 Jan 06 15:04 -0700" }}`, ExpectedOutput: "07 May 24 15:04 -0400", Data: map[string]any{"V": &timeTest}},
}

pesticide.RunTestCases(t, time.NewRegistry(), tc)
})

t.Run("New York offset", func(t *testing.T) {
timeTest, err := goTime.Parse("02 Jan 06 15:04 -0700", "07 May 24 15:04 -0400")
if err != nil {
t.Fatal(err)
}

tc := []pesticide.TestCase{
{Name: "TestTimeObject", Input: `{{ .V | date "02 Jan 06 15:04 -0700" }}`, ExpectedOutput: "07 May 24 15:04 -0400", Data: map[string]any{"V": timeTest}},
{Name: "TestTimeObjectPointer", Input: `{{ .V | date "02 Jan 06 15:04 -0700" }}`, ExpectedOutput: "07 May 24 15:04 -0400", Data: map[string]any{"V": &timeTest}},
}

pesticide.RunTestCases(t, time.NewRegistry(), tc)
})

t.Run("New York timezone", func(t *testing.T) {
local, err := goTime.LoadLocation("America/New_York")
if err != nil {
t.Fatal(err)
}
timeTest := goTime.Date(2024, 5, 7, 15, 4, 5, 0, local)

tc := []pesticide.TestCase{
{Name: "TestTimeObject", Input: `{{ .V | date "02 Jan 06 15:04 -0700" }}`, ExpectedOutput: "07 May 24 15:04 -0400", Data: map[string]any{"V": timeTest}},
{Name: "TestTimeObjectPointer", Input: `{{ .V | date "02 Jan 06 15:04 -0700" }}`, ExpectedOutput: "07 May 24 15:04 -0400", Data: map[string]any{"V": &timeTest}},
}

pesticide.RunTestCases(t, time.NewRegistry(), tc)
})

t.Run("unixtime", func(t *testing.T) {
timeTest := goTime.Date(2024, 5, 7, 15, 4, 5, 0, goTime.UTC)

// temporarily force UTC
forceTimeLocal(t, goTime.UTC)

tc := []pesticide.TestCase{
{Name: "TestTimeObjectUnix", Input: `{{ .V | date "02 Jan 06 15:04 -0700" }}`, ExpectedOutput: "07 May 24 15:04 +0000", Data: map[string]any{"V": timeTest.Unix()}},
{Name: "TestTimeObjectUnixInt", Input: `{{ .V | date "02 Jan 06 15:04 -0700" }}`, ExpectedOutput: "07 May 24 15:04 +0000", Data: map[string]any{"V": int(timeTest.Unix())}},
}

pesticide.RunTestCases(t, time.NewRegistry(), tc)
})
}

func TestDateInZone(t *testing.T) {
Expand All @@ -30,7 +96,7 @@ func TestDateInZone(t *testing.T) {
{Name: "TestTimeObjectUnix", Input: `{{ dateInZone "02 Jan 06 15:04 -0700" .V "UTC" }}`, ExpectedOutput: "07 May 24 15:04 +0000", Data: map[string]any{"V": timeTest.Unix()}},
{Name: "TestTimeObjectUnixInt", Input: `{{ dateInZone "02 Jan 06 15:04 -0700" .V "UTC" }}`, ExpectedOutput: "07 May 24 15:04 +0000", Data: map[string]any{"V": int(timeTest.Unix())}},
{Name: "TestTimeObjectUnixInt", Input: `{{ dateInZone "02 Jan 06 15:04 -0700" .V "UTC" }}`, ExpectedOutput: "07 May 24 15:04 +0000", Data: map[string]any{"V": int32(timeTest.Unix())}},
{Name: "TestWithInvalidInput", Input: `{{ dateInZone "02 Jan 06 15:04 -0700" .V "UTC" }}`, ExpectedOutput: goTime.Now().Format("02 Jan 06 15:04 -0700"), Data: map[string]any{"V": "invalid"}},
{Name: "TestWithInvalidInput", Input: `{{ dateInZone "02 Jan 06 15:04 -0700" .V "UTC" }}`, ExpectedOutput: goTime.Now().UTC().Format("02 Jan 06 15:04 -0700"), Data: map[string]any{"V": "invalid"}},
{Name: "TestWithInvalidZone", Input: `{{ dateInZone "02 Jan 06 15:04 -0700" .V "invalid" }}`, ExpectedErr: "unknown time zone invalid", Data: map[string]any{"V": timeTest}},
}

Expand Down

0 comments on commit 39a04c1

Please sign in to comment.