loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request '[PORT] Replace DateTime with proper functions (gitea#32402)' (#5796) from gusted/forgejo-port-dateutils into forgejo

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5796
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Reviewed-by: Otto <otto@codeberg.org>

Otto f28e7283 cd0ac418

+174 -110
+2 -1
modules/templates/helper.go
··· 52 52 "StringUtils": NewStringUtils, 53 53 "SliceUtils": NewSliceUtils, 54 54 "JsonUtils": NewJsonUtils, 55 + "DateUtils": NewDateUtils, 55 56 56 57 // ----------------------------------------------------------------- 57 58 // svg / avatar / icon / color ··· 68 69 "CountFmt": base.FormatNumberSI, 69 70 "TimeSince": timeutil.TimeSince, 70 71 "TimeSinceUnix": timeutil.TimeSinceUnix, 71 - "DateTime": timeutil.DateTime, 72 + "DateTime": dateTimeLegacy, // for backward compatibility only, do not use it anymore 72 73 "Sec2Time": util.SecToTime, 73 74 "LoadTimes": func(startTime time.Time) string { 74 75 return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms"
+60
modules/templates/util_date.go
··· 1 + // Copyright 2024 The Gitea Authors. All rights reserved. 2 + // SPDX-License-Identifier: MIT 3 + 4 + package templates 5 + 6 + import ( 7 + "context" 8 + "html/template" 9 + "time" 10 + 11 + "code.gitea.io/gitea/modules/setting" 12 + "code.gitea.io/gitea/modules/timeutil" 13 + ) 14 + 15 + type DateUtils struct { 16 + ctx context.Context 17 + } 18 + 19 + func NewDateUtils(ctx context.Context) *DateUtils { 20 + return &DateUtils{ctx} 21 + } 22 + 23 + // AbsoluteShort renders in "Jan 01, 2006" format 24 + func (du *DateUtils) AbsoluteShort(time any) template.HTML { 25 + return timeutil.DateTime("short", time) 26 + } 27 + 28 + // AbsoluteLong renders in "January 01, 2006" format 29 + func (du *DateUtils) AbsoluteLong(time any) template.HTML { 30 + return timeutil.DateTime("long", time) 31 + } 32 + 33 + // FullTime renders in "Jan 01, 2006 20:33:44" format 34 + func (du *DateUtils) FullTime(time any) template.HTML { 35 + return timeutil.DateTime("full", time) 36 + } 37 + 38 + // ParseLegacy parses the datetime in legacy format, eg: "2016-01-02" in server's timezone. 39 + // It shouldn't be used in new code. New code should use Time or TimeStamp as much as possible. 40 + func (du *DateUtils) ParseLegacy(datetime string) time.Time { 41 + return parseLegacy(datetime) 42 + } 43 + 44 + func parseLegacy(datetime string) time.Time { 45 + t, err := time.Parse(time.RFC3339, datetime) 46 + if err != nil { 47 + t, _ = time.ParseInLocation(time.DateOnly, datetime, setting.DefaultUILocation) 48 + } 49 + return t 50 + } 51 + 52 + func dateTimeLegacy(format string, datetime any, _ ...string) template.HTML { 53 + if !setting.IsProd || setting.IsInTesting { 54 + panic("dateTimeLegacy is for backward compatibility only, do not use it in new code") 55 + } 56 + if s, ok := datetime.(string); ok { 57 + datetime = parseLegacy(s) 58 + } 59 + return timeutil.DateTime(format, datetime) 60 + }
+61
modules/templates/util_date_test.go
··· 1 + // Copyright 2023 The Gitea Authors. All rights reserved. 2 + // SPDX-License-Identifier: MIT 3 + 4 + package templates 5 + 6 + import ( 7 + "html/template" 8 + "testing" 9 + "time" 10 + 11 + "code.gitea.io/gitea/modules/setting" 12 + "code.gitea.io/gitea/modules/test" 13 + "code.gitea.io/gitea/modules/timeutil" 14 + 15 + "github.com/stretchr/testify/assert" 16 + "github.com/stretchr/testify/require" 17 + ) 18 + 19 + func TestDateTime(t *testing.T) { 20 + testTz, err := time.LoadLocation("America/New_York") 21 + require.NoError(t, err) 22 + defer test.MockVariableValue(&setting.DefaultUILocation, testTz)() 23 + defer test.MockVariableValue(&setting.IsInTesting, false)() 24 + 25 + du := NewDateUtils(nil) 26 + 27 + refTimeStr := "2018-01-01T00:00:00Z" 28 + refDateStr := "2018-01-01" 29 + refTime, _ := time.Parse(time.RFC3339, refTimeStr) 30 + refTimeStamp := timeutil.TimeStamp(refTime.Unix()) 31 + 32 + for _, val := range []any{nil, 0, time.Time{}, timeutil.TimeStamp(0)} { 33 + for _, fun := range []func(val any) template.HTML{du.AbsoluteLong, du.AbsoluteShort, du.FullTime} { 34 + assert.EqualValues(t, "-", fun(val)) 35 + } 36 + } 37 + 38 + actual := dateTimeLegacy("short", "invalid") 39 + assert.EqualValues(t, `-`, actual) 40 + 41 + actual = dateTimeLegacy("short", refTimeStr) 42 + assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2018-01-01T00:00:00Z">2018-01-01</absolute-date>`, actual) 43 + 44 + actual = du.AbsoluteShort(refTime) 45 + assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2018-01-01T00:00:00Z">2018-01-01</absolute-date>`, actual) 46 + 47 + actual = du.AbsoluteLong(refTime) 48 + assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="long" day="numeric" date="2018-01-01T00:00:00Z">2018-01-01</absolute-date>`, actual) 49 + 50 + actual = dateTimeLegacy("short", refDateStr) 51 + assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2018-01-01T00:00:00-05:00">2018-01-01</absolute-date>`, actual) 52 + 53 + actual = du.AbsoluteShort(refTimeStamp) 54 + assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2017-12-31T19:00:00-05:00">2017-12-31</absolute-date>`, actual) 55 + 56 + actual = du.AbsoluteLong(refTimeStamp) 57 + assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="long" day="numeric" date="2017-12-31T19:00:00-05:00">2017-12-31</absolute-date>`, actual) 58 + 59 + actual = du.FullTime(refTimeStamp) 60 + assert.EqualValues(t, `<relative-time weekday="" year="numeric" format="datetime" month="short" day="numeric" hour="numeric" minute="numeric" second="numeric" data-tooltip-content data-tooltip-interactive="true" datetime="2017-12-31T19:00:00-05:00">2017-12-31 19:00:00 -05:00</relative-time>`, actual) 61 + }
+2 -10
modules/timeutil/datetime.go
··· 12 12 ) 13 13 14 14 // DateTime renders an absolute time HTML element by datetime. 15 - func DateTime(format string, datetime any, extraAttrs ...string) template.HTML { 16 - // TODO: remove the extraAttrs argument, it's not used in any call to DateTime 17 - 15 + func DateTime(format string, datetime any) template.HTML { 18 16 if p, ok := datetime.(*time.Time); ok { 19 17 datetime = *p 20 18 } ··· 34 32 switch v := datetime.(type) { 35 33 case nil: 36 34 return "-" 37 - case string: 38 - datetimeEscaped = html.EscapeString(v) 39 - textEscaped = datetimeEscaped 40 35 case time.Time: 41 36 if v.IsZero() || v.Unix() == 0 { 42 37 return "-" ··· 51 46 panic(fmt.Sprintf("Unsupported time type %T", datetime)) 52 47 } 53 48 54 - attrs := make([]string, 0, 10+len(extraAttrs)) 55 - attrs = append(attrs, extraAttrs...) 56 - attrs = append(attrs, `weekday=""`, `year="numeric"`) 57 - 49 + attrs := []string{`weekday=""`, `year="numeric"`} 58 50 switch format { 59 51 case "short", "long": // date only 60 52 attrs = append(attrs, `month="`+format+`"`, `day="numeric"`)
-47
modules/timeutil/datetime_test.go
··· 1 - // Copyright 2023 The Gitea Authors. All rights reserved. 2 - // SPDX-License-Identifier: MIT 3 - 4 - package timeutil 5 - 6 - import ( 7 - "testing" 8 - "time" 9 - 10 - "code.gitea.io/gitea/modules/setting" 11 - "code.gitea.io/gitea/modules/test" 12 - 13 - "github.com/stretchr/testify/assert" 14 - ) 15 - 16 - func TestDateTime(t *testing.T) { 17 - testTz, _ := time.LoadLocation("America/New_York") 18 - defer test.MockVariableValue(&setting.DefaultUILocation, testTz)() 19 - 20 - refTimeStr := "2018-01-01T00:00:00Z" 21 - refDateStr := "2018-01-01" 22 - refTime, _ := time.Parse(time.RFC3339, refTimeStr) 23 - refTimeStamp := TimeStamp(refTime.Unix()) 24 - 25 - assert.EqualValues(t, "-", DateTime("short", nil)) 26 - assert.EqualValues(t, "-", DateTime("short", 0)) 27 - assert.EqualValues(t, "-", DateTime("short", time.Time{})) 28 - assert.EqualValues(t, "-", DateTime("short", TimeStamp(0))) 29 - 30 - actual := DateTime("short", "invalid") 31 - assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="invalid">invalid</absolute-date>`, actual) 32 - 33 - actual = DateTime("short", refTimeStr) 34 - assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2018-01-01T00:00:00Z">2018-01-01T00:00:00Z</absolute-date>`, actual) 35 - 36 - actual = DateTime("short", refTime) 37 - assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2018-01-01T00:00:00Z">2018-01-01</absolute-date>`, actual) 38 - 39 - actual = DateTime("short", refDateStr) 40 - assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2018-01-01">2018-01-01</absolute-date>`, actual) 41 - 42 - actual = DateTime("short", refTimeStamp) 43 - assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2017-12-31T19:00:00-05:00">2017-12-31</absolute-date>`, actual) 44 - 45 - actual = DateTime("full", refTimeStamp) 46 - assert.EqualValues(t, `<relative-time weekday="" year="numeric" format="datetime" month="short" day="numeric" hour="numeric" minute="numeric" second="numeric" data-tooltip-content data-tooltip-interactive="true" datetime="2017-12-31T19:00:00-05:00">2017-12-31 19:00:00 -05:00</relative-time>`, actual) 47 - }
+2 -2
routers/web/repo/activity.go
··· 48 48 ctx.Data["Period"] = "weekly" 49 49 timeFrom = timeUntil.Add(-time.Hour * 168) 50 50 } 51 - ctx.Data["DateFrom"] = timeFrom.UTC().Format(time.RFC3339) 52 - ctx.Data["DateUntil"] = timeUntil.UTC().Format(time.RFC3339) 51 + ctx.Data["DateFrom"] = timeFrom 52 + ctx.Data["DateUntil"] = timeUntil 53 53 ctx.Data["PeriodText"] = ctx.Tr("repo.activity.period." + ctx.Data["Period"].(string)) 54 54 55 55 var err error
+1
services/context/context.go
··· 102 102 tmplCtx := NewTemplateContext(ctx) 103 103 tmplCtx["Locale"] = ctx.Base.Locale 104 104 tmplCtx["AvatarUtils"] = templates.NewAvatarUtils(ctx) 105 + tmplCtx["DateUtils"] = templates.NewDateUtils(ctx) 105 106 return tmplCtx 106 107 } 107 108
+2 -2
templates/admin/auth/list.tmpl
··· 26 26 <td><a href="{{AppSubUrl}}/admin/auths/{{.ID}}">{{.Name}}</a></td> 27 27 <td>{{.TypeName}}</td> 28 28 <td>{{if .IsActive}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td> 29 - <td>{{DateTime "short" .UpdatedUnix}}</td> 30 - <td>{{DateTime "short" .CreatedUnix}}</td> 29 + <td>{{ctx.DateUtils.AbsoluteShort .UpdatedUnix}}</td> 30 + <td>{{ctx.DateUtils.AbsoluteShort .CreatedUnix}}</td> 31 31 <td><a href="{{AppSubUrl}}/admin/auths/{{.ID}}">{{svg "octicon-pencil"}}</a></td> 32 32 </tr> 33 33 {{end}}
+2 -2
templates/admin/cron.tmpl
··· 23 23 <td><button type="submit" class="ui primary button" name="op" value="{{.Name}}" title="{{ctx.Locale.Tr "admin.dashboard.operation_run"}}">{{svg "octicon-triangle-right"}}</button></td> 24 24 <td>{{ctx.Locale.Tr (printf "admin.dashboard.%s" .Name)}}</td> 25 25 <td>{{.Spec}}</td> 26 - <td>{{DateTime "full" .Next}}</td> 27 - <td>{{if gt .Prev.Year 1}}{{DateTime "full" .Prev}}{{else}}-{{end}}</td> 26 + <td>{{ctx.DateUtils.FullTime .Next}}</td> 27 + <td>{{if gt .Prev.Year 1}}{{ctx.DateUtils.FullTime .Prev}}{{else}}-{{end}}</td> 28 28 <td>{{.ExecTimes}}</td> 29 29 <td {{if ne .Status ""}}data-tooltip-content="{{.FormatLastMessage ctx.Locale}}"{{end}} >{{if eq .Status ""}}—{{else if eq .Status "finished"}}{{svg "octicon-check" 16}}{{else}}{{svg "octicon-x" 16}}{{end}}</td> 30 30 </tr>
+1 -1
templates/admin/notice.tmpl
··· 21 21 <td>{{.ID}}</td> 22 22 <td>{{ctx.Locale.Tr .TrStr}}</td> 23 23 <td class="view-detail auto-ellipsis tw-w-4/5"><span class="notice-description">{{.Description}}</span></td> 24 - <td nowrap>{{DateTime "short" .CreatedUnix}}</td> 24 + <td nowrap>{{ctx.DateUtils.AbsoluteShort .CreatedUnix}}</td> 25 25 <td class="view-detail"><a href="#">{{svg "octicon-note" 16}}</a></td> 26 26 </tr> 27 27 {{end}}
+1 -1
templates/admin/org/list.tmpl
··· 63 63 <td>{{.NumTeams}}</td> 64 64 <td>{{.NumMembers}}</td> 65 65 <td>{{.NumRepos}}</td> 66 - <td>{{DateTime "short" .CreatedUnix}}</td> 66 + <td>{{ctx.DateUtils.AbsoluteShort .CreatedUnix}}</td> 67 67 <td><a href="{{.OrganisationLink}}/settings" data-tooltip-content="{{ctx.Locale.Tr "edit"}}">{{svg "octicon-pencil"}}</a></td> 68 68 </tr> 69 69 {{end}}
+1 -1
templates/admin/packages/list.tmpl
··· 71 71 {{end}} 72 72 </td> 73 73 <td>{{ctx.Locale.TrSize .CalculateBlobSize}}</td> 74 - <td>{{DateTime "short" .Version.CreatedUnix}}</td> 74 + <td>{{ctx.DateUtils.AbsoluteShort .Version.CreatedUnix}}</td> 75 75 <td><a class="delete-button" href="" data-url="{{$.Link}}/delete?page={{$.Page.Paginater.Current}}&sort={{$.SortType}}" data-id="{{.Version.ID}}" data-name="{{.Package.Name}}" data-data-version="{{.Version.Version}}">{{svg "octicon-trash"}}</a></td> 76 76 </tr> 77 77 {{end}}
+2 -2
templates/admin/repo/list.tmpl
··· 82 82 <td>{{.NumIssues}}</td> 83 83 <td>{{ctx.Locale.TrSize .GitSize}}</td> 84 84 <td>{{ctx.Locale.TrSize .LFSSize}}</td> 85 - <td>{{DateTime "short" .UpdatedUnix}}</td> 86 - <td>{{DateTime "short" .CreatedUnix}}</td> 85 + <td>{{ctx.DateUtils.AbsoluteShort .UpdatedUnix}}</td> 86 + <td>{{ctx.DateUtils.AbsoluteShort .CreatedUnix}}</td> 87 87 <td><a class="delete-button" href="" data-url="{{$.Link}}/delete?page={{$.Page.Paginater.Current}}&sort={{$.SortType}}" data-id="{{.ID}}" data-name="{{.Name}}">{{svg "octicon-trash"}}</a></td> 88 88 </tr> 89 89 {{end}}
+2 -2
templates/admin/user/list.tmpl
··· 96 96 <td>{{if .IsActive}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td> 97 97 <td>{{if .IsRestricted}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td> 98 98 <td>{{if index $.UsersTwoFaStatus .ID}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td> 99 - <td>{{DateTime "short" .CreatedUnix}}</td> 99 + <td>{{ctx.DateUtils.AbsoluteShort .CreatedUnix}}</td> 100 100 {{if .LastLoginUnix}} 101 - <td>{{DateTime "short" .LastLoginUnix}}</td> 101 + <td>{{ctx.DateUtils.AbsoluteShort .LastLoginUnix}}</td> 102 102 {{else}} 103 103 <td><span>{{ctx.Locale.Tr "admin.users.never_login"}}</span></td> 104 104 {{end}}
+1 -1
templates/explore/user_list.tmpl
··· 21 21 <a href="mailto:{{.Email}}">{{.Email}}</a> 22 22 </span> 23 23 {{end}} 24 - <span class="flex-text-inline">{{svg "octicon-calendar"}}{{ctx.Locale.Tr "user.joined_on" (DateTime "short" .CreatedUnix)}}</span> 24 + <span class="flex-text-inline">{{svg "octicon-calendar"}}{{ctx.Locale.Tr "user.joined_on" (ctx.DateUtils.AbsoluteShort .CreatedUnix)}}</span> 25 25 </div> 26 26 </div> 27 27 </div>
+1 -1
templates/package/shared/cleanup_rules/preview.tmpl
··· 22 22 <td><a href="{{.VersionWebLink}}">{{.Version.Version}}</a></td> 23 23 <td><a href="{{.Creator.HomeLink}}">{{.Creator.Name}}</a></td> 24 24 <td>{{ctx.Locale.TrSize .CalculateBlobSize}}</td> 25 - <td>{{DateTime "short" .Version.CreatedUnix}}</td> 25 + <td>{{ctx.DateUtils.AbsoluteShort .Version.CreatedUnix}}</td> 26 26 </tr> 27 27 {{else}} 28 28 <tr>
+1 -1
templates/package/view.tmpl
··· 94 94 {{range .LatestVersions}} 95 95 <div class="item tw-flex"> 96 96 <a class="tw-flex-1 gt-ellipsis" title="{{.Version}}" href="{{$.PackageDescriptor.PackageWebLink}}/{{PathEscape .LowerVersion}}">{{.Version}}</a> 97 - <span class="text small">{{DateTime "short" .CreatedUnix}}</span> 97 + <span class="text small">{{ctx.DateUtils.AbsoluteShort .CreatedUnix}}</span> 98 98 </div> 99 99 {{end}} 100 100 </div>
+1 -1
templates/repo/diff/compare.tmpl
··· 212 212 {{if .Repository.ArchivedUnix.IsZero}} 213 213 {{ctx.Locale.Tr "repo.archive.title"}} 214 214 {{else}} 215 - {{ctx.Locale.Tr "repo.archive.title_date" (DateTime "long" .Repository.ArchivedUnix)}} 215 + {{ctx.Locale.Tr "repo.archive.title_date" (ctx.DateUtils.AbsoluteLong .Repository.ArchivedUnix)}} 216 216 {{end}} 217 217 </div> 218 218 {{end}}
+1 -1
templates/repo/empty.tmpl
··· 10 10 {{if .Repository.ArchivedUnix.IsZero}} 11 11 {{ctx.Locale.Tr "repo.archive.title"}} 12 12 {{else}} 13 - {{ctx.Locale.Tr "repo.archive.title_date" (DateTime "long" .Repository.ArchivedUnix)}} 13 + {{ctx.Locale.Tr "repo.archive.title_date" (ctx.DateUtils.AbsoluteLong .Repository.ArchivedUnix)}} 14 14 {{end}} 15 15 </div> 16 16 {{end}}
+1 -1
templates/repo/graph/commits.tmpl
··· 71 71 {{$userName}} 72 72 {{end}} 73 73 </span> 74 - <span class="time tw-flex tw-items-center">{{DateTime "full" $commit.Date}}</span> 74 + <span class="time tw-flex tw-items-center">{{ctx.DateUtils.FullTime $commit.Date}}</span> 75 75 {{end}} 76 76 </li> 77 77 {{end}}
+1 -1
templates/repo/home.tmpl
··· 53 53 {{if .Repository.ArchivedUnix.IsZero}} 54 54 {{ctx.Locale.Tr "repo.archive.title"}} 55 55 {{else}} 56 - {{ctx.Locale.Tr "repo.archive.title_date" (DateTime "long" .Repository.ArchivedUnix)}} 56 + {{ctx.Locale.Tr "repo.archive.title_date" (ctx.DateUtils.AbsoluteLong .Repository.ArchivedUnix)}} 57 57 {{end}} 58 58 </div> 59 59 {{end}}
+1 -1
templates/repo/issue/milestone_issues.tmpl
··· 38 38 {{if .Milestone.DeadlineString}} 39 39 <span{{if .IsOverdue}} class="text red"{{end}}> 40 40 {{svg "octicon-calendar"}} 41 - {{DateTime "short" .Milestone.DeadlineString}} 41 + {{ctx.DateUtils.AbsoluteShort (.Milestone.DeadlineString|ctx.DateUtils.ParseLegacy)}} 42 42 </span> 43 43 {{else}} 44 44 {{svg "octicon-calendar"}}
+1 -1
templates/repo/issue/milestones.tmpl
··· 61 61 {{if .DeadlineString}} 62 62 <span class="flex-text-inline {{if .IsOverdue}}text red{{end}}"> 63 63 {{svg "octicon-calendar" 14}} 64 - {{DateTime "short" .DeadlineString}} 64 + {{ctx.DateUtils.AbsoluteShort (.DeadlineString|ctx.DateUtils.ParseLegacy)}} 65 65 </span> 66 66 {{else}} 67 67 {{svg "octicon-calendar" 14}}
+6 -4
templates/repo/issue/view_content/comments.tmpl
··· 300 300 {{template "shared/user/avatarlink" dict "user" .Poster}} 301 301 <span class="text grey muted-links"> 302 302 {{template "shared/user/authorlink" .Poster}} 303 - {{ctx.Locale.Tr "repo.issues.due_date_added" (DateTime "long" .Content) $createdStr}} 303 + {{$dueDate := ctx.DateUtils.AbsoluteLong (.Content|ctx.DateUtils.ParseLegacy)}} 304 + {{ctx.Locale.Tr "repo.issues.due_date_added" $dueDate $createdStr}} 304 305 </span> 305 306 </div> 306 307 {{else if eq .Type 17}} ··· 311 312 {{template "shared/user/authorlink" .Poster}} 312 313 {{$parsedDeadline := StringUtils.Split .Content "|"}} 313 314 {{if eq (len $parsedDeadline) 2}} 314 - {{$from := DateTime "long" (index $parsedDeadline 1)}} 315 - {{$to := DateTime "long" (index $parsedDeadline 0)}} 315 + {{$to := ctx.DateUtils.AbsoluteLong ((index $parsedDeadline 0)|ctx.DateUtils.ParseLegacy)}} 316 + {{$from := ctx.DateUtils.AbsoluteLong ((index $parsedDeadline 1)|ctx.DateUtils.ParseLegacy)}} 316 317 {{ctx.Locale.Tr "repo.issues.due_date_modified" $to $from $createdStr}} 317 318 {{end}} 318 319 </span> ··· 323 324 {{template "shared/user/avatarlink" dict "user" .Poster}} 324 325 <span class="text grey muted-links"> 325 326 {{template "shared/user/authorlink" .Poster}} 326 - {{ctx.Locale.Tr "repo.issues.due_date_remove" (DateTime "long" .Content) $createdStr}} 327 + {{$dueDate := ctx.DateUtils.AbsoluteLong (.Content|ctx.DateUtils.ParseLegacy)}} 328 + {{ctx.Locale.Tr "repo.issues.due_date_remove" $dueDate $createdStr}} 327 329 </span> 328 330 </div> 329 331 {{else if eq .Type 19}}
+1 -1
templates/repo/issue/view_content/sidebar/due_deadline.tmpl
··· 9 9 <div class="tw-flex tw-justify-between tw-items-center"> 10 10 <div class="due-date {{if .Issue.IsOverdue}}text red{{end}}" {{if .Issue.IsOverdue}}data-tooltip-content="{{ctx.Locale.Tr "repo.issues.due_date_overdue"}}"{{end}}> 11 11 {{svg "octicon-calendar" 16 "tw-mr-2"}} 12 - {{DateTime "long" .Issue.DeadlineUnix.FormatDate}} 12 + {{ctx.DateUtils.AbsoluteLong .Issue.DeadlineUnix}} 13 13 </div> 14 14 <div> 15 15 {{if and .HasIssuesOrPullsWritePermission (not .Repository.IsArchived)}}
+1 -1
templates/repo/pulse.tmpl
··· 1 1 <h2 class="ui header activity-header"> 2 - <span>{{DateTime "long" .DateFrom}} - {{DateTime "long" .DateUntil}}</span> 2 + <span>{{ctx.DateUtils.AbsoluteLong .DateFrom}} - {{ctx.DateUtils.AbsoluteLong .DateUntil}}</span> 3 3 <!-- Period --> 4 4 <div class="ui floating dropdown jump filter"> 5 5 <div class="ui basic compact button">
+1 -1
templates/repo/settings/deploy_keys.tmpl
··· 55 55 {{.Fingerprint}} 56 56 </div> 57 57 <div class="flex-item-body"> 58 - <p>{{ctx.Locale.Tr "settings.added_on" (DateTime "short" .CreatedUnix)}} — {{svg "octicon-info"}} {{if .HasUsed}}{{ctx.Locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="text green"{{end}}>{{DateTime "short" .UpdatedUnix}}</span>{{else}}{{ctx.Locale.Tr "settings.no_activity"}}{{end}} - <span>{{ctx.Locale.Tr "settings.can_read_info"}}{{if not .IsReadOnly}} / {{ctx.Locale.Tr "settings.can_write_info"}} {{end}}</span></p> 58 + <p>{{ctx.Locale.Tr "settings.added_on" (ctx.DateUtils.AbsoluteShort .CreatedUnix)}} — {{svg "octicon-info"}} {{if .HasUsed}}{{ctx.Locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="text green"{{end}}>{{ctx.DateUtils.AbsoluteShort .UpdatedUnix}}</span>{{else}}{{ctx.Locale.Tr "settings.no_activity"}}{{end}} - <span>{{ctx.Locale.Tr "settings.can_read_info"}}{{if not .IsReadOnly}} / {{ctx.Locale.Tr "settings.can_write_info"}} {{end}}</span></p> 59 59 </div> 60 60 </div> 61 61 <div class="flex-item-trailing">
+3 -3
templates/repo/settings/options.tmpl
··· 154 154 <tr> 155 155 <td>{{.PullMirror.RemoteAddress}}</td> 156 156 <td>{{ctx.Locale.Tr "repo.settings.mirror_settings.direction.pull"}}</td> 157 - <td>{{DateTime "full" .PullMirror.UpdatedUnix}}</td> 157 + <td>{{ctx.DateUtils.FullTime .PullMirror.UpdatedUnix}}</td> 158 158 <td class="right aligned"> 159 159 <form method="post" class="tw-inline-block"> 160 160 {{.CsrfTokenHtml}} ··· 243 243 <tr> 244 244 <td class="tw-break-anywhere">{{.RemoteAddress}}</td> 245 245 <td>{{ctx.Locale.Tr "repo.settings.mirror_settings.direction.push"}}</td> 246 - <td>{{if .LastUpdateUnix}}{{DateTime "full" .LastUpdateUnix}}{{else}}{{ctx.Locale.Tr "never"}}{{end}} {{if .LastError}}<div class="ui red label" data-tooltip-content="{{.LastError}}">{{ctx.Locale.Tr "error"}}</div>{{end}}</td> 246 + <td>{{if .LastUpdateUnix}}{{ctx.DateUtils.FullTime .LastUpdateUnix}}{{else}}{{ctx.Locale.Tr "never"}}{{end}} {{if .LastError}}<div class="ui red label" data-tooltip-content="{{.LastError}}">{{ctx.Locale.Tr "error"}}</div>{{end}}</td> 247 247 <td>{{if not (eq (len .GetPublicKey) 0)}}<a data-clipboard-text="{{.GetPublicKey}}">{{ctx.Locale.Tr "repo.settings.mirror_settings.push_mirror.copy_public_key"}}</a>{{else}}{{ctx.Locale.Tr "repo.settings.mirror_settings.push_mirror.none_ssh"}}{{end}}</td> 248 - <td class="right aligned df"> 248 + <td class="right aligned"> 249 249 <button 250 250 class="ui tiny button show-modal" 251 251 data-modal="#push-mirror-edit-modal"
+1 -1
templates/repo/user_cards.tmpl
··· 20 20 {{else if .Location}} 21 21 {{svg "octicon-location"}} {{.Location}} 22 22 {{else}} 23 - {{svg "octicon-calendar"}} {{ctx.Locale.Tr "user.joined_on" (DateTime "short" .CreatedUnix)}} 23 + {{svg "octicon-calendar"}} {{ctx.Locale.Tr "user.joined_on" (ctx.DateUtils.AbsoluteShort .CreatedUnix)}} 24 24 {{end}} 25 25 </div> 26 26 </div>
+1 -1
templates/shared/issuelist.tmpl
··· 117 117 <span class="due-date flex-text-inline" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.due_date"}}"> 118 118 <span{{if .IsOverdue}} class="text red"{{end}}> 119 119 {{svg "octicon-calendar" 14}} 120 - {{DateTime "short" (.DeadlineUnix.FormatDate)}} 120 + {{ctx.DateUtils.AbsoluteShort .DeadlineUnix}} 121 121 </span> 122 122 </span> 123 123 {{end}}
+1 -1
templates/shared/secrets/add_list.tmpl
··· 28 28 </div> 29 29 <div class="flex-item-trailing"> 30 30 <span class="color-text-light-2"> 31 - {{ctx.Locale.Tr "settings.added_on" (DateTime "short" .CreatedUnix)}} 31 + {{ctx.Locale.Tr "settings.added_on" (ctx.DateUtils.AbsoluteShort .CreatedUnix)}} 32 32 </span> 33 33 <button class="ui btn interact-bg link-action tw-p-2" 34 34 data-url="{{$.Link}}/delete?id={{.ID}}"
+1 -1
templates/shared/user/profile_big_avatar.tmpl
··· 73 73 </li> 74 74 {{end}} 75 75 {{end}} 76 - <li>{{svg "octicon-calendar"}} <span>{{ctx.Locale.Tr "user.joined_on" (DateTime "short" .ContextUser.CreatedUnix)}}</span></li> 76 + <li>{{svg "octicon-calendar"}} <span>{{ctx.Locale.Tr "user.joined_on" (ctx.DateUtils.AbsoluteShort .ContextUser.CreatedUnix)}}</span></li> 77 77 {{if and .Orgs .HasOrgsVisible}} 78 78 <li> 79 79 <ul class="user-orgs">
+1 -1
templates/shared/variables/variable_list.tmpl
··· 30 30 </div> 31 31 <div class="flex-item-trailing"> 32 32 <span class="color-text-light-2"> 33 - {{ctx.Locale.Tr "settings.added_on" (DateTime "short" .CreatedUnix)}} 33 + {{ctx.Locale.Tr "settings.added_on" (ctx.DateUtils.AbsoluteShort .CreatedUnix)}} 34 34 </span> 35 35 <button class="btn interact-bg tw-p-2 show-modal" 36 36 data-tooltip-content="{{ctx.Locale.Tr "actions.variables.edit"}}"
+1 -1
templates/user/dashboard/milestones.tmpl
··· 116 116 {{if .DeadlineString}} 117 117 <span{{if .IsOverdue}} class="text red"{{end}}> 118 118 {{svg "octicon-calendar" 14}} 119 - {{DateTime "short" .DeadlineString}} 119 + {{ctx.DateUtils.AbsoluteShort (.DeadlineString|ctx.DateUtils.ParseLegacy)}} 120 120 </span> 121 121 {{else}} 122 122 {{svg "octicon-calendar" 14}}
+1 -1
templates/user/settings/applications.tmpl
··· 36 36 </ul> 37 37 </details> 38 38 <div class="flex-item-body"> 39 - <p>{{ctx.Locale.Tr "settings.added_on" (DateTime "short" .CreatedUnix)}} — {{svg "octicon-info"}} {{if .HasUsed}}{{ctx.Locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="text green"{{end}}>{{DateTime "short" .UpdatedUnix}}</span>{{else}}{{ctx.Locale.Tr "settings.no_activity"}}{{end}}</p> 39 + <p>{{ctx.Locale.Tr "settings.added_on" (ctx.DateUtils.AbsoluteShort .CreatedUnix)}} — {{svg "octicon-info"}} {{if .HasUsed}}{{ctx.Locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="text green"{{end}}>{{ctx.DateUtils.AbsoluteShort .UpdatedUnix}}</span>{{else}}{{ctx.Locale.Tr "settings.no_activity"}}{{end}}</p> 40 40 </div> 41 41 </div> 42 42 <div class="flex-item-trailing">
+1 -1
templates/user/settings/grants_oauth2.tmpl
··· 14 14 <div class="flex-item-main"> 15 15 <div class="flex-item-title">{{.Application.Name}}</div> 16 16 <div class="flex-item-body"> 17 - <p>{{ctx.Locale.Tr "settings.added_on" (DateTime "short" .CreatedUnix)}}</p> 17 + <p>{{ctx.Locale.Tr "settings.added_on" (ctx.DateUtils.AbsoluteShort .CreatedUnix)}}</p> 18 18 </div> 19 19 </div> 20 20 <div class="flex-item-trailing">
+3 -9
templates/user/settings/keys_gpg.tmpl
··· 63 63 <b>{{ctx.Locale.Tr "settings.subkeys"}}:</b> {{range .SubsKey}} {{.PaddedKeyID}} {{end}} 64 64 </div> 65 65 <div class="flex-item-body"> 66 - <p> 67 - {{ctx.Locale.Tr "settings.added_on" (DateTime "short" .AddedUnix)}} 68 - - 69 - {{if not .ExpiredUnix.IsZero}} 70 - {{ctx.Locale.Tr "settings.valid_until_date" (DateTime "short" .ExpiredUnix)}} 71 - {{else}} 72 - {{ctx.Locale.Tr "settings.valid_forever"}} 73 - {{end}} 74 - </p> 66 + <p>{{ctx.Locale.Tr "settings.added_on" (ctx.DateUtils.AbsoluteShort .AddedUnix)}}</p> 67 + - 68 + <p>{{if not .ExpiredUnix.IsZero}}{{ctx.Locale.Tr "settings.valid_until_date" (ctx.DateUtils.AbsoluteShort .ExpiredUnix)}}{{else}}{{ctx.Locale.Tr "settings.valid_forever"}}{{end}}</p> 75 69 </div> 76 70 </div> 77 71 <div class="flex-item-trailing">
+1 -1
templates/user/settings/keys_principal.tmpl
··· 22 22 <div class="flex-item-main"> 23 23 <div class="flex-item-title">{{.Name}}</div> 24 24 <div class="flex-item-body"> 25 - <p>{{ctx.Locale.Tr "settings.added_on" (DateTime "short" .CreatedUnix)}} — {{svg "octicon-info" 16}} {{if .HasUsed}}{{ctx.Locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="green"{{end}}>{{DateTime "short" .UpdatedUnix}}</span>{{else}}{{ctx.Locale.Tr "settings.no_activity"}}{{end}}</p> 25 + <p>{{ctx.Locale.Tr "settings.added_on" (ctx.DateUtils.AbsoluteShort .CreatedUnix)}} — {{svg "octicon-info" 16}} {{if .HasUsed}}{{ctx.Locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="green"{{end}}>{{ctx.DateUtils.AbsoluteShort .UpdatedUnix}}</span>{{else}}{{ctx.Locale.Tr "settings.no_activity"}}{{end}}</p> 26 26 </div> 27 27 </div> 28 28 <div class="flex-item-trailing">
+1 -1
templates/user/settings/keys_ssh.tmpl
··· 53 53 {{.Fingerprint}} 54 54 </div> 55 55 <div class="flex-item-body"> 56 - <p>{{ctx.Locale.Tr "settings.added_on" (DateTime "short" .CreatedUnix)}} — {{svg "octicon-info"}} {{if .HasUsed}}{{ctx.Locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="text green"{{end}}>{{DateTime "short" .UpdatedUnix}}</span>{{else}}{{ctx.Locale.Tr "settings.no_activity"}}{{end}}</p> 56 + <p>{{ctx.Locale.Tr "settings.added_on" (ctx.DateUtils.AbsoluteShort .CreatedUnix)}} — {{svg "octicon-info"}} {{if .HasUsed}}{{ctx.Locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="text green"{{end}}>{{ctx.DateUtils.AbsoluteShort .UpdatedUnix}}</span>{{else}}{{ctx.Locale.Tr "settings.no_activity"}}{{end}}</p> 57 57 </div> 58 58 </div> 59 59 <div class="flex-item-trailing">
+1 -1
templates/user/settings/security/webauthn.tmpl
··· 12 12 <div class="flex-item-main"> 13 13 <div class="flex-item-title">{{.Name}}</div> 14 14 <div class="flex-item-body"> 15 - <p>{{ctx.Locale.Tr "settings.added_on" (DateTime "short" .CreatedUnix)}}</p> 15 + <p>{{ctx.Locale.Tr "settings.added_on" (ctx.DateUtils.AbsoluteShort .CreatedUnix)}}</p> 16 16 </div> 17 17 </div> 18 18 <div class="flex-item-trailing">