Skip to content

luci-mod-status: use localized time#8014

Merged
systemcrash merged 4 commits intoopenwrt:masterfrom
AndyChiang888:localized-time
Oct 20, 2025
Merged

luci-mod-status: use localized time#8014
systemcrash merged 4 commits intoopenwrt:masterfrom
AndyChiang888:localized-time

Conversation

@AndyChiang888
Copy link
Copy Markdown
Contributor

@AndyChiang888 AndyChiang888 commented Oct 15, 2025

Use localized time for luci-mod-status luci-mod-system and luci-mod-dashboard.
This will allow display appropriate time format for each region/language.

1 2 3
root@OpenWrt:~# ubus call system info
{
        "localtime": 1760575303,
        "unixtime": 1760550103,
        "uptime": 9225,
        "load": [
                4384,
                1728,
                384
        ],
        "memory": {
                "total": 8181231616,
                "free": 7570432000,
                "shared": 2363392,
                "buffered": 16850944,
                "available": 7661576192,
                "cached": 182722560
        },
        "root": {
                "total": 1674496,
                "free": 1584524,
                "used": 89972,
                "avail": 1584524
        },
        "tmp": {
                "total": 3994740,
                "free": 3992668,
                "used": 2072,
                "avail": 3992668
        },
        "swap": {
                "total": 0,
                "free": 0
        }
}
  • This PR is not from my main or master branch 💩, but a separate branch ✅
  • Each commit has a valid ✒️ Signed-off-by: <my@email.address> row (via git commit --signoff)
  • Each commit and PR title has a valid 📝 <package name>: title first line subject for packages
  • Incremented 🆙 any PKG_VERSION in the Makefile
  • Tested on: (x86/64, openwrt r31441-7dd62db9a9, Chrome) ✅
  • ( Preferred ) Mention: @ the original code author for feedback
  • ( Preferred ) Screenshot or mp4 of changes:
  • ( Optional ) Closes: e.g. openwrt/luci#issue-number
  • [] ( Optional ) Depends on:
  • Description: (describe the changes proposed in this PR)

@AndyChiang888
Copy link
Copy Markdown
Contributor Author

AndyChiang888 commented Oct 16, 2025

If we continue to use systeminfo.localtime, we can only set the timeZone to UTC like this:

date.toLocaleString(undefined, { hour12: false, timeZone: 'UTC' });

Which will not display the correct zonename.

If we want display the correct zonename on the homepage, we need unixtime. On this basis, if we do not want the timezone change follow browser timezone, we can set timeZone like this:

date.toLocaleString(undefined, { hour12: false, timeZoneName: 'long', timeZone: zonename });

zonename can be written to /tmp/ZA via /etc/init.d/system at startup like /tmp/TZ,and get it via rpc.
However, for most people, the router's timezone is the same as the browser's timezone, so this can be added later or be ignored.

Should we continue to wait for unixtime or use localtime first?
I think we should at least display it in the appropriate format based on the browser's language/region.
As for the time zone issue, we can deal with it later, after we have unixtime.

Any thoughts from @systemcrash @hnyman ?

@systemcrash
Copy link
Copy Markdown
Contributor

@AndyChiang888
Copy link
Copy Markdown
Contributor Author

Well, let us use Intl.DateTimeFormat, but we no unixtime now, so we can only use localtime with UTC first.
Once we have unixtime, we can modify code to:

{ dateStyle: "medium", timeStyle: "full" }

Remove timeZone and use the system's timezone so that the correct zonename can be displayed like this:

Dec 19, 2020, 10:23:16 PM Eastern Standard Time

@AndyChiang888 AndyChiang888 marked this pull request as ready for review October 17, 2025 00:32
@AndyChiang888
Copy link
Copy Markdown
Contributor Author

AndyChiang888 commented Oct 17, 2025

The user timezone is set in the system settings, so it's accessible.

Yours: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString Recommended: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat

