From acdb92ad425b1f7035b677f430516ab4a9f645c2 Mon Sep 17 00:00:00 2001
From: Yarden Shoham <hrsi88@gmail.com>
Date: Mon, 17 Oct 2022 07:08:21 +0300
Subject: [PATCH] Localize all timestamps (#21440)

Following
* #21410

We are now able to localize all timestamps. Some examples:

`short-date` format, French, user profile page:

![image](https://user-images.githubusercontent.com/20454870/195622461-aa0d5b93-f8df-42ad-881c-9c16606bf387.png)

`date-time` format, Portuguese, mirror repository settings page:

![image](https://user-images.githubusercontent.com/20454870/195623191-7a37d77c-4a02-4140-846d-f290a65ea21d.png)

Signed-off-by: Yarden Shoham <hrsi88@gmail.com>

Signed-off-by: Yarden Shoham <hrsi88@gmail.com>
Co-authored-by: Gusted <williamzijl7@hotmail.com>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
---
 templates/admin/auth/list.tmpl                |  4 +--
 templates/admin/notice.tmpl                   |  2 +-
 templates/admin/org/list.tmpl                 |  2 +-
 templates/admin/packages/list.tmpl            |  2 +-
 templates/admin/repo/list.tmpl                |  2 +-
 templates/admin/user/list.tmpl                |  4 +--
 templates/explore/organizations.tmpl          |  2 +-
 templates/explore/users.tmpl                  |  2 +-
 .../repo/issue/view_content/sidebar.tmpl      |  2 +-
 templates/repo/settings/deploy_keys.tmpl      |  2 +-
 templates/repo/settings/options.tmpl          |  4 +--
 templates/repo/user_cards.tmpl                |  2 +-
 templates/shared/issuelist.tmpl               |  2 +-
 templates/user/profile.tmpl                   |  2 +-
 templates/user/settings/applications.tmpl     |  2 +-
 templates/user/settings/grants_oauth2.tmpl    |  2 +-
 templates/user/settings/keys_gpg.tmpl         |  4 +--
 templates/user/settings/keys_principal.tmpl   |  2 +-
 templates/user/settings/keys_ssh.tmpl         |  2 +-
 web_src/js/features/formatting.js             | 30 ++++++++++++++++---
 20 files changed, 49 insertions(+), 27 deletions(-)

diff --git a/templates/admin/auth/list.tmpl b/templates/admin/auth/list.tmpl
index 3ce138449d..c43287ee1a 100644
--- a/templates/admin/auth/list.tmpl
+++ b/templates/admin/auth/list.tmpl
@@ -29,8 +29,8 @@
 							<td><a href="{{AppSubUrl}}/admin/auths/{{.ID}}">{{.Name}}</a></td>
 							<td>{{.TypeName}}</td>
 							<td>{{if .IsActive}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
-							<td><span class="tooltip" data-content="{{.UpdatedUnix.FormatShort}}">{{.UpdatedUnix.FormatShort}}</span></td>
-							<td><span class="tooltip" data-content="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</span></td>
+							<td><span class="tooltip" data-content="{{.UpdatedUnix.FormatShort}}"><time data-format="short-date" datetime="{{.UpdatedUnix.FormatLong}}">{{.UpdatedUnix.FormatShort}}</time></span></td>
+							<td><span class="tooltip" data-content="{{.CreatedUnix.FormatLong}}"><time data-format="short-date" datetime="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</time></span></td>
 							<td><a href="{{AppSubUrl}}/admin/auths/{{.ID}}">{{svg "octicon-pencil"}}</a></td>
 						</tr>
 					{{end}}
diff --git a/templates/admin/notice.tmpl b/templates/admin/notice.tmpl
index b831f50c85..2777741efb 100644
--- a/templates/admin/notice.tmpl
+++ b/templates/admin/notice.tmpl
@@ -29,7 +29,7 @@
 							<td>{{.ID}}</td>
 							<td>{{$.locale.Tr .TrStr}}</td>
 							<td class="view-detail"><span class="notice-description text truncate">{{.Description}}</span></td>
-							<td><span class="notice-created-time tooltip" data-content="{{.CreatedUnix.AsTime}}">{{.CreatedUnix.FormatShort}}</span></td>
+							<td><span class="notice-created-time tooltip" data-content="{{.CreatedUnix.AsTime}}"><time data-format="short-date" datetime="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</time></span></td>
 							<td><a href="#">{{svg "octicon-note" 16 "view-detail"}}</a></td>
 						</tr>
 					{{end}}
diff --git a/templates/admin/org/list.tmpl b/templates/admin/org/list.tmpl
index aec3f2c841..11dc23c60e 100644
--- a/templates/admin/org/list.tmpl
+++ b/templates/admin/org/list.tmpl
@@ -44,7 +44,7 @@
 							<td>{{.NumTeams}}</td>
 							<td>{{.NumMembers}}</td>
 							<td>{{.NumRepos}}</td>
-							<td><span title="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</span></td>
+							<td><span title="{{.CreatedUnix.FormatLong}}"><time data-format="short-date" datetime="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</time></span></td>
 							<td><a href="{{.OrganisationLink}}/settings">{{svg "octicon-pencil"}}</a></td>
 						</tr>
 					{{end}}
diff --git a/templates/admin/packages/list.tmpl b/templates/admin/packages/list.tmpl
index 06d6163476..b62e788799 100644
--- a/templates/admin/packages/list.tmpl
+++ b/templates/admin/packages/list.tmpl
@@ -75,7 +75,7 @@
 							{{end}}
 							</td>
 							<td>{{FileSize .CalculateBlobSize}}</td>
-							<td><span title="{{.Version.CreatedUnix.FormatLong}}">{{.Version.CreatedUnix.FormatShort}}</span></td>
+							<td><span title="{{.Version.CreatedUnix.FormatLong}}"><time data-format="short-date" datetime="{{.Version.CreatedUnix.FormatLong}}">{{.Version.CreatedUnix.FormatShort}}</time></span></td>
 							<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>
 						</tr>
 					{{end}}
diff --git a/templates/admin/repo/list.tmpl b/templates/admin/repo/list.tmpl
index b26ec2eb78..837802f0d0 100644
--- a/templates/admin/repo/list.tmpl
+++ b/templates/admin/repo/list.tmpl
@@ -83,7 +83,7 @@
 							<td>{{.NumForks}}</td>
 							<td>{{.NumIssues}}</td>
 							<td>{{FileSize .Size}}</td>
-							<td><span title="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</span></td>
+							<td><span title="{{.CreatedUnix.FormatLong}}"><time data-format="short-date" datetime="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</time></span></td>
 							<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>
 						</tr>
 					{{end}}
diff --git a/templates/admin/user/list.tmpl b/templates/admin/user/list.tmpl
index 061e663850..56f6eaa3ad 100644
--- a/templates/admin/user/list.tmpl
+++ b/templates/admin/user/list.tmpl
@@ -94,9 +94,9 @@
 							<td>{{if .IsRestricted}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
 							<td>{{if index $.UsersTwoFaStatus .ID}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td>
 							<td>{{.NumRepos}}</td>
-							<td><span title="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</span></td>
+							<td><span title="{{.CreatedUnix.FormatLong}}"><time data-format="short-date" datetime="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</time></span></td>
 							{{if .LastLoginUnix}}
-								<td><span title="{{.LastLoginUnix.FormatLong}}">{{.LastLoginUnix.FormatShort}}</span></td>
+								<td><span title="{{.LastLoginUnix.FormatLong}}"><time data-format="short-date" datetime="{{.LastLoginUnix.FormatLong}}">{{.LastLoginUnix.FormatShort}}</time></span></td>
 							{{else}}
 								<td><span>{{$.locale.Tr "admin.users.never_login"}}</span></td>
 							{{end}}
diff --git a/templates/explore/organizations.tmpl b/templates/explore/organizations.tmpl
index 2073b8c69c..36267baf33 100644
--- a/templates/explore/organizations.tmpl
+++ b/templates/explore/organizations.tmpl
@@ -23,7 +23,7 @@
 								{{svg "octicon-link"}}
 								<a href="{{.Website}}" rel="nofollow">{{.Website}}</a>
 							{{end}}
-							{{svg "octicon-clock"}} {{$.locale.Tr "user.join_on"}} {{.CreatedUnix.FormatShort}}
+							{{svg "octicon-clock"}} {{$.locale.Tr "user.join_on"}} <time data-format="short-date" datetime="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</time>
 						</div>
 					</div>
 				</div>
diff --git a/templates/explore/users.tmpl b/templates/explore/users.tmpl
index 94a21d9959..5fb79c0dd0 100644
--- a/templates/explore/users.tmpl
+++ b/templates/explore/users.tmpl
@@ -18,7 +18,7 @@
 								{{svg "octicon-mail"}}
 								<a href="mailto:{{.Email}}" rel="nofollow">{{.Email}}</a>
 							{{end}}
-							{{svg "octicon-clock"}} {{$.locale.Tr "user.join_on"}} {{.CreatedUnix.FormatShort}}
+							{{svg "octicon-clock"}} {{$.locale.Tr "user.join_on"}} <time data-format="short-date" datetime="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</time>
 						</div>
 					</div>
 				</div>
diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl
index 5b95d3d8e5..eb95674b13 100644
--- a/templates/repo/issue/view_content/sidebar.tmpl
+++ b/templates/repo/issue/view_content/sidebar.tmpl
@@ -413,7 +413,7 @@
 					<div class="df sb ac">
 						<div class="due-date tooltip {{if .Issue.IsOverdue}}text red{{end}}" {{if .Issue.IsOverdue}}data-content="{{.locale.Tr "repo.issues.due_date_overdue"}}"{{end}}>
 							{{svg "octicon-calendar" 16 "mr-3"}}
-							{{.Issue.DeadlineUnix.FormatDate}}
+							<time data-format="date" datetime="{{.Issue.DeadlineUnix.FormatLong}}">{{.Issue.DeadlineUnix.FormatDate}}</time>
 						</div>
 						<div>
 							{{if and .HasIssuesOrPullsWritePermission (not .Repository.IsArchived)}}
diff --git a/templates/repo/settings/deploy_keys.tmpl b/templates/repo/settings/deploy_keys.tmpl
index 2f8a4c6c1e..44c916eefb 100644
--- a/templates/repo/settings/deploy_keys.tmpl
+++ b/templates/repo/settings/deploy_keys.tmpl
@@ -64,7 +64,7 @@
 									{{.Fingerprint}}
 								</div>
 								<div class="activity meta">
-									<i>{{$.locale.Tr "settings.add_on"}} <span>{{.CreatedUnix.FormatShort}}</span> —  {{svg "octicon-info"}} {{if .HasUsed}}{{$.locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="green"{{end}}>{{.UpdatedUnix.FormatShort}}</span>{{else}}{{$.locale.Tr "settings.no_activity"}}{{end}} - <span>{{$.locale.Tr "settings.can_read_info"}}{{if not .IsReadOnly}} / {{$.locale.Tr "settings.can_write_info"}} {{end}}</span></i>
+									<i>{{$.locale.Tr "settings.add_on"}} <span><time data-format="short-date" datetime="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</time></span> —  {{svg "octicon-info"}} {{if .HasUsed}}{{$.locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="green"{{end}}><time data-format="short-date" datetime="{{.UpdatedUnix.FormatLong}}">{{.UpdatedUnix.FormatShort}}</time></span>{{else}}{{$.locale.Tr "settings.no_activity"}}{{end}} - <span>{{$.locale.Tr "settings.can_read_info"}}{{if not .IsReadOnly}} / {{$.locale.Tr "settings.can_write_info"}} {{end}}</span></i>
 								</div>
 							</div>
 						</div>
diff --git a/templates/repo/settings/options.tmpl b/templates/repo/settings/options.tmpl
index 9030235e7c..3c5996e903 100644
--- a/templates/repo/settings/options.tmpl
+++ b/templates/repo/settings/options.tmpl
@@ -93,7 +93,7 @@
 						<tr>
 							<td>{{(MirrorRemoteAddress $.Context .Repository .Mirror.GetRemoteName false).Address}}</td>
 							<td>{{$.locale.Tr "repo.settings.mirror_settings.direction.pull"}}</td>
-							<td>{{.Mirror.UpdatedUnix.AsTime}}</td>
+							<td><time data-format="date-time" datetime="{{.Mirror.UpdatedUnix.FormatLong}}">{{.Mirror.UpdatedUnix.AsTime}}</time></td>
 							<td class="right aligned">
 								<form method="post" style="display: inline-block">
 									{{.CsrfTokenHtml}}
@@ -171,7 +171,7 @@
 							{{$address := MirrorRemoteAddress $.Context $.Repository .GetRemoteName true}}
 							<td>{{$address.Address}}</td>
 							<td>{{$.locale.Tr "repo.settings.mirror_settings.direction.push"}}</td>
-							<td>{{if .LastUpdateUnix}}{{.LastUpdateUnix.AsTime}}{{else}}{{$.locale.Tr "never"}}{{end}} {{if .LastError}}<div class="ui red label tooltip" data-content="{{.LastError}}">{{$.locale.Tr "error"}}</div>{{end}}</td>
+							<td>{{if .LastUpdateUnix}}<time data-format="date-time" datetime="{{.LastUpdateUnix.FormatLong}}">{{.LastUpdateUnix.AsTime}}</time>{{else}}{{$.locale.Tr "never"}}{{end}} {{if .LastError}}<div class="ui red label tooltip" data-content="{{.LastError}}">{{$.locale.Tr "error"}}</div>{{end}}</td>
 							<td class="right aligned">
 								<form method="post" style="display: inline-block">
 									{{$.CsrfTokenHtml}}
diff --git a/templates/repo/user_cards.tmpl b/templates/repo/user_cards.tmpl
index eec31d8b50..efc8530820 100644
--- a/templates/repo/user_cards.tmpl
+++ b/templates/repo/user_cards.tmpl
@@ -18,7 +18,7 @@
 					{{else if .Location}}
 						{{svg "octicon-location"}} {{.Location}}
 					{{else}}
-						{{svg "octicon-clock"}} {{$.locale.Tr "user.join_on"}} {{.CreatedUnix.FormatShort}}
+						{{svg "octicon-clock"}} {{$.locale.Tr "user.join_on"}} <time data-format="short-date" datetime="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</time>
 					{{end}}
 				</div>
 			</li>
diff --git a/templates/shared/issuelist.tmpl b/templates/shared/issuelist.tmpl
index 066d34fe33..6fce412ffa 100644
--- a/templates/shared/issuelist.tmpl
+++ b/templates/shared/issuelist.tmpl
@@ -109,7 +109,7 @@
 						<span class="due-date tooltip" data-content="{{$.locale.Tr "repo.issues.due_date"}}" data-position="right center">
 							<span{{if .IsOverdue}} class="overdue"{{end}}>
 								{{svg "octicon-calendar" 14 "mr-2"}}
-								{{.DeadlineUnix.FormatShort}}
+								<time data-format="short-date" datetime="{{.DeadlineUnix.FormatLong}}">{{.DeadlineUnix.FormatShort}}</time>
 							</span>
 						</span>
 					{{end}}
diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl
index a4ac65db6a..3b776bc16d 100644
--- a/templates/user/profile.tmpl
+++ b/templates/user/profile.tmpl
@@ -53,7 +53,7 @@
 									</li>
 								{{end}}
 							{{end}}
-							<li>{{svg "octicon-clock"}} {{.locale.Tr "user.join_on"}} {{.Owner.CreatedUnix.FormatShort}}</li>
+							<li>{{svg "octicon-clock"}} {{.locale.Tr "user.join_on"}} <time data-format="short-date" datetime="{{.Owner.CreatedUnix.FormatLong}}">{{.Owner.CreatedUnix.FormatShort}}</time></li>
 							{{if and .Orgs .HasOrgsVisible}}
 							<li>
 								<ul class="user-orgs">
diff --git a/templates/user/settings/applications.tmpl b/templates/user/settings/applications.tmpl
index 9125f4bd00..e05cebb0e4 100644
--- a/templates/user/settings/applications.tmpl
+++ b/templates/user/settings/applications.tmpl
@@ -23,7 +23,7 @@
 						<div class="content">
 							<strong>{{.Name}}</strong>
 							<div class="activity meta">
-								<i>{{$.locale.Tr "settings.add_on"}} <span>{{.CreatedUnix.FormatShort}}</span> — {{svg "octicon-info"}} {{if .HasUsed}}{{$.locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="green"{{end}}>{{.UpdatedUnix.FormatShort}}</span>{{else}}{{$.locale.Tr "settings.no_activity"}}{{end}}</i>
+								<i>{{$.locale.Tr "settings.add_on"}} <span><time data-format="short-date" datetime="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</time></span> — {{svg "octicon-info"}} {{if .HasUsed}}{{$.locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="green"{{end}}><time data-format="short-date" datetime="{{.UpdatedUnix.FormatLong}}">{{.UpdatedUnix.FormatShort}}</time></span>{{else}}{{$.locale.Tr "settings.no_activity"}}{{end}}</i>
 							</div>
 						</div>
 					</div>
diff --git a/templates/user/settings/grants_oauth2.tmpl b/templates/user/settings/grants_oauth2.tmpl
index e67fd2d222..878c258dd3 100644
--- a/templates/user/settings/grants_oauth2.tmpl
+++ b/templates/user/settings/grants_oauth2.tmpl
@@ -20,7 +20,7 @@
 				<div class="content">
 					<strong>{{$grant.Application.Name}}</strong>
 					<div class="activity meta">
-						<i>{{$.locale.Tr "settings.add_on"}} <span>{{$grant.CreatedUnix.FormatShort}}</span></i>
+						<i>{{$.locale.Tr "settings.add_on"}} <span><time data-format="short-date" datetime="{{$grant.CreatedUnix.FormatLong}}">{{$grant.CreatedUnix.FormatShort}}</time></span></i>
 					</div>
 				</div>
 			</div>
diff --git a/templates/user/settings/keys_gpg.tmpl b/templates/user/settings/keys_gpg.tmpl
index 5883508179..fe6c0bbeb1 100644
--- a/templates/user/settings/keys_gpg.tmpl
+++ b/templates/user/settings/keys_gpg.tmpl
@@ -68,9 +68,9 @@
 						<b>{{$.locale.Tr "settings.subkeys"}}:</b> {{range .SubsKey}} {{.PaddedKeyID}} {{end}}
 					</div>
 					<div class="activity meta">
-						<i>{{$.locale.Tr "settings.add_on"}} <span>{{.AddedUnix.FormatShort}}</span></i>
+						<i>{{$.locale.Tr "settings.add_on"}} <span><time data-format="short-date" datetime="{{.AddedUnix.FormatLong}}">{{.AddedUnix.FormatShort}}</time></span></i>
 						-
-						<i>{{if not .ExpiredUnix.IsZero}}{{$.locale.Tr "settings.valid_until"}} <span>{{.ExpiredUnix.FormatShort}}</span>{{else}}{{$.locale.Tr "settings.valid_forever"}}{{end}}</i>
+						<i>{{if not .ExpiredUnix.IsZero}}{{$.locale.Tr "settings.valid_until"}} <span><time data-format="short-date" datetime="{{.ExpiredUnix.FormatLong}}">{{.ExpiredUnix.FormatShort}}</time></span>{{else}}{{$.locale.Tr "settings.valid_forever"}}{{end}}</i>
 					</div>
 				</div>
 			</div>
diff --git a/templates/user/settings/keys_principal.tmpl b/templates/user/settings/keys_principal.tmpl
index 5699214468..b0cacbe54c 100644
--- a/templates/user/settings/keys_principal.tmpl
+++ b/templates/user/settings/keys_principal.tmpl
@@ -25,7 +25,7 @@
 					<div class="content">
 						<strong>{{.Name}}</strong>
 						<div class="activity meta">
-							<i>{{$.locale.Tr "settings.add_on"}} <span>{{.CreatedUnix.FormatShort}}</span> —  {{svg "octicon-info" 16}} {{if .HasUsed}}{{$.locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="green"{{end}}>{{.UpdatedUnix.FormatShort}}</span>{{else}}{{$.locale.Tr "settings.no_activity"}}{{end}}</i>
+							<i>{{$.locale.Tr "settings.add_on"}} <span><time data-format="short-date" datetime="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</time></span> —  {{svg "octicon-info" 16}} {{if .HasUsed}}{{$.locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="green"{{end}}><time data-format="short-date" datetime="{{.UpdatedUnix.FormatLong}}">{{.UpdatedUnix.FormatShort}}</time></span>{{else}}{{$.locale.Tr "settings.no_activity"}}{{end}}</i>
 						</div>
 					</div>
 				</div>
diff --git a/templates/user/settings/keys_ssh.tmpl b/templates/user/settings/keys_ssh.tmpl
index bcab968d59..0933953909 100644
--- a/templates/user/settings/keys_ssh.tmpl
+++ b/templates/user/settings/keys_ssh.tmpl
@@ -58,7 +58,7 @@
 								{{.Fingerprint}}
 						</div>
 						<div class="activity meta">
-								<i>{{$.locale.Tr "settings.add_on"}} <span>{{.CreatedUnix.FormatShort}}</span> —	{{svg "octicon-info"}} {{if .HasUsed}}{{$.locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="green"{{end}}>{{.UpdatedUnix.FormatShort}}</span>{{else}}{{$.locale.Tr "settings.no_activity"}}{{end}}</i>
+								<i>{{$.locale.Tr "settings.add_on"}} <span><time data-format="short-date" datetime="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</time></span> —	{{svg "octicon-info"}} {{if .HasUsed}}{{$.locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="green"{{end}}><time data-format="short-date" datetime="{{.UpdatedUnix.FormatLong}}">{{.UpdatedUnix.FormatShort}}</time></span>{{else}}{{$.locale.Tr "settings.no_activity"}}{{end}}</i>
 						</div>
 				</div>
 			</div>
diff --git a/web_src/js/features/formatting.js b/web_src/js/features/formatting.js
index 5f4633bba2..c8f5db9e14 100644
--- a/web_src/js/features/formatting.js
+++ b/web_src/js/features/formatting.js
@@ -1,7 +1,10 @@
 import {prettyNumber} from '../utils.js';
 
 const {lang} = document.documentElement;
+
 const dateFormatter = new Intl.DateTimeFormat(lang, {year: 'numeric', month: 'long', day: 'numeric'});
+const shortDateFormatter = new Intl.DateTimeFormat(lang, {year: 'numeric', month: 'short', day: 'numeric'});
+const dateTimeFormatter = new Intl.DateTimeFormat(lang, {year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric'});
 
 export function initFormattingReplacements() {
   // replace english formatted numbers with locale-specific separators
@@ -13,9 +16,28 @@ export function initFormattingReplacements() {
     }
   }
 
-  // for each <time></time> tag, if it has the data-format="date" attribute, format
-  // the text according to the user's chosen locale
-  for (const timeElement of document.querySelectorAll('time[data-format="date"]')) {
-    timeElement.textContent = dateFormatter.format(new Date(timeElement.dateTime));
+  // for each <time></time> tag, if it has the data-format attribute, format
+  // the text according to the user's chosen locale and formatter.
+  formatAllTimeElements();
+}
+
+function formatAllTimeElements() {
+  const timeElements = document.querySelectorAll('time[data-format]');
+  for (const timeElement of timeElements) {
+    const formatter = getFormatter(timeElement.dataset.format);
+    timeElement.textContent = formatter.format(new Date(timeElement.dateTime));
+  }
+}
+
+function getFormatter(format) {
+  switch (format) {
+    case 'date':
+      return dateFormatter;
+    case 'short-date':
+      return shortDateFormatter;
+    case 'date-time':
+      return dateTimeFormatter;
+    default:
+      throw new Error('Unknown format');
   }
 }