DIYgod / RSSHub

🧡 Everything is RSSible
https://docs.rsshub.app
MIT License
30.82k stars 6.88k forks source link

pubDate 时间错误 #6795

Open ngamc opened 3 years ago

ngamc commented 3 years ago

路由地址(不包含参数)

/ifnews/:cid

完整路由地址,包含所有必选与可选参数

https://rsshub.app/ifnews/40

相关文档地址

预期是什么

时间 应该是正确的

实际发生了什么

时间 错误,显示的时间实际是明天 例如:现在时间是北京时间 2021/1/26 16:21 RSS 内有: lastBuildDate:Tue, 26 Jan 2021 07:30:43 GMT pubDate:Tue, 26 Jan 2021 23:07:00 GMT

其中,pubDate明显不对,猜测是时间GMT+8 和 GMT-8弄反了,所以 23:07:00实际应该是7:07:00

除了这个路由外,其他很多路由都出现类似问题,例如: /21caijing/channel/:name /bjnews/:category /yicai/brief

部署相关信息

Env Value
OS
Node version
if Docker, version
github-actions[bot] commented 3 years ago

👍 感谢提交该 Issue,请确保仔细阅读 Issue 模板RSS 提案模板Feature 提案模板 以便于测试。不符合模板将导致 Issue 被直接关闭。

👍 Thanks for the issue, please follow the Issue template, RSS proposal template or Feature proposal template. Otherwise the issue will be closed.

NeverBehave commented 3 years ago

请提供部署环境信息 demo的话,服务器时区默认也不是Shanghai,默认应该使用了北美地区 噢意识到了,这个问题可能需要规范路由写法以后才能解决,目前部分时间使用了自己处理的方式,没有遵守统一的格式处理

ngamc commented 3 years ago

~请提供部署环境信息~ ~demo的话,服务器时区默认也不是Shanghai,默认应该使用了北美地区~ 噢意识到了,这个问题可能需要规范路由写法以后才能解决,目前部分时间使用了自己处理的方式,没有遵守统一的格式处理

奇怪之前没有这个问题,是最近几个路由都同时发生问题

NeverBehave commented 3 years ago

~请提供部署环境信息~ ~demo的话,服务器时区默认也不是Shanghai,默认应该使用了北美地区~ 噢意识到了,这个问题可能需要规范路由写法以后才能解决,目前部分时间使用了自己处理的方式,没有遵守统一的格式处理

奇怪之前没有这个问题,是最近几个路由都同时发生问题

服务换了,时区也变了

但是无论怎么样这个问题都不应该是这样的emmm

zhufree commented 3 years ago

我也遇到了这个问题,请求微博超话数据的时候,所有的发布时间日期都设置成了当天,只有时间是对的,例如显示今天Feb 22 13:55的微博实际上是1.18日13:55发的微博。 看了下代码 pubDate: date(mblog.created_at, 8), 感觉应该是date = require('@/utils/date')这个工具库里面有点问题,但是不擅长前端所以不是很清楚

NeverBehave commented 3 years ago

7181 这里是什么问题?

是不是相关util没有包含文档,我看了一下确实似乎是没有 @queensferryme

zhufree commented 3 years ago

我了解的情况就在上面评论里了,超话这个路由的问题应该不是时区问题,猜测是date这个工具类处理原始字符串的时候没有匹配上,导致丢失了日期,把所有日期设置成了当天。 https://rsshub.app/weibo/super_index/1008084989d223732bf6f02f75ea30efad58a9 访问这个链接的第一条微博日期是<pubDate>Sat, 13 Mar 2021 15:37:00 GMT</pubDate>,而打开链接可以看到发布日期是2月15日 23:37 ,只有37分这个是对的,23时是因为时区,而日期就是完全不对。 因此我在我提交的代码里把这个date方法去掉了,也没有+8,自己处理了这个时区

NeverBehave commented 3 years ago

我了解的情况就在上面评论里了,超话这个路由的问题应该不是时区问题,猜测是date这个工具类处理原始字符串的时候没有匹配上,导致丢失了日期,把所有日期设置成了当天。 https://rsshub.app/weibo/super_index/1008084989d223732bf6f02f75ea30efad58a9 访问这个链接的第一条微博日期是<pubDate>Sat, 13 Mar 2021 15:37:00 GMT</pubDate>,而打开链接可以看到发布日期是2月15日 23:37 ,只有37分这个是对的,23时是因为时区,而日期就是完全不对。 因此我在我提交的代码里把这个date方法去掉了,也没有+8,自己处理了这个时区

问题是大部分自己处理的情况是不正确的,会受到服务器时区,访问方式变化等影响。这也是为什么我们引入了这个工具集。所有的pubDate应该通过这个方式标识获取的时间以及处理方式。 这个部分文档是缺失的,我也没有时间去处理,所以在让目前正在处理的贡献者提供建议

