英文:
Computing time/duration in Golang templates
问题
我有一个通过template
渲染的结构体,例如:
type Foo struct {
Created time.Time
...
}
我将这个值传递给一个模板,我希望它被渲染成这样:
Created at 2022-11-22 9:50 (0d1h12m34s ago)
显示时间戳(并格式化它)很容易,但我找不到计算时间间隔的方法。
Created at {{.Created}} ({{???}} ago)
在Go中,可以通过time.Since(foo.Created)
来实现,它返回一个Duration
,然后可以以不同的方式将持续时间转换为字符串。
但是在模板本身中进行计算似乎是不可能的:
function "time" not defined
或者说呢?
我找不到任何明确告诉我time
(或其他任意函数)在模板中是绝对不允许的信息。所以我不知道我是不是调用方法不对。
(我知道我可以从Foo
创建一个新的FooTemplateValue
,添加该字段,这样模板就可以直接渲染持续时间。我只是想避免这样做,如果可能的话,直接使用实际的对象)。
英文:
I have a structure that gets rendered via template
. e.g.:
type Foo struct {
Created time.Time
...
}
I pass this value to a template, and I'd like to this rendered see:
Created at 2022-11-22 9:50 (0d1h12m34s ago)
Displaying the timestamp (and formatting it) is easy enough, but I can't find a way to calculate the interval.
Created at {{.Created}} ({{???}} ago)
In go, this would be accomplished by time.Since(foo.Created)
which returns a Duration
, and then I can convert duration to string in various ways.
But doing the calculation in the template itself does not seem possible:
function "time" not defined
Or is it?
Can't find any information that explicitly tells me that time
(or other arbitrary functions) are never ever allowed in templates. So I don't know if I'm just calling it wrong.
(I know I could create a new FooTemplateValue
from a Foo
add that field, so the template can render the duration as-is. I was just trying to avoid it if I can and use the actual object as-is).
答案1
得分: 1
你可以使用template.FuncMap
注册一个自定义模板函数,然后在模板中像调用内置函数一样调用该函数。
template.New("").Funcs(template.FuncMap{
"dur_until_now": func(t time.Time) time.Duration {
return time.Now().Sub(t)
},
}).Parse(`{{ dur_until_now .Created }}`)
https://go.dev/play/p/wM2f1oDFtDr
或者你可以声明一个自定义的时间类型,并使该类型实现一个生成所需值的方法,然后你可以在模板中直接在字段上调用该方法。
type MyTime struct{ time.Time }
func (t MyTime) DurUntilNow() time.Duration {
return time.Now().Sub(t.Time)
}
// ...
.Parse(`{{ .Created.DurUntilNow }}`)
https://go.dev/play/p/3faW4nTzK3-
英文:
You can register a custom template function using template.FuncMap
, then you can invoke that function inside the template just like you would invoke a builtin function.
template.New("").Funcs(template.FuncMap{
"dur_until_now": func(t time.Time) time.Duration {
return time.Now().Sub(t)
},
}).Parse(`{{ dur_until_now .Created }}`)
https://go.dev/play/p/wM2f1oDFtDr
Or you can declare a custom time type and have that type implement a method that produces the desired value, then you can invoke that method inside the template directly on the field.
type MyTime struct{ time.Time }
func (t MyTime) DurUntilNow() time.Duration {
return time.Now().Sub(t.Time)
}
// ...
.Parse(`{{ .Created.DurUntilNow }}`)
答案2
得分: -2
看起来你需要使用time.Now()来初始化Created字段。
package main
import (
"fmt"
"time"
)
type Foo struct {
Created time.Time
// ...
}
func main() {
x := Foo{Created: time.Now()}
fmt.Println(time.Since(x.Created))
}
请注意,以上代码是使用Go语言编写的。它定义了一个名为Foo的结构体,其中包含一个Created字段,类型为time.Time。在main函数中,我们创建了一个Foo类型的变量x,并使用time.Now()函数将当前时间赋值给了x的Created字段。最后,我们打印了从Created字段到当前时间的时间间隔。
英文:
Looks like you need to initialize the Created field with time.Now()
package main
import (
"fmt"
"time"
)
type Foo struct {
Created time.Time
// ...
}
func main() {
x := Foo{Created: time.Now()}
fmt.Println(time.Since(x.Created))
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论