feat: relative or absolute timestamping depending on time/date proximity

- implement LocaleUtils.formatRelativeTimestamp() that does all the heavy
  lifting
- use it in StatusTimeStampLabel -> propagates to all message timestamps
  (chat, activity center, settings, etc)

Closes #9397
This commit is contained in:
Lukáš Tinkl 2023-02-21 18:15:17 +01:00 committed by Lukáš Tinkl
parent e4d03a903e
commit 340866612b
2 changed files with 38 additions and 1 deletions

View File

@ -12,7 +12,7 @@ StatusBaseText {
color: Theme.palette.baseColor1
font.pixelSize: 10
visible: !!text
text: showFullTimestamp ? LocaleUtils.formatDateTime(timestamp) : LocaleUtils.formatTime(timestamp, Locale.ShortFormat)
text: showFullTimestamp ? LocaleUtils.formatDateTime(timestamp) : LocaleUtils.formatRelativeTimestamp(timestamp)
StatusToolTip {
id: tooltip
visible: hhandler.hovered && !!text

View File

@ -78,6 +78,8 @@ QtObject {
readonly property var amPmFormatChars: ["AP", "A", "ap", "a"]
readonly property int msInADay: 86400000
// try to parse date from a number or ISO string timestamp
function readDate(value) {
if (typeof value === "undefined") // default to "now" if omitted
@ -102,6 +104,13 @@ QtObject {
return result
}
}
// return full days between 2 dates
function daysBetween(firstDate, secondDate) {
firstDate.setHours(0, 0, 0) // discard time
secondDate.setHours(0, 0, 0)
return Math.round(Math.abs((firstDate - secondDate) / d.msInADay)) // Math.round: not all days are 24 hours long!
}
}
readonly property Settings settings: Settings {
@ -162,6 +171,34 @@ QtObject {
return value.toLocaleString(loc, formatString)
}
// TODO use JS Intl.RelativeTimeFormat in Qt 6?
function formatRelativeTimestamp(timestamp) {
const now = new Date()
const value = d.readDate(timestamp)
const loc = Qt.locale()
const formatString = d.fixupTimeFormatString(loc.timeFormat(Locale.ShortFormat)) // format string for the time part
const dayDifference = d.daysBetween(d.readDate(timestamp), now)
// within last day, 2 or 7 days
if (dayDifference < 1) // today -> "Today 14:23"
return qsTr("Today %1").arg(value.toLocaleTimeString(loc, formatString))
if (dayDifference < 2) // yesterday -> "Yesterday 14:23"
return qsTr("Yesterday %1").arg(value.toLocaleTimeString(loc, formatString))
if (dayDifference < 7) // last 7 days -> "Mon 14:23"
return qsTr("%1 %2").arg(loc.standaloneDayName(value.getDay(), Locale.ShortFormat)).arg(value.toLocaleTimeString(loc, formatString))
// otherwise
var fullFormatString = d.fixupTimeFormatString(loc.dateTimeFormat(Locale.ShortFormat))
if (now.getFullYear() === value.getFullYear())
fullFormatString = fullFormatString.replace(/y/g, "") // strip year part, if current year -> "31 December 09:41"
else
fullFormatString = fullFormatString.replace("yy", "yyyy") // different year -> "31 December 2022 09:41"
return value.toLocaleString(loc, fullFormatString)
}
function getTimeDifference(d1, d2) {
const day1Year = d1.getFullYear()
const day1Month = d1.getMonth()