zhufree commented 3 years ago

我了解的情况就在上面评论里了,超话这个路由的问题应该不是时区问题,猜测是date这个工具类处理原始字符串的时候没有匹配上,导致丢失了日期,把所有日期设置成了当天。 https://rsshub.app/weibo/super_index/1008084989d223732bf6f02f75ea30efad58a9 访问这个链接的第一条微博日期是<pubDate>Sat, 13 Mar 2021 15:37:00 GMT</pubDate>,而打开链接可以看到发布日期是2月15日 23:37 ,只有37分这个是对的,23时是因为时区,而日期就是完全不对。 因此我在我提交的代码里把这个date方法去掉了,也没有+8,自己处理了这个时区

问题是大部分自己处理的情况是不正确的,会受到服务器时区,访问方式变化等影响。这也是为什么我们引入了这个工具集。所有的pubDate应该通过这个方式标识获取的时间以及处理方式。 这个部分文档是缺失的,我也没有时间去处理,所以在让目前正在处理的贡献者提供建议

ok,我试试转换成标准时间格式再用date处理看看。

queensferryme commented 3 years ago

因此我在我提交的代码里把这个date方法去掉了,也没有+8,自己处理了这个时区

我认为不应该这样做,因为有很多用户自建 RSSHub,而不是所有服务器都在 +8 时区,所以我们引入了 @/utils/date 这个工具。

https://rsshub.app/weibo/super_index/1008084989d223732bf6f02f75ea30efad58a9 访问这个链接的第一条微博日期是Sat, 13 Mar 2021 15:37:00 GMT,而打开链接可以看到发布日期是2月15日 23:37 ,只有37分这个是对的,23时是因为时区,而日期就是完全不对。

我测试了一下,复现了你提到的这个日期错误但时间正确的问题,但我发现问题不止这些。我的测试方法是在 lib/routes/weibo/super_index.js 加入以下几行:

console.log("mblog.created_at           = ", mblog.created_at)
console.log("new Date(mblog.created_at) = ", new Date(mblog.created_at).toUTCString())
console.log("date(mblog.created_at, 8)  = ", date(mblog.created_at, 8))
console.log()

然后访问上述路由,输出以下日志:

info: /weibo/super_index/1008084989d223732bf6f02f75ea30efad58a9, user IP: ::ffff:127.0.0.1
mblog.created_at           =  Sat Mar 20 20:39:33 +0800 2021
new Date(mblog.created_at) =  Sat, 20 Mar 2021 12:39:33 GMT
date(mblog.created_at, 8)  =  Sat, 20 Mar 2021 12:39:00 GMT

mblog.created_at           =  Sat Mar 20 19:39:33 +0800 2021
new Date(mblog.created_at) =  Sat, 20 Mar 2021 11:39:33 GMT
date(mblog.created_at, 8)  =  Sat, 20 Mar 2021 11:39:00 GMT

mblog.created_at           =  Sat Mar 20 09:01:04 +0800 2021
new Date(mblog.created_at) =  Sat, 20 Mar 2021 01:01:04 GMT
date(mblog.created_at, 8)  =  Sat, 20 Mar 2021 01:01:00 GMT

mblog.created_at           =  Sat Mar 20 18:19:39 +0800 2021
new Date(mblog.created_at) =  Sat, 20 Mar 2021 10:19:39 GMT
date(mblog.created_at, 8)  =  Sat, 20 Mar 2021 10:19:00 GMT

mblog.created_at           =  Mon Mar 11 07:10:25 +0800 2019
new Date(mblog.created_at) =  Sun, 10 Mar 2019 23:10:25 GMT
date(mblog.created_at, 8)  =  Fri, 19 Mar 2021 23:10:00 GMT

mblog.created_at           =  Fri Mar 19 21:32:45 +0800 2021
new Date(mblog.created_at) =  Fri, 19 Mar 2021 13:32:45 GMT
date(mblog.created_at, 8)  =  Sat, 20 Mar 2021 13:32:00 GMT

mblog.created_at           =  Sat Mar 20 06:45:56 +0800 2021
new Date(mblog.created_at) =  Fri, 19 Mar 2021 22:45:56 GMT
date(mblog.created_at, 8)  =  Fri, 19 Mar 2021 22:45:00 GMT

mblog.created_at           =  Sat Mar 20 06:52:13 +0800 2021
new Date(mblog.created_at) =  Fri, 19 Mar 2021 22:52:13 GMT
date(mblog.created_at, 8)  =  Fri, 19 Mar 2021 22:52:00 GMT

mblog.created_at           =  Fri Mar 19 11:54:57 +0800 2021
new Date(mblog.created_at) =  Fri, 19 Mar 2021 03:54:57 GMT
date(mblog.created_at, 8)  =  Sat, 20 Mar 2021 03:54:00 GMT

