Commit 568741bf32

568741bf3226b21a023ff5dcd22b00fa0047350c

parent: 1a274bec3b

Verified · cmc

cmc <hello@cleberg.net> · 2026-09-12 04:55 UTC

web: one timestamp format, with the zone named

when renders 2006-01-02 15:04 UTC on every page; commit, log,
compare, blame, snippet and settings pages use it instead of
date-only, ISO, or raw stored strings.

Ref #182
internal/httpd/compare.go +1 −1
@@ -69,7 +69,7 @@ func (s *Server) compare(w http.ResponseWriter, r *http.Request) {
6969 cr.Subject = parsed.Subject
7070 cr.AuthorName = names.name(parsed.AuthorEmail, parsed.AuthorName)
7171 cr.AuthorUser, _ = names.account(parsed.AuthorEmail)
72 cr.Date = time.Unix(parsed.AuthorUnix, 0).UTC().Format("2006-01-02")
72 cr.Date = time.Unix(parsed.AuthorUnix, 0).UTC().Format(time.RFC3339)
7373 }
7474 commits = append(commits, cr)
7575 }
internal/httpd/depspage_test.go +1 −1
@@ -27,7 +27,7 @@ func TestSettingsPageRendersDepsStatus(t *testing.T) {
2727 }
2828 page := sb.String()
2929 for _, want := range []string{
30 "2026-09-03T08:20:25Z", "golang.org/x/crypto", "v0.31.0", "v0.42.0",
30 "2026-09-03 08:20 UTC", "golang.org/x/crypto", "v0.31.0", "v0.42.0",
3131 `href="/krz/gitbay/issues/140"`,
3232 } {
3333 if !strings.Contains(page, want) {
internal/httpd/web.go +3 −3
@@ -860,7 +860,7 @@ func (s *Server) blame(w http.ResponseWriter, r *http.Request) {
860860 }
861861 date := h.Date
862862 if t, err := time.Parse(time.RFC3339, h.Date); err == nil {
863 date = t.Format("2006-01-02")
863 date = t.Format(time.RFC3339)
864864 }
865865 hv := hunkView{
866866 BlameHunk: gitutil.BlameHunk{SHA: h.SHA, AuthorName: h.AuthorName,
@@ -1513,7 +1513,7 @@ func (s *Server) log(w http.ResponseWriter, r *http.Request) {
15131513 rw.AuthorName = names.name(parsed.AuthorEmail, parsed.AuthorName)
15141514 rw.AuthorUser, _ = names.account(parsed.AuthorEmail)
15151515 rw.AuthorEmail = parsed.AuthorEmail
1516 rw.Date = time.Unix(parsed.AuthorUnix, 0).UTC().Format("2006-01-02")
1516 rw.Date = time.Unix(parsed.AuthorUnix, 0).UTC().Format(time.RFC3339)
15171517 }
15181518 rows = append(rows, rw)
15191519 }
@@ -1887,7 +1887,7 @@ func (s *Server) mr(w http.ResponseWriter, r *http.Request) {
18871887 cr.Subject = parsed.Subject
18881888 cr.AuthorName = mrNames.name(parsed.AuthorEmail, parsed.AuthorName)
18891889 cr.AuthorUser, _ = mrNames.account(parsed.AuthorEmail)
1890 cr.Date = time.Unix(parsed.AuthorUnix, 0).UTC().Format("2006-01-02")
1890 cr.Date = time.Unix(parsed.AuthorUnix, 0).UTC().Format(time.RFC3339)
18911891 }
18921892 commits = append(commits, cr)
18931893 }
internal/web/templates/blame.html +1 −1
@@ -13,7 +13,7 @@
1313{{range .Hunks}}<div class="blamehunk">
1414 <div class="blameinfo">
1515 <p class="subject"><a href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/commit/{{.SHA}}">{{.Summary}}</a></p>
16 <p class="meta"><code><a href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/commit/{{.SHA}}">{{.ShortSHA}}</a></code> <span title="{{.AuthorEmail}}">{{.AuthorName}}</span> · {{.Date}} {{template "sigbadge" .Sig}}</p>
16 <p class="meta"><code><a href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/commit/{{.SHA}}">{{.ShortSHA}}</a></code> <span title="{{.AuthorEmail}}">{{.AuthorName}}</span> · {{when .Date}} {{template "sigbadge" .Sig}}</p>
1717 </div>
1818 <pre class="blamecode">{{range .Numbered}}<span class="lineno">{{.N}}</span>{{.Text}}
1919{{end}}</pre>
internal/web/templates/commit.html +1 −1
@@ -5,7 +5,7 @@
55 <p class="meta"><code class="fullsha">{{.SHA}}</code></p>
66 {{if .Parents}}<p class="meta">parent{{if gt (len .Parents) 1}}s{{end}}:{{range .Parents}} <code><a href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/commit/{{.}}">{{short .}}</a></code>{{end}}</p>{{end}}
77 <p>{{template "sigbadge" .Sig}}{{range .Checks}} <span class="badge check-{{.State}}">{{.Context}}: {{.State}}</span>{{end}}</p>
8 <p class="meta">{{template "authorname" dict "Name" .AuthorName "User" .AuthorUser "Email" .AuthorEmail}} &lt;{{.AuthorEmail}}&gt; · {{.Date}}
8 <p class="meta">{{template "authorname" dict "Name" .AuthorName "User" .AuthorUser "Email" .AuthorEmail}} &lt;{{.AuthorEmail}}&gt; · {{when .Date}}
99 {{if .CommitterEmail}}<br>committer: &lt;{{.CommitterEmail}}&gt;{{end}}</p>
1010</div>
1111<pre class="message">{{.Message}}</pre>
internal/web/templates/compare.html +1 −1
@@ -6,7 +6,7 @@
66{{range .Commits}}<li>
77 <div class="commitmain">
88 <p class="subject"><a href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/commit/{{.SHA}}">{{.Subject}}</a></p>
9 <p class="meta">{{template "authorname" dict "Name" .AuthorName "User" .AuthorUser "Email" ""}} · {{.Date}}</p>
9 <p class="meta">{{template "authorname" dict "Name" .AuthorName "User" .AuthorUser "Email" ""}} · {{when .Date}}</p>
1010 </div>
1111 <span class="commitside">{{template "sigbadge" .Sig}} <code><a href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/commit/{{.SHA}}">{{.ShortSHA}}</a></code></span>
1212</li>{{end}}
internal/web/templates/log.html +1 −1
@@ -12,7 +12,7 @@
1212{{range .Commits}}{{$c := .}}<li>
1313 <div class="commitmain">
1414 <p class="subject"><a href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/commit/{{.SHA}}">{{.Subject}}</a></p>
15 <p class="meta">{{template "authorname" dict "Name" .AuthorName "User" .AuthorUser "Email" .AuthorEmail}} · {{.Date}}</p>
15 <p class="meta">{{template "authorname" dict "Name" .AuthorName "User" .AuthorUser "Email" .AuthorEmail}} · {{when .Date}}</p>
1616 </div>
1717 <div class="commitside">
1818 {{with .Check}}<a class="badge badge-{{.}}" href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/commit/{{$c.SHA}}" title="checks: {{.}}">{{.}}</a>{{end}}
internal/web/templates/mr.html +1 −1
@@ -62,7 +62,7 @@
6262{{range .Commits}}<li>
6363 <div class="commitmain">
6464 <p class="subject"><a href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/commit/{{.SHA}}">{{.Subject}}</a></p>
65 <p class="meta">{{template "authorname" dict "Name" .AuthorName "User" .AuthorUser "Email" ""}} · {{.Date}}</p>
65 <p class="meta">{{template "authorname" dict "Name" .AuthorName "User" .AuthorUser "Email" ""}} · {{when .Date}}</p>
6666 </div>
6767 <div class="commitside">
6868 {{template "sigbadge" .Sig}}
internal/web/templates/settings.html +2 −2
@@ -144,7 +144,7 @@ proxy.golang.org, npm, crates.io, and PyPI once a day, and tracks what is behind
144144in an issue. Checking a private repository tells those registries what it
145145depends on.</p>
146146{{if .DepsEnabled}}
147<p class="meta">Last checked {{if .Deps.LastCheck}}{{.Deps.LastCheck}}{{else}}never{{end}}{{if .Deps.IssueNumber}} · tracked in <a href="/{{.Repo.OwnerName}}/{{.Repo.Name}}/issues/{{.Deps.IssueNumber}}">#{{.Deps.IssueNumber}}</a>{{end}}</p>
147<p class="meta">Last checked {{if .Deps.LastCheck}}{{when .Deps.LastCheck}}{{else}}never{{end}}{{if .Deps.IssueNumber}} · tracked in <a href="/{{.Repo.OwnerName}}/{{.Repo.Name}}/issues/{{.Deps.IssueNumber}}">#{{.Deps.IssueNumber}}</a>{{end}}</p>
148148{{if .Deps.LastError}}<p class="error" role="alert">{{.Deps.LastError}}</p>{{end}}
149149{{if .Deps.Behind}}<div class="tablewrap"><table class="keys">
150150<tr class="cols"><th scope="col">dependency</th><th scope="col">pinned</th><th scope="col">latest</th></tr>
@@ -160,7 +160,7 @@ depends on.</p>
160160<h2>Runners</h2>
161161{{if .Runners}}
162162<ul class="protlist">
163{{range .Runners}}<li><code>{{.Fingerprint}}</code> <span class="meta">{{.Username}}{{if .LastSeen}}, last poll {{.LastSeen}}{{else}}, never polled{{end}}{{if .BuildNumber}}, running {{.BuildRepo}} #{{.BuildNumber}} {{.BuildJob}}{{end}}</span>
163{{range .Runners}}<li><code>{{.Fingerprint}}</code> <span class="meta">{{.Username}}{{if .LastSeen}}, last poll {{when .LastSeen}}{{else}}, never polled{{end}}{{if .BuildNumber}}, running {{.BuildRepo}} #{{.BuildNumber}} {{.BuildJob}}{{end}}</span>
164164 <form method="post" action="{{$base}}" class="inline">
165165 <input type="hidden" name="field" value="runner-remove">
166166 <input type="hidden" name="fingerprint" value="{{.Fingerprint}}">
internal/web/templates/snippet.html +1 −1
@@ -2,7 +2,7 @@
22{{define "content"}}
33<h1><a href="/{{.Owner}}">{{.Owner}}</a> / <a href="/{{.Owner}}/-/snippets">snippets</a> / {{.Snippet.PublicID}}</h1>
44{{if .Snippet.Description}}<p class="desc lede">{{.Snippet.Description}}</p>{{end}}
5<p class="meta"><span class="chip chip-neutral">{{.Snippet.Visibility}}</span> · updated {{.Snippet.UpdatedAt}} · <code>gitbay snippet show {{.Snippet.PublicID}}</code></p>
5<p class="meta"><span class="chip chip-neutral">{{.Snippet.Visibility}}</span> · updated {{when .Snippet.UpdatedAt}} · <code>gitbay snippet show {{.Snippet.PublicID}}</code></p>
66{{if .Notice}}<p class="error" role="alert">{{.Notice}}</p>{{end}}
77{{range .Files}}
88<section class="snippetfile" id="file-{{.Name}}">
internal/web/templates/snippets.html +1 −1
@@ -9,7 +9,7 @@
99 <td><a href="/{{$.Owner}}/-/snippets/{{.PublicID}}">{{if .Description}}{{.Description}}{{else}}{{.PublicID}}{{end}}</a></td>
1010 <td><span class="mono">{{.Names}}</span></td>
1111 {{if $.All}}<td><span class="chip chip-neutral">{{.Visibility}}</span></td>{{end}}
12 <td>{{.UpdatedAt}}</td>
12 <td>{{when .UpdatedAt}}</td>
1313</tr>
1414{{end}}</table></div>
1515{{else}}<p class="none">No snippets yet.</p>{{end}}
internal/web/templates/tree.html +2 −2
@@ -30,7 +30,7 @@
3030 <a class="subject" href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/commit/{{.SHA}}">{{.Subject}}</a>
3131 <span class="spacer"></span>
3232 <a class="sha" href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/commit/{{.SHA}}"><code>{{short .SHA}}</code></a>
33 <span class="age">{{ago .When}}</span>
33 <span class="age"{{if not .When.IsZero}} title="{{whenT .When}}"{{end}}>{{ago .When}}</span>
3434</div>{{end}}{{end}}
3535<div class="tablewrap">
3636<table class="tree">
@@ -39,7 +39,7 @@
3939 {{if eq .Type "tree"}}<td class="name dir"><a href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/tree/{{$.Ref}}/{{$.Prefix}}{{.Name}}">{{.Name}}/</a></td>
4040 {{else}}<td class="name"><a href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/blob/{{$.Ref}}/{{$.Prefix}}{{.Name}}">{{.Name}}</a></td>{{end}}
4141 <td class="lastcommit">{{with $c.Subject}}<a href="/{{$.Repo.OwnerName}}/{{$.Repo.Name}}/commit/{{$c.SHA}}" title="{{.}}">{{.}}</a>{{end}}</td>
42 <td class="age">{{ago $c.When}}</td>
42 <td class="age"{{if not $c.When.IsZero}} title="{{whenT $c.When}}"{{end}}>{{ago $c.When}}</td>
4343</tr>
4444{{else}}<tr><td class="name empty" colspan="3">this repository is empty — push something:<br><code>git remote add origin {{.CloneURL}}</code></td></tr>{{end}}
4545</table>
internal/web/web.go +6 −1
@@ -224,7 +224,12 @@ var funcs = template.FuncMap{
224224 if err != nil {
225225 return s
226226 }
227 return t.UTC().Format("2006-01-02 15:04")
227 return t.UTC().Format("2006-01-02 15:04 UTC")
228 },
229 // whenT is when for a value that is already a time.Time rather than
230 // a stored string.
231 "whenT": func(t time.Time) string {
232 return t.UTC().Format("2006-01-02 15:04 UTC")
228233 },
229234}
230235
internal/web/web_test.go +12
@@ -71,3 +71,15 @@ func TestHeaderRowsAreLeftAligned(t *testing.T) {
7171 }
7272 }
7373}
74
75// when names the zone rather than leaving an absolute time ambiguous, and
76// passes an unparseable value through unchanged (#182).
77func TestWhenNamesTheZone(t *testing.T) {
78 got := funcs["when"].(func(string) string)("2026-09-12T02:18:07.123Z")
79 if got != "2026-09-12 02:18 UTC" {
80 t.Fatalf("when: %q", got)
81 }
82 if got := funcs["when"].(func(string) string)("not a time"); got != "not a time" {
83 t.Fatalf("passthrough: %q", got)
84 }
85}