diff --git a/frontend_tests/node_tests/timerender.js b/frontend_tests/node_tests/timerender.js
index d28db882b6..ee4c26e7b4 100644
--- a/frontend_tests/node_tests/timerender.js
+++ b/frontend_tests/node_tests/timerender.js
@@ -219,24 +219,59 @@ run_test("absolute_time_24_hour", () => {
assert.equal(actual, expected);
});
-run_test("set_full_datetime", () => {
- const message = {
- timestamp: 1495091573, // 2017/5/18 7:12:53 AM (UTC+0)
- };
+function test_set_full_datetime(message, expected_tooltip_content) {
const time_element = $("");
const attrs = {};
- time_element.attr = (name, val) => {
+ time_element.attr = (name, val = null) => {
+ if (val === null) {
+ return attrs[name];
+ }
attrs[name] = val;
- return time_element;
+ return val;
+ };
+
+ timerender.set_full_datetime(message, time_element);
+ assert.equal(attrs["data-tippy-content"], expected_tooltip_content);
+
+ // Removing `data-tippy-content` and re-running should
+ // set `data-tippy-content` value again.
+ delete attrs["data-tippy-content"];
+ timerender.set_full_datetime(message, time_element);
+ assert.equal(attrs["data-tippy-content"], expected_tooltip_content);
+}
+
+run_test("set_full_datetime", () => {
+ let message = {
+ timestamp: 1495091573, // 2017/5/18 7:12:53 AM (UTC+0)
};
// The formatting of the string time.toLocale(Date|Time)String() on Node
// might differ from the browser.
- const time = new Date(message.timestamp * 1000);
- const expected = `${time.toLocaleDateString()} 7:12:53 AM (UTC+0)`;
- timerender.set_full_datetime(message, time_element);
- assert.equal(attrs.title, expected);
+ let time = new Date(message.timestamp * 1000);
+ let expected = `${time.toLocaleDateString("en", {
+ weekday: "long",
+ month: "long",
+ day: "numeric",
+ year: "numeric",
+ })}
7:12:53 AM Coordinated Universal Time`;
+ test_set_full_datetime(message, expected);
+
+ // Check year is hidden if current year.
+ time = new Date();
+ message = {
+ timestamp: Math.floor(time.getTime() / 1000),
+ };
+ // Also check 24hour time format is shown.
+ page_params.twenty_four_hour_time = true;
+ const date_string = time.toLocaleDateString("en", {
+ weekday: "long",
+ month: "long",
+ day: "numeric",
+ });
+ const time_string = time.toLocaleString("en", {timeStyle: "full", hourCycle: "h24"});
+ expected = `${date_string}
${time_string}`;
+ test_set_full_datetime(message, expected);
});
run_test("last_seen_status_from_date", () => {
diff --git a/static/js/timerender.js b/static/js/timerender.js
index 0eb7e83a96..f4295873ce 100644
--- a/static/js/timerender.js
+++ b/static/js/timerender.js
@@ -307,29 +307,38 @@ export const absolute_time = (function () {
})();
export function get_full_datetime(time) {
- // Convert to number of hours ahead/behind UTC.
- // The sign of getTimezoneOffset() is reversed wrt
- // the conventional meaning of UTC+n / UTC-n
- const tz_offset = -time.getTimezoneOffset() / 60;
+ const date_string_options = {weekday: "long", month: "long", day: "numeric"};
+ const time_string_options = {timeStyle: "full"};
+
+ if (page_params.twenty_four_hour_time) {
+ time_string_options.hourCycle = "h24";
+ }
+
+ const current_date = new Date();
+ if (time.getFullYear() !== current_date.getFullYear()) {
+ // Show year only if not current year.
+ date_string_options.year = "numeric";
+ }
+
return {
- date: time.toLocaleDateString(),
- time: time.toLocaleTimeString() + " (UTC" + (tz_offset < 0 ? "" : "+") + tz_offset + ")",
+ date: time.toLocaleDateString(page_params.request_language, date_string_options),
+ time: time.toLocaleTimeString(page_params.request_language, time_string_options),
};
}
+function render_tippy_tooltip(message, time_elem) {
+ time_elem.attr("data-tippy-content", message.full_date_str + "
" + message.full_time_str);
+}
+
// Date.toLocaleDateString and Date.toLocaleTimeString are
// expensive, so we delay running the following code until we need
// the full date and time strings.
export const set_full_datetime = function timerender_set_full_datetime(message, time_elem) {
- if (message.full_date_str !== undefined) {
- return;
- }
-
const time = new Date(message.timestamp * 1000);
const full_datetime = get_full_datetime(time);
message.full_date_str = full_datetime.date;
message.full_time_str = full_datetime.time;
- time_elem.attr("title", message.full_date_str + " " + message.full_time_str);
+ render_tippy_tooltip(message, time_elem);
};
diff --git a/static/js/tippyjs.js b/static/js/tippyjs.js
index aaead56882..41c751ee97 100644
--- a/static/js/tippyjs.js
+++ b/static/js/tippyjs.js
@@ -145,4 +145,14 @@ export function initialize() {
return true;
},
});
+
+ delegate("body", {
+ target: ".message_time",
+ allowHTML: true,
+ placement: "top",
+ appendTo: () => document.body,
+ onHidden(instance) {
+ instance.destroy();
+ },
+ });
}