以下两条微博(链接一链接二)出现了日期错误但时间正确的问题。这两条微博的 UTC 时间和 UTC+8 时间都在 19 号:

mblog.created_at           =  Fri Mar 19 21:32:45 +0800 2021
new Date(mblog.created_at) =  Fri, 19 Mar 2021 13:32:45 GMT
date(mblog.created_at, 8)  =  Sat, 20 Mar 2021 13:32:00 GMT

mblog.created_at           =  Fri Mar 19 11:54:57 +0800 2021
new Date(mblog.created_at) =  Fri, 19 Mar 2021 03:54:57 GMT
date(mblog.created_at, 8)  =  Sat, 20 Mar 2021 03:54:00 GMT

还有两条微博(链接一链接二)也值得注意。它们的 UTC+8 时间在 20 号(今天)但 UTC 时间在 19 号(昨天)。对于这样的微博,解析就没有出现问题。

mblog.created_at           =  Sat Mar 20 06:45:56 +0800 2021
new Date(mblog.created_at) =  Fri, 19 Mar 2021 22:45:56 GMT
date(mblog.created_at, 8)  =  Fri, 19 Mar 2021 22:45:00 GMT

mblog.created_at           =  Sat Mar 20 06:52:13 +0800 2021
new Date(mblog.created_at) =  Fri, 19 Mar 2021 22:52:13 GMT
date(mblog.created_at, 8)  =  Fri, 19 Mar 2021 22:52:00 GMT

还有一条微博干脆年份跑到 2019 年,解析出来的结果错得更加离谱:

mblog.created_at           =  Mon Mar 11 07:10:25 +0800 2019
new Date(mblog.created_at) =  Sun, 10 Mar 2019 23:10:25 GMT
date(mblog.created_at, 8)  =  Fri, 19 Mar 2021 23:10:00 GMT

我的初步猜测是问题出在 @/utils/date 中的一系列正则表达式那里,但还需要再研究研究。

这个部分文档是缺失的,我也没有时间去处理,所以在让目前正在处理的贡献者提供建议

@/utils/date 这个模块比较复杂,功能也不是很明确,似乎同时想干很多件事(尽管我本人只用来处理时区)。我认为 date.jsdateParser.js 都需要文档和一定程度的重构,和时间有关的问题似乎也一直反复出现,建议单独再开一个 issue 来讨论。

/cc @NeverBehave @zhufree

ryocoooool commented 3 years ago

在我使用的一些路由中也有部分出现了这个问题,例如:https://rsshub.app/thepaper/featured。 一开始我以为是阅读器的原因,在我询问之后得到了如下答复 WechatIMG4563 请问这样的问题该如何解决呢?

zhufree commented 3 years ago

在我使用的一些路由中也有部分出现了这个问题,例如:https://rsshub.app/thepaper/featured。 一开始我以为是阅读器的原因,在我询问之后得到了如下答复 WechatIMG4563 请问这样的问题该如何解决呢?

改代码修复这个问题。。。你可以自建改了自己用,或者提pr到这个官方库

NeverBehave commented 3 years ago

@queensferryme cc @DIYgod

可以的话直接改把,然后写一下文档。

我觉得我们可以接受一个dayjs object,或者是date object。这样我们可以拿到一个带时区的时间,然后再统一按照需求转换

再这个问题解决之前我们先暂缓新路由添加

DIYgod commented 3 years ago

utils/date 有处理时区的逻辑,第二个参数就是,我觉得问题出在文档缺失上 😥 有的源站总是返回+8时区的时间,有的源站会根据服务器时间返回,所以还是要靠路由来传这个参数 dateParser 这个模块看起来有点重复,可以跟 date 模块合成一个

NeverBehave commented 3 years ago

@queensferryme 这样子的话,因为我们大多数情况下还是要做一次string2object

两个参数的情况作为fallback保留 新增接受一个参数的使用方式,传入必须是dayjs或者date object然后接续处理

cc @SukkaW 看看有没有更好的处理方法

SukkaW commented 3 years ago

我想了一下,Hexo 里处理时区利用的是 timezone offset 方法获取服务器时区和 UTC 时区的差别。

moment 库里也有 offset 方法,而且可以计算和指定时区之间的 offset。具体的实现我还没有思路。

tuzi3040 commented 3 years ago

我认为不应该这样做,因为有很多用户自建 RSSHub,而不是所有服务器都在 +8 时区,所以我们引入了 @/utils/date 这个工具。

如果在路由内能写好时间时区处理逻辑到也无妨,因为有些路由的时间解析还是需要一些奇淫技巧的(笑),不可能全部都使用 @/utils/date

我的初步猜测是问题出在 @/utils/date 中的一系列正则表达式那里,但还需要再研究研究。