If timeZone is not specified, the system settings are used, which is fine for most people. However, if someone's system and the router are in different timezone, do we need to specify timeZone as the zonename value from /etc/config/system in the js file so that the router can output a fixed timezone instead of the system settings?
But this is not a big deal. We can use the value in /tmp/ZA as the timeZone, or ignore this issue.

All this has to wait until unixtime is available.

@AndyChiang888
Copy link
Copy Markdown
Contributor Author

@systemcrash
My test is OK, do you think there is anything that needs to be improved?

@systemcrash
Copy link
Copy Markdown
Contributor

See 5443299.

Now:

callGetUnixtime = rpc.declare({
	object: 'luci',
	method: 'getUnixtime',
	expect: { result: 0 }
});

@AndyChiang888
Copy link
Copy Markdown
Contributor Author

Great, then I can use unixtime and add timezone display. I will push it again later.

@AndyChiang888 AndyChiang888 force-pushed the localized-time branch 4 times, most recently from 47464b0 to d5f4bfa Compare October 17, 2025 15:32
@systemcrash
Copy link
Copy Markdown
Contributor

Now I think you need to provide it with the TZ set in system.system so that the Local Time displayed on the unit is actually the local time on the unit, using its timezone, and not the timezone set on the user's (web browser's) system.

@hnyman
Copy link
Copy Markdown
Contributor

hnyman commented Oct 17, 2025

Please be careful with the timezone related things. It's handling in OpenWrt is complex enough due to minimal approach, where most routers do not have "normal" large zoneinfo packages installed, and instead LuCI contains a POSIX string based list of current time zones. But some people do have zoneinfo installed.

And there may be differences in musl / glibc handling of timezones.

AndyChiang888 added a commit to AndyChiang888/openwrt that referenced this pull request Oct 18, 2025
add zonename for localized time
Link: openwrt/luci#8014

Signed-off-by: Andy Chiang <AndyChiang_git@outlook.com>
@AndyChiang888
Copy link
Copy Markdown
Contributor Author

luci part is complete, now we need use /tmp/ZN to fixed timezone.

AndyChiang888 added a commit to AndyChiang888/openwrt that referenced this pull request Oct 18, 2025
base-files: add zonename for localized time
Link: openwrt/luci#8014

Signed-off-by: Andy Chiang <AndyChiang_git@outlook.com>
AndyChiang888 added a commit to AndyChiang888/openwrt that referenced this pull request Oct 18, 2025
add zonename for localized time
Link: openwrt/luci#8014

Signed-off-by: Andy Chiang <AndyChiang_git@outlook.com>
@systemcrash
Copy link
Copy Markdown
Contributor

Why not just use something simpler like uci.get('system', 'system', 'zonename') and uci.get('system', 'system', 'timezone')?

@AndyChiang888
Copy link
Copy Markdown
Contributor Author

considering the life of flash, it is best to read the memory.
the timeZone of Intl.DateTimeFormat can only use system', 'system', 'zonename', and does not support system', 'system', 'timezone', otherwise I would use /tmp/TZ.

image image image

@AndyChiang888
Copy link
Copy Markdown
Contributor Author

so /tmp/ZN is necessary

@systemcrash
Copy link
Copy Markdown
Contributor

considering the life of flash, it is best to read the memory.

That's what uci.get does. I don't follow.

Your second picture which show RangeError uses a TZ which is identical informat to what I have in my /tmp/TZ file. So use system.@system[0].zonename

@AndyChiang888
Copy link
Copy Markdown
Contributor Author

AndyChiang888 commented Oct 18, 2025

considering the life of flash, it is best to read the memory.

That's what uci.get does. I don't follow.

Your second picture which show RangeError uses a TZ which is identical informat to what I have in my /tmp/TZ file. So use system.@system[0].zonename

