diff --git a/modules/timeutil/datetime.go b/modules/timeutil/datetime.go index 62b94f7cf481c..f8819a05df605 100644 --- a/modules/timeutil/datetime.go +++ b/modules/timeutil/datetime.go @@ -52,17 +52,16 @@ func DateTime(format string, datetime any, extraAttrs ...string) template.HTML { attrs := make([]string, 0, 10+len(extraAttrs)) attrs = append(attrs, extraAttrs...) attrs = append(attrs, `data-tooltip-content`, `data-tooltip-interactive="true"`) - attrs = append(attrs, `format="datetime"`, `weekday=""`, `year="numeric"`) + attrs = append(attrs, `weekday=""`, `year="numeric"`) switch format { - case "short": - attrs = append(attrs, `month="short"`, `day="numeric"`) - case "long": - attrs = append(attrs, `month="long"`, `day="numeric"`) + case "short", "long": + attrs = append(attrs, `month="`+format+`"`, `day="numeric"`) + return template.HTML(fmt.Sprintf(``, strings.Join(attrs, " "), datetimeEscaped)) case "full": - attrs = append(attrs, `month="short"`, `day="numeric"`, `hour="numeric"`, `minute="numeric"`, `second="numeric"`) + attrs = append(attrs, `format="datetime"`, `month="short"`, `day="numeric"`, `hour="numeric"`, `minute="numeric"`, `second="numeric"`) + return template.HTML(fmt.Sprintf(`%s`, strings.Join(attrs, " "), datetimeEscaped, textEscaped)) default: panic(fmt.Sprintf("Unsupported format %s", format)) } - return template.HTML(fmt.Sprintf(`%s`, strings.Join(attrs, " "), datetimeEscaped, textEscaped)) } diff --git a/templates/devtest/gitea-ui.tmpl b/templates/devtest/gitea-ui.tmpl index ccf188609c91d..929485eb7f58a 100644 --- a/templates/devtest/gitea-ui.tmpl +++ b/templates/devtest/gitea-ui.tmpl @@ -110,6 +110,16 @@
+
+

GiteaLocaleDate

+
+
+
+
+
+
relative-time:
+
+

LocaleNumber

{{ctx.Locale.PrettyNumber 1}}
diff --git a/web_src/js/webcomponents/GiteaLocaleDate.js b/web_src/js/webcomponents/GiteaLocaleDate.js new file mode 100644 index 0000000000000..fa33bb16b4c96 --- /dev/null +++ b/web_src/js/webcomponents/GiteaLocaleDate.js @@ -0,0 +1,37 @@ +window.customElements.define('gitea-locale-date', class extends HTMLElement { + static observedAttributes = ['date', 'year', 'month', 'weekday', 'day']; + + update = () => { + const year = this.getAttribute('year') ?? 'numeric'; + const month = this.getAttribute('month') ?? 'short'; + const weekday = this.getAttribute('weekday') ?? ''; + const day = this.getAttribute('day') ?? 'numeric'; + const lang = this.closest('[lang]')?.getAttribute('lang') || + this.ownerDocument.documentElement.getAttribute('lang') || + ''; + const date = new Date(this.getAttribute('date')); + + // apply negative timezone offset because `new Date()` above assumes that `yyyy-mm-dd` is + // a UTC date, so the local date will have a offset towards the user's timezone. + // Ref: https://stackoverflow.com/a/14569783/808699 + const correctedDate = new Date(date.getTime() - date.getTimezoneOffset() * -60000); + + this.textContent = correctedDate.toLocaleString(lang ?? [], { + ...(year && {year}), + ...(month && {month}), + ...(weekday && {weekday}), + ...(day && {day}), + }); + }; + + attributeChangedCallback(_name, oldValue, newValue) { + if (oldValue === newValue || !this.initialized) return; + this.update(); + } + + connectedCallback() { + this.initialized = false; + this.update(); + this.initialized = true; + } +}); diff --git a/web_src/js/webcomponents/webcomponents.js b/web_src/js/webcomponents/webcomponents.js index 916a588db64bf..b942f58ffc089 100644 --- a/web_src/js/webcomponents/webcomponents.js +++ b/web_src/js/webcomponents/webcomponents.js @@ -3,3 +3,4 @@ import './polyfill.js'; import '@github/relative-time-element'; import './GiteaOriginUrl.js'; +import './GiteaLocaleDate.js';