profile: add local time to profile tooltip

This is a user request: add local time of dive to the tooltip.

Showing a localized time was surprisingly complex. First I had
to add a function that decomposes a timestamp into h/m/s. Then
the QLocale time-string has to be stripped of the timezone.

Fixes #3469.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2022-07-31 22:23:24 +02:00
parent 4989041efd
commit 2e6d65ef08
4 changed files with 52 additions and 2 deletions

View File

@ -1,4 +1,4 @@
- profile: show local time of cursor position in tooltip (fixes #3469).
---
* Always add new entries at the very top of this file above other existing entries and this note.
* Use this layout for new entries: `[Area]: [Details about the change] [reference thread / issue]`

View File

@ -304,6 +304,18 @@ QString formatTripTitleWithDives(const dive_trip *trip)
gettextFromC::tr("(%n dive(s))", "", nr);
}
static QString formatTimeOfDay(timestamp_t when)
{
auto [h, m, s] = utc_time_of_day(when);
QLocale loc;
QString format = loc.timeFormat(QLocale::LongFormat);
// We don't want to show the timezone, as that currently is the
// timezone the application is run in, not the timezone of the dive!
format.replace("t", "");
QTime time(h, m, s);
return loc.toString(time, format.trimmed());
}
#define DIV_UP(x, y) (((x) + (y) - 1) / (y))
#define translate(x,y) qPrintable(QCoreApplication::translate(x,y))
@ -316,9 +328,11 @@ static QString formatPlotInfoInternal(const dive *d, const plot_info *pi, int id
int decimals, cyl;
const char *unit;
const struct plot_data *entry = pi->entry + idx;
timestamp_t when = d->when + entry->sec;
depthvalue = get_depth_units(entry->depth, NULL, &depth_unit);
res = qasprintf_loc("%s: %d:%02d\n", translate("gettextFromC", "@"), FRACTION(entry->sec, 60));
res = qasprintf_loc("%s: %d:%02d (%s)\n", translate("gettextFromC", "@"), FRACTION(entry->sec, 60),
qPrintable(formatTimeOfDay(when)));
res += qasprintf_loc("%s: %.1f%s\n", translate("gettextFromC", "D"), depthvalue, depth_unit);
for (cyl = 0; cyl < pi->nr_cylinders; cyl++) {
int mbar = get_plot_pressure(pi, idx, cyl);

View File

@ -9,10 +9,15 @@
extern "C" {
#endif
struct time_of_day {
int h, m, s;
};
extern timestamp_t utc_mktime(const struct tm *tm);
extern void utc_mkdate(timestamp_t, struct tm *tm);
extern int utc_year(timestamp_t timestamp);
extern int utc_weekday(timestamp_t timestamp);
extern struct time_of_day utc_time_of_day(timestamp_t timestamp);
/* parse and format date times of the form YYYY-MM-DD hh:mm:ss */
extern timestamp_t parse_datetime(const char *s); /* returns 0 on error */

View File

@ -99,6 +99,37 @@ void utc_mkdate(timestamp_t timestamp, struct tm *tm)
tm->tm_mon = m;
}
/*
* Convert 64-bit timestamp to time of day (split into h, m, s)
*
* On 32-bit machines, only do 64-bit arithmetic for the seconds
* part, after that we do everything in 'long'. 64-bit divides
* are unnecessary once you're counting minutes (32-bit minutes:
* 8000+ years).
*/
struct time_of_day utc_time_of_day(timestamp_t timestamp)
{
struct time_of_day res = { 0 };
unsigned long val;
// Midnight at Jan 1, 1970 means "no date"
if (!timestamp)
return res;
/* Convert to seconds since 1900 */
timestamp += EPOCH_OFFSET;
/* minutes since 1900 */
res.s = timestamp % 60;
val = timestamp / 60;
res.m = val % 60;
val /= 60;
res.h = val % 24;
return res;
}
timestamp_t utc_mktime(const struct tm *tm)
{
static const int mdays[] = {