I tried to get the zonename via uci.get in js, but there is a drawback. If zonename changes, the value obtained by uci.load and uci.get will not change. We need to manually refresh the web page. And when manually refresh the web page, uci.load will still access from flash. The existing solution will write the new zonename to /tmp/ZN through /etc/init.d/system if the zonename is updated. Each Polling will automatically get the latest value.

	load: function() {
		return Promise.all([
			L.resolveDefault(callSystemBoard(), {}),
			L.resolveDefault(callSystemInfo(), {}),
			L.resolveDefault(callLuciVersion(), { revision: _('unknown version'), branch: 'LuCI' }),
			L.resolveDefault(callGetUnixtime(), {}),
			uci.load('system')
		]);
	},

	render: function(data) {
		var boardinfo   = data[0],
		    systeminfo  = data[1],
		    luciversion = data[2],
		    unixtime    = data[3];

		luciversion = luciversion.branch + ' ' + luciversion.revision;

		var datestr = null;

		if (unixtime) {
			var date = new Date(unixtime * 1000);
			var zn = uci.get('system', '@system[0]', 'zonename') || 'UTC';

			datestr = new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', timeStyle: 'full', timeZone: zn }).format(date);
		}

This also avoids the need to access the flash every time we open a web page due to uci.load and uci.get.

Therefore, whether from the perspective of polling or reducing flash access, writing zonename to /tmp/ZN through /etc/init.d/system is the best solution.

@systemcrash
Copy link
Copy Markdown
Contributor

Maybe, but configured timezones rarely change, so that's unnecessary. And it's only used in the browser display, so I don't see the point.

@AndyChiang888
Copy link
Copy Markdown
Contributor Author

Well, I'll use uci.get instead. It is true that timezone rarely change.
And for me, I use x86/64, so access SSD has almost no effect on its lifespan.

@AndyChiang888
Copy link
Copy Markdown
Contributor Author

I have added the option to customize the time format.
Now we can choose to display the full timezone name or the timezone offset according to our preference.

const date = new Date(Date.UTC(2020, 11, 20, 3, 23, 16, 738));
console.log(
  new Intl.DateTimeFormat("en-GB", {
    dateStyle: "medium",
    timeStyle: "long",
    timeZone: "Australia/Sydney",
    hourCycle: undefined
  }).format(date),
);
console.log(
  new Intl.DateTimeFormat("en-GB", {
    dateStyle: "medium",
    timeStyle: "long",
    timeZone: "Australia/Sydney",
    hourCycle: 'h11'
  }).format(date),
);
console.log(
  new Intl.DateTimeFormat("en-GB", {
    dateStyle: "medium",
    timeStyle: "long",
    timeZone: "Australia/Sydney",
    hourCycle: 'h23'
  }).format(date),
);

console.log(
  new Intl.DateTimeFormat("en-GB", {
    dateStyle: "medium",
    timeStyle: "full",
    timeZone: "Australia/Sydney",
    hourCycle: undefined
  }).format(date),
);
console.log(
  new Intl.DateTimeFormat("en-GB", {
    dateStyle: "medium",
    timeStyle: "full",
    timeZone: "Australia/Sydney",
    hourCycle: 'h11'
  }).format(date),
);
console.log(
  new Intl.DateTimeFormat("en-GB", {
    dateStyle: "medium",
    timeStyle: "full",
    timeZone: "Australia/Sydney",
    hourCycle: 'h23'
  }).format(date),
);

Shown as:

"20 Dec 2020, 14:23:16 GMT+11"
"20 Dec 2020, 02:23:16 pm GMT+11"
"20 Dec 2020, 14:23:16 GMT+11"
"20 Dec 2020, 14:23:16 Australian Eastern Daylight Time"
"20 Dec 2020, 02:23:16 pm Australian Eastern Daylight Time"
"20 Dec 2020, 14:23:16 Australian Eastern Daylight Time"

@systemcrash
Copy link
Copy Markdown
Contributor

Use h12 and h24 - using h11 you can see weird things like 00pm/am.

@systemcrash
Copy link
Copy Markdown
Contributor

systemcrash commented Oct 20, 2025

Found another bug. You must process the timeZone zonename and replace all spaces for _ so the function completes. It can't handle spaces in names, e.g.

	'Africa/Dar es Salaam': 'EAT-3',
...
	'Africa/El Aaiun': 'XXX-2<+01>-1,0/0,J365/23',
...
	'Africa/Sao Tome': 'GMT0',
...

etc

fixed in d9a087e

@AndyChiang888
Copy link
Copy Markdown
Contributor Author

Use h12 and h24 - using h11 you can see weird things like 00pm/am.

We should use h12, but not h24, otherwise it will be like this:

const date = new Date(Date.UTC(2020, 11, 20, 13, 05, 00, 738));
console.log(
  new Intl.DateTimeFormat("en-GB", {
    dateStyle: "full",
    timeStyle: "long",
    timeZone: "Australia/Sydney",
    hourCycle: 'h24'
  }).format(date),
);

Monday 21 December 2020 at 24:05:00 GMT+11
const date = new Date(Date.UTC(2020, 11, 20, 13, 05, 00, 738));
console.log(
  new Intl.DateTimeFormat("en-GB", {
    dateStyle: "full",
    timeStyle: "long",
    timeZone: "Australia/Sydney",
    hourCycle: 'h23'
  }).format(date),
);

"Monday 21 December 2020 at 00:05:00 GMT+11"

@AndyChiang888
Copy link
Copy Markdown
Contributor Author

Found another bug. You must process the timeZone zonename and replace all spaces for _ so the function completes. It can't handle spaces in names, e.g.

	'Africa/Dar es Salaam': 'EAT-3',
...
	'Africa/El Aaiun': 'XXX-2<+01>-1,0/0,J365/23',
...
	'Africa/Sao Tome': 'GMT0',
...

etc

fixed in d9a087e

I thought of a situation where if someone's current zonename happens to contain spaces, it will crash after the upgrade. Should this problem be handled at the js level? . . .

@systemcrash
Copy link
Copy Markdown
Contributor

ofc ?.replaceAll(' ', '_'). Especially if this is to be backported.

@AndyChiang888
Copy link
Copy Markdown
Contributor Author

In fact, f36f014 and d9a087e can be reverted. I can just handle it in js.
In this way, the existing UCI settings do not need to be changed, and the GUI aesthetic will not be affected.

@systemcrash
Copy link
Copy Markdown
Contributor

I can just handle it in js. In this way, the existing UCI settings do not need to be changed, and the GUI aesthetic will not be affected.

The timezones are supposed to have underscore. The system page could replace the underscore in the displayed entries, but that's just an aesthetic. That's for later.

Comment thread modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js Outdated
@AndyChiang888
Copy link
Copy Markdown
Contributor Author

GUI aesthetics are also handled...

Comment thread modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js Outdated
Comment thread modules/luci-mod-system/htdocs/luci-static/resources/view/system/system.js Outdated
@systemcrash
Copy link
Copy Markdown
Contributor

Looks good now. Please squash your commits to one per file.

use localized time

Signed-off-by: Andy Chiang <AndyChiang_git@outlook.com>
use localized time

Signed-off-by: Andy Chiang <AndyChiang_git@outlook.com>
use localized time

Signed-off-by: Andy Chiang <AndyChiang_git@outlook.com>
set an appropriate width for #localtime

Signed-off-by: Andy Chiang <AndyChiang_git@outlook.com>
@AndyChiang888
Copy link
Copy Markdown
Contributor Author

Now there are 4 commits.

@systemcrash systemcrash merged commit 91a94ce into openwrt:master Oct 20, 2025
5 checks passed
@systemcrash
Copy link
Copy Markdown
Contributor

Excellent work. Thanks @AndyChiang888

@AndyChiang888 AndyChiang888 deleted the localized-time branch October 20, 2025 18:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants