]> source.dussan.org Git - gitea.git/commitdiff
Localize all timestamps (#21440)
authorYarden Shoham <hrsi88@gmail.com>
Mon, 17 Oct 2022 04:08:21 +0000 (07:08 +0300)
committerGitHub <noreply@github.com>
Mon, 17 Oct 2022 04:08:21 +0000 (12:08 +0800)
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>
20 files changed:
templates/admin/auth/list.tmpl
templates/admin/notice.tmpl
templates/admin/org/list.tmpl
templates/admin/packages/list.tmpl
templates/admin/repo/list.tmpl
templates/admin/user/list.tmpl
templates/explore/organizations.tmpl
templates/explore/users.tmpl
templates/repo/issue/view_content/sidebar.tmpl
templates/repo/settings/deploy_keys.tmpl
templates/repo/settings/options.tmpl
templates/repo/user_cards.tmpl
templates/shared/issuelist.tmpl
templates/user/profile.tmpl
templates/user/settings/applications.tmpl
templates/user/settings/grants_oauth2.tmpl
templates/user/settings/keys_gpg.tmpl
templates/user/settings/keys_principal.tmpl
templates/user/settings/keys_ssh.tmpl
web_src/js/features/formatting.js

index 3ce138449d3b4db61527d032827e29ac52e284d0..c43287ee1ae0dcfa752a92190df1d2fcb4b27933 100644 (file)
@@ -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}}
index b831f50c850d8e9850cdafdf30b16b5d469b958e..2777741efbe9dba204c3593e9fb5494e32263aa9 100644 (file)
@@ -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}}
index aec3f2c8419cbd9818dc42cef832d40b04e41624..11dc23c60eb90cad0bb08f0e69952fda97336e03 100644 (file)
@@ -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}}
index 06d6163476a9f284bf178ad5580db45774d15af1..b62e788799153509e11d25711c1ce1c7624077a6 100644 (file)
@@ -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}}
index b26ec2eb786582964363862ad6a7163a27c99c9f..837802f0d0ce73174c87dd500685a9e2406b11fd 100644 (file)
@@ -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}}
index 061e66385021dba8f64616fd9690e42f3488ae81..56f6eaa3ad7108316063092e17a456856ed85bea 100644 (file)
@@ -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}}
index 2073b8c69c6979dce362fcf4797209e03e550b60..36267baf33954f39440c42634ef7b004c4b29f0b 100644 (file)
@@ -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>
index 94a21d995958365bf69d2926962adec2acf90504..5fb79c0dd027ab65b1732bf0c5d211baf5d3ec9c 100644 (file)
@@ -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>
index 5b95d3d8e56e8a3e2b7706fa6a8121ae3109b54b..eb95674b13d2ed581a98d6088ec51a89bf7807b9 100644 (file)
                                        <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)}}
index 2f8a4c6c1e25b350d733cb5667fedd4eeefa626c..44c916eefbdb1872075507d7a5a9c8789a525370 100644 (file)
@@ -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>
index 9030235e7c120dd8c3e1c6350af74f32d80d9c2c..3c5996e903a732dcbf3d4d7136e5f46ca133eaf2 100644 (file)
@@ -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}}
                                                        {{$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}}
index eec31d8b5013dfaee8263739150c095020824e72..efc85308203bc3e57952a10f78a34507f9b39580 100644 (file)
@@ -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>
index 066d34fe3303e2446393ee87a9cd0e93ece684a4..6fce412ffa1404dfd1b088d6bceb98d99b40f0bf 100644 (file)
                                                <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}}
index a4ac65db6aed5d64e89e5c69fdcdde5b1e8e99c0..3b776bc16d5e4f4e05e0cadc3792ee804c02cd35 100644 (file)
@@ -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">
index 9125f4bd00f6a31901589d1fe202f08f93a353cf..e05cebb0e4e80001495439c654b9aa0dd4d616e6 100644 (file)
@@ -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>
index e67fd2d22257f2308448deb8a65635854776f406..878c258dd32a0c894cf045167ca96692f450df6f 100644 (file)
@@ -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>
index 58835081796f32f1d128bb7ee5c52e5894b94915..fe6c0bbeb1f7903dbe752dc5612eedcbfa7c223d 100644 (file)
@@ -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>
index 56992144686f13e6c428b07eaddb200187f4612e..b0cacbe54c519be6357ebf82133a5212299ef261 100644 (file)
@@ -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>
index bcab968d599fb4a9e69b9bee4c20d50cc1e2d44c..09339539096ef584cbf018f77b535bf332e02ba2 100644 (file)
@@ -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>
index 5f4633bba2120b1fe09d1542ff1ad1a3213e1727..c8f5db9e14505ddeda32925a662a2cc192a977c2 100644 (file)
@@ -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');
   }
 }