Please check the following before submitting a new issue.
hexo version to check)The issue has been reported in
For example, I have a post setup as following:
# _config.yml
timezone: Asia/Shanghai
title: Hello World
date: 2020-09-29 23:00:00
Also, my machine is under the Asia/Shanghai timezone, which will also affect Node.js' timezone.
After the front-matter being processed by js-yaml, the "Date-like string" will be converted into Date object:
const jsYaml = require("js-yaml");
jsYaml.load('date: 2020-09-29 23:00:00');
// > "Tue, 29 Sep 2020 23:00:00 GMT"
Notice that the input was converted into the UTC? Users will only fill in the front-matter with their local time, not the UTC. Thus it is not the desired behavior.
So during the processing of front-matter, Date#getTimezoneOffset has been used:
// https://github.com/hexojs/hexo-front-matter/blob/ccbdff36d151a56932418cdc6d0329d866032a1b/lib/front_matter.js#L55-L62
// Convert timezone
Object.keys(data).forEach(key => {
const item = data[key];
if (item instanceof Date) {
data[key] = new Date(item.getTime() + (item.getTimezoneOffset() * 60 * 1000));
}
});
It will result in:
"Tue, 29 Sep 2020 15:00:00 GMT"
Which is the desired behavior.
Then, during the processing pf posts, moment.timezone was used:
https://github.com/hexojs/hexo/blob/557487a2f8ab0065bf94d5a9466c54034f1db17f/lib/plugins/processor/post.js#L80-L82
https://github.com/hexojs/hexo/blob/557487a2f8ab0065bf94d5a9466c54034f1db17f/lib/plugins/processor/common.js#L51-L60
If the config.timezone is configured correctly, there will be no differences between before and after timezone():
"Tue, 29 Sep 2020 15:00:00 GMT"
// There's no differences
A demo can be found here: https://runkit.com/sukkaw/5f732261a7aac8001a42bcc4
Date#getTimezoneOffset: -480
Date parsed by js-yaml: Tue, 29 Sep 2020 23:00:00 GMT
Date after calculating the timezone offset: Tue, 29 Sep 2020 15:00:00 GMT
Date after moment-timezone: Tue, 29 Sep 2020 15:00:00 GMT
Date after moment-timezone (without pre offset): Tue, 29 Sep 2020 15:00:00 GMT // Will be discussed later
So, what about a different timezone environment? For example, the CI environment. Its timezone will not be Asia/Shanghai.
So here is another demo: https://repl.it/repls/LividBewitchedControlflowgraph#index.js
Date#getTimezoneOffset: 0 // See? It is not -480 anymore, it is now 0
Date parsed by js-yaml: Tue, 29 Sep 2020 23:00:00 GMT
Date after calculating the timezone offset: Tue, 29 Sep 2020 23:00:00 GMT // It is now wrong
Date after moment-timezone: Tue, 29 Sep 2020 15:00:00 GMT // But it is still correct
Date after moment-timezone (without pre offset): Tue, 29 Sep 2020 15:00:00 GMT // Will be discussed later
As you can see, Date after calculating the timezone offset is now wrong, while Date after moment-timezone is still correct. That's because timezone() takes getTimezoneOffset into consideration.
So, what about removing "getTimezoneOffset" completely?
Here goes Date after moment-timezone (without pre offset). It is generated without using Date#getTimezoneOffset, and the result is still correct. It also means it is not affected by the environment (no `Date#getTimezoneOffset being used).
By eliminating the Node.js timezone affection (only dependents on users' config.timezone configuration) the timezone issue should be solved.
cc @YoshinoriN @ItsZero @stevenjoezhang @curbengh
So far I just assume those issues were caused by their machines' timezones are inconsistent with their hexo configurations.
So, what about removing "getTimezoneOffset" completely?
+1, Hexo shouldn't need to query the host machine's timezone, config.timezone should be the canonical timezone.
There is still a need to query host's timezone since config.timezone is empty by default. Host's timezone should be ignored if config.timezone is specified.
Another complication is that it is also possible to specify timezone in front-matter, e.g. 2013-02-08 09:30:26.123+07:00.
Perhaps we can prioritise like this:
There is still a need to query the host's timezone
@curbengh
It appears that there is no way we could get the timezone name directly (If so, we could use it as a default value during hexo config processing). The only thing we get is getTimezoneOffset.
@curbengh
We can use JavaScript built-in object Intl:
Intl.DateTimeFormat().resolvedOptions().timeZone
// UTC
// Asia/Tokyo
// etc.
We can use it for the default timezone in config.
Most helpful comment
cc @YoshinoriN @ItsZero @stevenjoezhang @curbengh
So far I just assume those issues were caused by their machines' timezones are inconsistent with their hexo configurations.