【问题标题】:Execute formatted time in a slice with html/template使用 html/template 在切片中执行格式化时间
【发布时间】:2013-09-07 01:17:36
【问题描述】:

我正在制作一个可以托管我的博客的简单网络服务器,但无论我做什么;我无法在我的 html/模板中执行正确的格式化时间。

这是我的工作:

我已经创建了这个结构:

type Blogpost struct {
    Title   string
    Content string
    Date    time.Time
}

接下来我创建了这个小函数,它从 Appengine 数据存储中检索具有相应标题/日期的博文并将其作为切片返回:

func GetBlogs(r *http.Request, max int) []Blogpost {
    c := appengine.NewContext(r)
    q := datastore.NewQuery("Blogpost").Order("-Date").Limit(max)
    bp := make([]Blogpost, 0, max)
    q.GetAll(c, &bp)
    return bp
}

最后,在 blogHandler 中,我根据从 Appengine 数据存储区检索到的数据创建了一个切片:

blogs := GetBlogs(r, 10)

现在,当我像这样执行名为 blog 的模板时,博客的日期被解析为默认日期:

blog.Execute(w, blogs) // gives dates like: 2013-09-03 16:06:48 +0000 UTC

所以,作为 Golang n00b 的我,会说像下面这样的函数会给我想要的结果

blogs[0].Date = blogs[0].Date.Format("02-01-2006 15:04:05") // Would return like 03-09-2013 16:06:48, at least when you print the formatted date that is.

但是这会导致类型冲突,我尝试使用以下方法解决:

blogs[0].Date, _ = time.Parse("02-01-2006 15:04:05", blogs[0].Date.Format("02-01-2006 15:04:05")) // returns once again: 2013-09-03 16:06:48 +0000 UTC

这可能是我再次监督的一些 n00b 事情,但我只是看不出我不能覆盖时间。时间 输入一个切片或至少以我想要的格式打印它。

【问题讨论】:

  • 我感觉这个问题与在 .Execute 中使用接口作为参数而不是使用结构有关。但还不是 100% 确定。

标签: google-app-engine go


【解决方案1】:

虽然我正在寻找类似的功能来简单地格式化和渲染 html/template 中的 time.Time 类型,但我偶然发现 go 的模板解析器允许在渲染 time.Time 类型时在 certain restrictions 下调用方法。

例如;

type Post struct {
    Id        int
    Title     string
    CreatedOn time.Time
}

// post is a &Post. in my case, I fetched that from a postgresql
// table which has a datetime column for that field and
// value in db is 2015-04-04 20:51:48

template.Execute(w, post)

并且可以在如下模板中使用该时间:

<span>{{ .CreatedOn }}</span>
<!-- Outputs: 2015-04-04 20:51:48 +0000 +0000 -->

<span>{{ .CreatedOn.Format "2006 Jan 02" }}</span>
<!-- Outputs: 2015 Apr 04 -->

<span>{{ .CreatedOn.Format "Jan 02, 2006" }}</span>
<!-- Outputs: Apr 04, 2015 -->

<span>{{.CreatedOn.Format "Jan 02, 2006 15:04:05 UTC" }}</span>
<!-- Outputs: Apr 04, 2015 20:51:48 UTC -->

作为注释;我的 go 版本是go1.4.2 darwin/amd64

希望对他人有所帮助。

【讨论】:

  • 作为一个 Go 新手,这对我来说并不明显。注意Mon Jan 2 15:04:05 MST 2006 是 Go 时间格式的特殊字符串值。通过将确切的日期值重新排列为格式参数,您可以获得各种日期格式。然后您的日期将以这种方式格式化,例如如果今天是 2019 年 12 月 15 日,并且您使用格式字符串 01/02/2006,则生成的字符串将为 12/15/2019。同样,如果您使用格式字符串Jan 2, 2006,则生成的字符串将为Dec 15, 2019 golang.org/pkg/time/#pkg-constants
【解决方案2】:

您的Date 字段的类型为time.Time。如果将其格式化为字符串并将其解析回来,您将再次获得time.Time 值,当模板执行调用其String 方法时,该值仍将打印默认方式,因此它并不能真正解决您的问题.

解决方法是为模板提供格式化的时间字符串本身而不是时间值,您可以通过多种方式做到这一点。例如:

  • 为您的博客文章类型添加一个名为FormattedDate 或类似名称的方法,该方法返回一个格式正确的字符串,格式符合您的偏好。如果您没有花哨的用例,这是最简单的,也可能是最好的方法。

  • 在您的博客类型中添加一个名为FormattedDate 或类似名称的字符串字段;这与上面的选项非常相似,但是您必须在必要时小心设置和更新字段,所以我更喜欢方法选项。

  • 如果您想在模板中以多种方式格式化时间值,您还可以选择定义模板格式化程序函数,这样您就可以执行{{post.Date | fdate "02-01-2006 15:04:05"}} 之类的操作。有关如何执行此操作的详细信息,请参阅Template.FuncsFuncMap typethis example 上的文档。

更新:第一个选项的示例代码:http://play.golang.org/p/3QYdrDQ1YO

【讨论】:

  • 多么好的答案。精彩的。谢谢古斯塔沃
  • 您不会使用模板文件测试您的示例:play.golang.org/p/3QYdrDQ1YO。对于模板文件,您应该使用:func (post BlogPost) FormattedDate() string 而不是 func (post *BlogPost) FormattedDate() string
  • 这与是否是模板文件无关。当然,有一个引擎可以解释这两种情况。这是关于您如何使您的数据可用于模板。使用引用而不是值。
  • 三个选项中的最后一个,不需要定义自定义函数fdate。模板管道可以包含方法调用,所以你可以写{{ post.Date.Format "02-01-2006" }}
【解决方案3】:

如果您在模板中输出 time.Time,它将被转换为字符串。此默认转换就是您所看到的。如果您需要不同的格式,您有两种可能:

  1. 在您的博文中添加一个 `FormatedDate 字符串字段,并通过 Date.Format(whatever) 从 Date 填充它
  2. 在您的模板中编写并注册一个格式化过滤器`(参见http://golang.org/pkg/html/template/#Template.Funcs)并使用它。

【讨论】:

  • 古斯塔沃斯的回答更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-16
  • 2015-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多