肯定是这个正则匹配到了里面的 /(\d+):(\d+)/ ,也就是 HH:mm ,然后其他参数(YYYY, MM, DD)都在按照当前时间解析。 这个把正则头尾加上 ^ $ -> /^(\d+):(\d+)$/ 就行了,匹配整串。

@/utils/date 这个模块比较复杂,功能也不是很明确,似乎同时想干很多件事(尽管我本人只用来处理时区)。我认为 date.jsdateParser.js 都需要文档和一定程度的重构,和时间有关的问题似乎也一直反复出现,建议单独再开一个 issue 来讨论。

要重构的话,索性全部用dayjs(或者moment,luxon什么的)重写一遍,部分正则规则还可以合并起来。

/cc @queensferryme

我觉得我们可以接受一个dayjs object,或者是date object。这样我们可以拿到一个带时区的时间,然后再统一按照需求转换

utils/date 有处理时区的逻辑,第二个参数就是,我觉得问题出在文档缺失上 😥 有的源站总是返回+8时区的时间,有的源站会根据服务器时间返回,所以还是要靠路由来传这个参数

感觉没必要换成 object,第一个参数还是 dateTime,第二个用可选的 customParseFormat,空值就过预置的正则那套,第三个用可选的 ianaTimezone 或者 timezoneOffset (e.g. +0800, -0630, +0000),默认为 localTimezone。最后第四个传 locale 做 localized day of week 和 month 的解析。 时区直接用 dayjs 内置的 timezone 或者 add 方法去调整。

/cc @NeverBehave @DIYgod @SukkaW

NeverBehave commented 3 years ago

@tuzi3040 现在主要问题是在于pubdate传入的部分可能太多,同时可能需要按照客户/服务器时区进行调整,需要规范一下 方法1,通过要求使用指定工具类 方法2,验证ctx pubdate是否符合规范,在届时统一处理 方法2的问题是如果采用object的方式,目前大部分缓存直接将object塞进去会是一个问题

SukkaW commented 3 years ago

@NeverBehave @tuzi3040

我们可以只指定时区名称,字符串总是可以被序列化、作为 cache key 的吧。

大概几个可能会用到的 Code Snippet:

// 获取当前 JS Runtime(即 RSSHub 服务端)当前时区,Node.js 8.10.0 起提供完整支持
Intl.DateTimeFormat().resolvedOptions().timeZone;
NeverBehave commented 3 years ago

@NeverBehave @tuzi3040

我们可以只指定时区名称,字符串总是可以被序列化、作为 cache key 的吧。

大概几个可能会用到的 Code Snippet:

// 获取当前 JS Runtime(即 RSSHub 服务端)当前时区,Node.js 8.10.0 起提供完整支持
Intl.DateTimeFormat().resolvedOptions().timeZone;

目前有看到dayjs直接序列化的操作,尚不清楚后果 其实主要是强制要求脚本规范pubDate时区,做法需要考虑到序列化/缓存问题

@SukkaW pubDate并不会作为key,目前默认的做法是请求链接作为key,处理后的ctx序列化后作为value,获取时重新转换

NeverBehave commented 3 years ago

由于部分路由需要继续追踪相关问题,重新开启 请后续pr不要带close标签,仅关联issue

queensferryme commented 3 years ago

目前以下路由仍在使用旧的时间处理模块,请有时间的贡献者考虑帮忙迁移到新的 timezone / parse-date 模块(文档)。

The following routes are still using the legacy modules for handling time, contributors could help migrate to the new timezone / parse-date modules(docs)。

Progress (grep -lnrw . -e "utils/date" --exclude-dir={node_modules,logs,docs,.git}):

queensferryme commented 3 years ago

And we should probably add unit tests for the new utils.

rockbenben commented 1 year ago

默认发布时间都是 GMT,Docker 部署如何默认 +8?

docker 中使用的时区是东八没用,官方文档看到转换代码,但能不能说下在 Docker 上如何设置转为东八?

const timezone = require('@/utils/timezone');
const pubDate = timezone(new Date(), +8)
NeverBehave commented 1 year ago

默认发布时间都是 GMT,Docker 部署如何默认 +8?

docker 中使用的时区是东八没用,官方文档看到转换代码,但能不能说下在 Docker 上如何设置转为东八?


const timezone = require('@/utils/timezone');

const pubDate = timezone(new Date(), +8)

这个控制是让脚本提供者声明获取来的时间是在什么时区,方便做偏移。如果作为用户,目前获取时间不受这个控制,也暂时没有参数可以控制输出格式

grock304 commented 1 year ago

财联社的都是错的呢: https://rsshub.app/cls/telegraph https://rsshub.app/cls/depth/1003 https://rsshub.app/cls/hot 财经新闻对时间很在意,希望能尽快修正,谢谢。

Cambamwam commented 5 months ago