在当地,一切都是精确到分钟的。一旦部署到Heroku,时间之间的差异大约为6小时。我不希望转换Heroku时区(希望它保持UTC)。我已经尝试了从getTimezoneOffset()转换到不同日期格式的所有方法,我仍然最终得到相同的结果。我怎样才能使这两个日期时间相互匹配,而不是由部署时的小时抵消?为什么它们的格式完全相同,但却不同?
// Used to calculate current date time
const currentDate = new Date();
// ^ Production - (2021-10-12T19:12:41.081Z)
const time = `${currentDate.getHours()}:${currentDate.getMinutes()}`;
const fullDate = `${currentDate.getMonth()}/${currentDate.getDate()}/${currentDate.getFullYear()}`;
const currentDateFormatted = new Date(`${fullDate} ${time}`);
// ^ Production - (2021-10-12T19:12:00.000Z)
const currentParsedDateToUTC = Date.parse(currentDateFormatted.toUTCString());
// Used to calculate an event date time
const eventDate = new Date(`${event.date} ${event.endTime}`); // same exact format as above
// ^ Production - (2021-10-12T13:12:00.000Z)
const eventParsedDateToUTC = Date.parse(eventDate.toUTCString());
const isExpired = (currentParsedDateToUTC > eventParsedDateToUTC); // works locally, but not in production
在本例中,事件日期和开始时间与当前日期时间相同。我怎样才能防止它们变得截然不同呢?
这是因为Heroku服务器与您的时区不同,您可以通过从前端转换时间格式来处理它,我建议您使用moment.js例如在您的前端中,您可以像这样转换:
npm install moment --save
,然后您可以创建一个函数来改变格式显示:
const formatDatetime = (
datetime = "N/A",
format = 'LLL' // here is your format
) => {
return moment(datetime).isValid()
? moment(datetime).format(format)
: datetime;
};
所以——Heroku返回正确的UTC本地时间,在撰写本文时,它是2021-10-12T19:36:00.000Z
。
你要求Heroku将2012-10-12 13:12
解释为日期,但你没有指定它应该使用哪个时区,所以它默认使用自己的UTC本地时间。
一切正常
我认为你含蓄地要求的是,你希望它把13:12解释为你的当地时间。但是,Heroku无法知道您的本地时间,因此您需要跟踪数据库中事件的时区。
这个在本地工作的唯一原因是你的本地服务器碰巧和你在同一个时区——如果我从我的时区连接到你的本地服务器,我也会遇到同样的问题。
前四行代码似乎试图创建一个Date并将秒数和毫秒数设置为零。可以这样做:
let d = new Date();
d.setSeconds(0,0);
将秒和毫秒设置为零。
我不知道你是怎么想的:
const currentParsedDateToUTC = Date.parse(currentDateFormatted.toUTCString());
,但同样的结果是:
d.getTime();
实际上是前面调用setSeconds时返回的值。所以前5行代码减少为:
let currentParsedDateToUTC = new Date().setSeconds(0,0);
然后在:
const eventDate = new Date(`${event.date} ${event.endTime}`);
使用内置解析器解析格式为d/m/y H:m的时间戳,这是一个坏主意,请参阅为什么要使用Date。解析给出不正确的结果?。你可以使用一个库来代替,或者只写一个两行的函数来完成这项工作。
还有:
const eventParsedDateToUTC = Date.parse(eventDate.toUTCString());
就是:
const eventParsedDateToUTC = eventDate.getTime();
最后是:
const isExpired = (currentParsedDateToUTC > eventParsedDateToUTC);
比较运算符将为您强制日期为数字,因此您可以将值保留为日期。
完成这项工作的函数是:
// eventDate is UTC timestamp in m/d/y H:m format
function isExpired(eventDate) {
// Parse eventDate as UTC
let [M,D,Y,H,m] = eventDate.split(/W/);
let eventD = new Date(Date.UTC(Y, M-1, D, H, m));
// return true if has passed (minute precision)
return eventD < new Date().setSeconds(0,0);
}
// Event dates (UTC)
['10/12/2021 12:00', // 12 Oct 2021 12:00
'10/13/2021 12:00', // 13 Oct 2021 12:00
'10/13/2022 12:00', // 13 Oct 2022 12:00
].forEach(d =>
console.log(d + ' has' + (isExpired(d)? '':' not') + ' Expired')
);
您可以使用Date.UTC(Y, M-1, D, H, m)
返回的值而不转换为Date,因此最后两行可以是:
return Date.UTC(Y, M-1, D, H, m) < new Date().setSeconds(0,0);
但是使用Date更符合语义(如果不必要的话)。: -)