Use local time, if available, in the web interface, fixes #427
This commit is contained in:
@@ -19,15 +19,47 @@
|
||||
|
||||
#include "Logger.hpp"
|
||||
|
||||
#include <Wt/WDateTime.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
|
||||
#include "core/Exception.hpp"
|
||||
#include "core/String.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string localISO8601TimeString()
|
||||
{
|
||||
using Clock = std::chrono::system_clock;
|
||||
const auto now{ Clock::now() };
|
||||
const int ms{ static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count() % 1000) };
|
||||
const std::time_t tt{ Clock::to_time_t(now) };
|
||||
std::tm tm{};
|
||||
::localtime_r(&tt, &tm);
|
||||
|
||||
std::array<char, 24> datetime{};
|
||||
std::array<char, 8> offset{};
|
||||
std::strftime(datetime.data(), datetime.size(), "%Y-%m-%dT%H:%M:%S", &tm);
|
||||
std::strftime(offset.data(), offset.size(), "%z", &tm); // "+HHMM" or "-HHMM"
|
||||
|
||||
// Append msecs and offset
|
||||
const std::string_view offsetView{ offset.data() };
|
||||
std::string result{ datetime.data() };
|
||||
result += '.';
|
||||
result += static_cast<char>('0' + ms / 100);
|
||||
result += static_cast<char>('0' + (ms / 10) % 10);
|
||||
result += static_cast<char>('0' + ms % 10);
|
||||
result += offsetView.substr(0, 3); // sign + HH
|
||||
result += ':';
|
||||
result += offsetView.substr(3); // MM
|
||||
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace lms::core::logging
|
||||
{
|
||||
@@ -205,9 +237,8 @@ namespace lms::core::logging
|
||||
{
|
||||
assert(isSeverityActive(severity)); // should have been filtered out by a isSeverityActive call
|
||||
OutputStream* outputStream{ _severityToOutputStreamMap.at(severity) };
|
||||
const Wt::WDateTime now{ Wt::WDateTime::currentDateTime() };
|
||||
|
||||
std::unique_lock lock{ outputStream->mutex };
|
||||
outputStream->stream << stringUtils::toISO8601String(now) << " " << std::this_thread::get_id() << " [" << getSeverityName(severity) << "] [" << getModuleName(module) << "] " << message << std::endl;
|
||||
outputStream->stream << localISO8601TimeString() << " " << std::this_thread::get_id() << " [" << getSeverityName(severity) << "] [" << getModuleName(module) << "] " << message << std::endl;
|
||||
}
|
||||
} // namespace lms::core::logging
|
||||
} // namespace lms::core::logging
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#include "LmsApplication.hpp"
|
||||
|
||||
#include <Wt/WConfig.h>
|
||||
|
||||
#include <Wt/WAnchor.h>
|
||||
#include <Wt/WEnvironment.h>
|
||||
#include <Wt/WLineEdit.h>
|
||||
@@ -117,7 +119,7 @@ namespace lms::ui
|
||||
return res;
|
||||
}
|
||||
|
||||
Wt::WLocale createLocale(const std::string& name)
|
||||
Wt::WLocale createLocale(const std::string& name, [[maybe_unused]] const std::string& timeZoneName)
|
||||
{
|
||||
Wt::WLocale locale{ name };
|
||||
locale.setDecimalPoint(Wt::WString::tr("Lms.locale.decimal-point").toUTF8());
|
||||
@@ -126,6 +128,19 @@ namespace lms::ui
|
||||
locale.setTimeFormat(Wt::WString::tr("Lms.locale.time-format").toUTF8());
|
||||
locale.setDateTimeFormat(Wt::WString::tr("Lms.locale.date-time-format").toUTF8());
|
||||
|
||||
#ifdef WT_DATE_TZ_USE_STD
|
||||
if (!timeZoneName.empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
locale.setTimeZone(std::chrono::locate_zone(timeZoneName));
|
||||
}
|
||||
catch (const std::runtime_error&)
|
||||
{
|
||||
// unknown zone, display stays UTC
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return locale;
|
||||
}
|
||||
|
||||
@@ -224,7 +239,7 @@ namespace lms::ui
|
||||
|
||||
setTitle();
|
||||
setLocalizedStrings(getOrCreateMessageBundle());
|
||||
setLocale(createLocale(Wt::WLocale::currentLocale().name()));
|
||||
setLocale(createLocale(Wt::WLocale::currentLocale().name(), environment().timeZoneName()));
|
||||
|
||||
// Handle Media Scanner events and other session events
|
||||
enableUpdates(true);
|
||||
@@ -325,7 +340,7 @@ namespace lms::ui
|
||||
|
||||
setUserInfo(userId, strongAuth);
|
||||
|
||||
LMS_LOG(UI, INFO, "User '" << getUserLoginName() << "' logged in from '" << environment().clientAddress() << "', user agent = " << environment().userAgent() << ", locale = '" << locale().name() << "'");
|
||||
LMS_LOG(UI, INFO, "User '" << getUserLoginName() << "' logged in from '" << environment().clientAddress() << "', user agent = " << environment().userAgent() << ", locale = '" << locale().name() << "', timezone = '" << environment().timeZoneName() << "'");
|
||||
|
||||
_appManager.registerApplication(*this);
|
||||
_appManager.applicationRegistered.connect(this, [this](LmsApplication& otherApplication) {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <Wt/WCheckBox.h>
|
||||
#include <Wt/WDateTime.h>
|
||||
#include <Wt/WLocalDateTime.h>
|
||||
#include <Wt/WLocale.h>
|
||||
#include <Wt/WPushButton.h>
|
||||
#include <Wt/WResource.h>
|
||||
@@ -114,11 +115,26 @@ namespace lms::ui
|
||||
{
|
||||
if (status.lastCompleteScanStats)
|
||||
{
|
||||
const auto& locale{ Wt::WLocale::currentLocale() };
|
||||
const Wt::WDateTime& stopTime{ status.lastCompleteScanStats->stopTime };
|
||||
Wt::WString stopDateStr;
|
||||
Wt::WString stopTimeStr;
|
||||
if (locale.timeZone())
|
||||
{
|
||||
const Wt::WLocalDateTime local{ stopTime.toLocalTime() };
|
||||
stopDateStr = local.date().toString(locale.dateFormat());
|
||||
stopTimeStr = local.time().toString(locale.timeFormat());
|
||||
}
|
||||
else
|
||||
{
|
||||
stopDateStr = stopTime.date().toString(locale.dateFormat());
|
||||
stopTimeStr = stopTime.time().toString(locale.timeFormat()) + " (UTC)";
|
||||
}
|
||||
_lastScanStatus->setText(Wt::WString::tr("Lms.Admin.ScannerController.last-scan-status")
|
||||
.arg(status.lastCompleteScanStats->getTotalFileCount())
|
||||
.arg(durationToString(status.lastCompleteScanStats->startTime, status.lastCompleteScanStats->stopTime))
|
||||
.arg(status.lastCompleteScanStats->stopTime.date().toString(Wt::WLocale::currentLocale().dateFormat()))
|
||||
.arg(status.lastCompleteScanStats->stopTime.time().toString(Wt::WLocale::currentLocale().timeFormat()))
|
||||
.arg(stopDateStr)
|
||||
.arg(stopTimeStr)
|
||||
.arg(status.lastCompleteScanStats->errorsCount)
|
||||
.arg(status.lastCompleteScanStats->duplicates.size()));
|
||||
|
||||
@@ -144,11 +160,27 @@ namespace lms::ui
|
||||
break;
|
||||
|
||||
case IScannerService::State::Scheduled:
|
||||
_status->setText(Wt::WString::tr("Lms.Admin.ScannerController.status-scheduled")
|
||||
.arg(status.nextScheduledScan.date().toString(Wt::WLocale::currentLocale().dateFormat()))
|
||||
.arg(status.nextScheduledScan.time().toString(Wt::WLocale::currentLocale().timeFormat())));
|
||||
_stepStatus->setText("");
|
||||
break;
|
||||
{
|
||||
const auto& locale{ Wt::WLocale::currentLocale() };
|
||||
Wt::WString nextDateStr;
|
||||
Wt::WString nextTimeStr;
|
||||
if (locale.timeZone())
|
||||
{
|
||||
const Wt::WLocalDateTime local{ status.nextScheduledScan.toLocalTime() };
|
||||
nextDateStr = local.date().toString(locale.dateFormat());
|
||||
nextTimeStr = local.time().toString(locale.timeFormat());
|
||||
}
|
||||
else
|
||||
{
|
||||
nextDateStr = status.nextScheduledScan.date().toString(locale.dateFormat());
|
||||
nextTimeStr = status.nextScheduledScan.time().toString(locale.timeFormat()) + " (UTC)";
|
||||
}
|
||||
_status->setText(Wt::WString::tr("Lms.Admin.ScannerController.status-scheduled")
|
||||
.arg(nextDateStr)
|
||||
.arg(nextTimeStr));
|
||||
_stepStatus->setText("");
|
||||
break;
|
||||
}
|
||||
|
||||
case IScannerService::State::InProgress:
|
||||
assert(status.currentScanStepStats);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <Wt/WCheckBox.h>
|
||||
#include <Wt/WComboBox.h>
|
||||
#include <Wt/WLineEdit.h>
|
||||
#include <Wt/WLocalDateTime.h>
|
||||
#include <Wt/WPushButton.h>
|
||||
#include <Wt/WTemplateFormView.h>
|
||||
|
||||
@@ -229,7 +230,10 @@ namespace lms::ui
|
||||
|
||||
t->bindString("title", title, Wt::TextFormat::Plain);
|
||||
t->setCondition("if-has-last-login", true);
|
||||
t->bindString("last-login", user->getLastLogin().toString(), Wt::TextFormat::Plain);
|
||||
const auto& locale{ Wt::WLocale::currentLocale() };
|
||||
const Wt::WDateTime lastLogin{ user->getLastLogin() };
|
||||
const Wt::WString lastLoginStr{ locale.timeZone() ? lastLogin.toLocalTime().toString() : lastLogin.toString(locale.dateTimeFormat()) + " (UTC)" };
|
||||
t->bindString("last-login", lastLoginStr, Wt::TextFormat::Plain);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user