hexojs / hexojs/hexo

Date & Timezone issue related with Front-Matter

Open
#4,548 9 comments 5 reactions 0 assignees Claimed by @stevenjoezhang View on GitHub
dates discussion
Dominant language
TypeScript
Stars
41.8k
Forks
41
PR merge metrics
No merged PRs in 30d

Description

## Check List

Please check the following before submitting a new issue.

- [x] I have already read [Docs page](https://hexo.io/docs/) & [Troubleshooting page](https://hexo.io/docs/troubleshooting)
- [x] I have already searched existing issues and they are not helpful to me
- [x] I examined error or warning messages and it's difficult to solve
- [x] Using [the latest](https://github.com/hexojs/hexo/releases) version of Hexo (run `hexo version` to check)
- [x] Node.js is higher than [minimum required version](https://hexo.io/docs/#Minimum-required-Node-js-version)

The issue has been reported in

- #4239
- #3397
- #3282
- #2063

-----

For example, I have a post setup as following:

```yaml
# _config.yml
timezone: Asia/Shanghai
```

```yaml
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:

```js
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:

```js
// 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.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.