hexojs / hexo

A fast, simple & powerful blog framework, powered by Node.js.
https://hexo.io
MIT License
38.83k stars 4.76k forks source link

permalink date is incorrect if the time zone of _config.yml and the time zone setting of the machine are different #3282

Open MatchaChoco010 opened 5 years ago

MatchaChoco010 commented 5 years ago

Environment Info

Node version(node -v):v10.9.0

site to reproduce the ploblem:

https://github.com/MatchaChoco010/hexo-timezone-permalink

$ hexo version
hexo: 3.7.1
hexo-cli: 1.1.0
os: Linux 4.4.0-17134-Microsoft linux x64
http_parser: 2.8.0
node: 10.9.0
v8: 6.8.275.24-node.14
uv: 1.22.0
zlib: 1.2.11
ares: 1.14.0
modules: 64
nghttp2: 1.32.0
napi: 3
openssl: 1.1.0i
icu: 62.1
unicode: 11.0
cldr: 33.1
tz: 2018e

For BUG

_config.yml is this:

...
timezone: America/New_York
...
permalink: :year/:month/:day/:title/
...

and source/_posts/test.md is this:

---
title: test
date: 2018-10-11 23:00:00
tags:
---

The permalink of this article should be /2018/10/11/test/. But hexo generate in Japan, which +0900, /2018/10/12/test/index.html is generated.

screenshot0

The article date is correct (2018/10/11).

screenshot1

Change the machine timezone to -0500 and hexo generate, /2018/10/11/test.index.html is generated.

It seems that the permalink is not generated correctly if the time zone of _config.yml and the time zone setting of the machine are incorrect.

yoshinorin commented 5 years ago

@MatchaChoco010 Thanks a report. I reproduced it. But, I can't judge fix this behavior or not. I think this problem impact is big.

I ask to other hexo maintainer this problem.

yoshinorin commented 5 years ago

@tommy351 @NoahDragon @JLHwung How do you think about this.

itszero commented 5 years ago

I spent some time digging into this today and found out where the bug is. Unfortunately removing timezone from _config.yml is not a valid workaround me because I run the build on a cloud server just prior to deploy which is running in UTC timezone.

Why the timezone is off?

In plugins/filter/post_permalink.js we can see how the path is constructed. It reads from data.date which is prepared by the hexo database layer. If you print the value, you will see that while the timestamp is correct, its timezone is off -- It's just UTC.

Why is the timezone specified in _config.yml not applied?

Next, I dig into why the timezone specified in the config file was not applied. The timezone is being used in models/types/moment.js in the cast function: It reads options.timezone where it is defined in models/post.js by reading [ctx.config.timezone](https://github.com/hexojs/hexo/blob/master/lib/models/post.js#L25).

Why the config appeared as the default config?

Now if you print out ctx.config, you will see that it is NOT your personal config. Instead, it's the default config comes with hexo. Digging into how hexo initialize hexo/index.js, we see that [registerModels](https://github.com/hexojs/hexo/blob/master/lib/hexo/index.js#L100) happened before [load_config](https://github.com/hexojs/hexo/blob/master/lib/hexo/index.js#L169). That's why!

Now, how to fix this?

This is where I'm not sure what's the best way to proceed. I think the current logic is wrong. We obviously are using config before it is loaded. We have a few options here:

  1. Move the initialization until after we load the config (aka here): This makes the most sense to me, however, it breaks tests because some of them don't call hexo.init() before using hexo stuff. I'm not sure how big the assumptions were. hexo.init() is also, unfortunately, an async function so we can't just simply call it in those callsites too.
  2. Make load_config synchronous and load it before init: It's a safer way to fix this as it maintains the API interface. However, now we will be reading config file before init() is being called which might break some other cases as well. It also makes the init function useless.

I'm happy to code this up and send a PR, but I would like to discuss which approach would be more preferable?

Thanks!

tobyqin commented 4 years ago

still have someone try to fix this?

SukkaW commented 4 years ago

@tobyqin So far, it is still remain as a known issue.

tobyqin commented 4 years ago

@SukkaW thanks, I workaround it by removing the timezone info in config file and build environment.