Add configurable server timezone

This commit is contained in:
Louis Lam 2022-10-09 20:59:58 +08:00
parent b007681e67
commit a36f24d827
7 changed files with 66 additions and 13 deletions

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "uptime-kuma", "name": "uptime-kuma",
"version": "1.18.3", "version": "1.18.4",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "uptime-kuma", "name": "uptime-kuma",
"version": "1.18.3", "version": "1.18.4",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@louislam/sqlite3": "~15.0.6", "@louislam/sqlite3": "~15.0.6",

View file

@ -123,7 +123,7 @@
"@vitejs/plugin-legacy": "~2.1.0", "@vitejs/plugin-legacy": "~2.1.0",
"@vitejs/plugin-vue": "~3.1.0", "@vitejs/plugin-vue": "~3.1.0",
"@vue/compiler-sfc": "~3.2.36", "@vue/compiler-sfc": "~3.2.36",
"@vuepic/vue-datepicker": "^3.4.8", "@vuepic/vue-datepicker": "~3.4.8",
"aedes": "^0.46.3", "aedes": "^0.46.3",
"babel-plugin-rewire": "~1.2.0", "babel-plugin-rewire": "~1.2.0",
"bootstrap": "5.1.3", "bootstrap": "5.1.3",

View file

@ -5,6 +5,11 @@
*/ */
console.log("Welcome to Uptime Kuma"); console.log("Welcome to Uptime Kuma");
// As the log function need to use dayjs, it should be very top
const dayjs = require("dayjs");
dayjs.extend(require("dayjs/plugin/utc"));
dayjs.extend(require("dayjs/plugin/timezone"));
// Check Node.js Version // Check Node.js Version
const nodeVersion = parseInt(process.versions.node.split(".")[0]); const nodeVersion = parseInt(process.versions.node.split(".")[0]);
const requiredVersion = 14; const requiredVersion = 14;
@ -34,10 +39,6 @@ const fs = require("fs");
log.info("server", "Importing 3rd-party libraries"); log.info("server", "Importing 3rd-party libraries");
const dayjs = require("dayjs");
dayjs.extend(require("dayjs/plugin/utc"));
dayjs.extend(require("dayjs/plugin/timezone"));
log.debug("server", "Importing express"); log.debug("server", "Importing express");
const express = require("express"); const express = require("express");
const expressStaticGzip = require("express-static-gzip"); const expressStaticGzip = require("express-static-gzip");
@ -160,6 +161,7 @@ let needSetup = false;
(async () => { (async () => {
Database.init(args); Database.init(args);
await initDatabase(testMode); await initDatabase(testMode);
await server.initAfterDatabaseReady();
exports.entryPage = await setting("entryPage"); exports.entryPage = await setting("entryPage");
await StatusPage.loadDomainMappingList(); await StatusPage.loadDomainMappingList();
@ -1061,10 +1063,15 @@ let needSetup = false;
socket.on("getSettings", async (callback) => { socket.on("getSettings", async (callback) => {
try { try {
checkLogin(socket); checkLogin(socket);
const data = await getSettings("general");
if (!data.serverTimezone) {
data.serverTimezone = await server.getTimezone();
}
callback({ callback({
ok: true, ok: true,
data: await getSettings("general"), data: data,
}); });
} catch (e) { } catch (e) {
@ -1092,9 +1099,14 @@ let needSetup = false;
await setSettings("general", data); await setSettings("general", data);
exports.entryPage = data.entryPage; exports.entryPage = data.entryPage;
// Also need to apply timezone globally
if (data.serverTimezone) {
await server.setTimezone(data.serverTimezone);
}
callback({ callback({
ok: true, ok: true,
msg: "Saved" msg: "Saved " + dayjs()
}); });
sendInfo(socket); sendInfo(socket);

View file

@ -9,6 +9,7 @@ const Database = require("./database");
const util = require("util"); const util = require("util");
const { CacheableDnsHttpAgent } = require("./cacheable-dns-http-agent"); const { CacheableDnsHttpAgent } = require("./cacheable-dns-http-agent");
const { Settings } = require("./settings"); const { Settings } = require("./settings");
const dayjs = require("dayjs");
/** /**
* `module.exports` (alias: `server`) should be inside this class, in order to avoid circular dependency issue. * `module.exports` (alias: `server`) should be inside this class, in order to avoid circular dependency issue.
@ -84,6 +85,13 @@ class UptimeKumaServer {
this.io = new Server(this.httpServer); this.io = new Server(this.httpServer);
} }
async initAfterDatabaseReady() {
process.env.TZ = await this.getTimezone();
dayjs.tz.setDefault(process.env.TZ);
log.debug("DEBUG", "Timezone: " + process.env.TZ);
log.debug("DEBUG", "Current Time: " + dayjs.tz().format());
}
async sendMonitorList(socket) { async sendMonitorList(socket) {
let list = await this.getMonitorJSONList(socket.userID); let list = await this.getMonitorJSONList(socket.userID);
this.io.to(socket.userID).emit("monitorList", list); this.io.to(socket.userID).emit("monitorList", list);
@ -184,6 +192,23 @@ class UptimeKumaServer {
return clientIP.replace(/^.*:/, ""); return clientIP.replace(/^.*:/, "");
} }
} }
async getTimezone() {
let timezone = await Settings.get("serverTimezone");
if (timezone) {
return timezone;
} else if (process.env.TZ) {
return process.env.TZ;
} else {
return dayjs.tz.guess();
}
}
async setTimezone(timezone) {
await Settings.set("serverTimezone", timezone, "general");
process.env.TZ = timezone;
dayjs.tz.setDefault(timezone);
}
} }
module.exports = { module.exports = {

View file

@ -1,10 +1,10 @@
<template> <template>
<div> <div>
<form class="my-4" @submit.prevent="saveGeneral"> <form class="my-4" @submit.prevent="saveGeneral">
<!-- Timezone --> <!-- Client side Timezone -->
<div class="mb-4"> <div class="mb-4">
<label for="timezone" class="form-label"> <label for="timezone" class="form-label">
{{ $t("Timezone") }} {{ $t("Display Timezone") }}
</label> </label>
<select id="timezone" v-model="$root.userTimezone" class="form-select"> <select id="timezone" v-model="$root.userTimezone" class="form-select">
<option value="auto"> <option value="auto">
@ -20,6 +20,22 @@
</select> </select>
</div> </div>
<!-- Server Timezone -->
<div class="mb-4">
<label for="timezone" class="form-label">
{{ $t("Server Timezone") }}
</label>
<select id="timezone" v-model="settings.serverTimezone" class="form-select">
<option
v-for="(timezone, index) in timezoneList"
:key="index"
:value="timezone.value"
>
{{ timezone.name }}
</option>
</select>
</div>
<!-- Search Engine --> <!-- Search Engine -->
<div class="mb-4"> <div class="mb-4">
<label class="form-label"> <label class="form-label">

View file

@ -101,7 +101,7 @@ class Logger {
} }
module = module.toUpperCase(); module = module.toUpperCase();
level = level.toUpperCase(); level = level.toUpperCase();
const now = new Date().toISOString(); const now = dayjs.tz(new Date()).format();
const formattedMessage = (typeof msg === "string") ? `${now} [${module}] ${level}: ${msg}` : msg; const formattedMessage = (typeof msg === "string") ? `${now} [${module}] ${level}: ${msg}` : msg;
if (level === "INFO") { if (level === "INFO") {
console.info(formattedMessage); console.info(formattedMessage);

View file

@ -116,7 +116,7 @@ class Logger {
module = module.toUpperCase(); module = module.toUpperCase();
level = level.toUpperCase(); level = level.toUpperCase();
const now = new Date().toISOString(); const now = dayjs.tz(new Date()).format();
const formattedMessage = (typeof msg === "string") ? `${now} [${module}] ${level}: ${msg}` : msg; const formattedMessage = (typeof msg === "string") ? `${now} [${module}] ${level}: ${msg}` : msg;
if (level === "INFO") { if (level === "INFO") {