2 回答
TA贡献1810条经验 获得超4个赞
该Date对象,尽管它的名字,并不代表一个“日期”。它代表一个时间戳。它在内部存储的所有内容都是自 Unix 纪元(基于 UTC)以来的毫秒数。它根据正在调用的函数,根据 UTC 或运行机器的本地时区输出值。
因此,如果您Date从仅限日期的值构造对象,那么您实际上是从该时区获取“午夜时间”并将其调整为 UTC。2002-01-01您的in示例证明了这一点Europe/Berlin。您将其视为2002-01-01T00:00:00.000+01:00,它确实具有相当于 的 UTC 2001-12-31T23:00:00.000Z,因此不包含与预期时区相同的年、月和日元素。
如果你想防止它们移动,你真的只有两个选项来处理仅限日期的值:
您的第一个选择是使用该Date对象,但将输入视为 UTC 并且仅使用基于 UTC 的函数。例如:
var dt = new Date(Date.UTC(2002, 0, 1)); // "2002-01-01T00:00:00.000Z"
var y = dt.getUTCFullYear(); // 2002
var m = dt.getUTCMonth() + 1; // 1
var d = dt.getUTCDate(); // 1
var dtString = d.toISOString().substring(0, 10) // "2002-01-01"
如果您需要解析日期字符串,请注意当前的ECMAScript 规范将仅限日期的值视为 UTC(这正是您想要的),但在过去这种行为是未定义的。因此,某些浏览器可能会从
new Date('2002-01-01')
.Z
为了new Date('2002-01-01' + 'T00:00:00.000Z')
安全起见,您可能希望明确添加时间和。如果您打算使用 date-fns,请小心 -
parseISO
和formatISO
函数使用本地时间,而不是 UTC。
第二种选择是不使用该
Date
对象。将日期保存为字符串形式(采用 ISO 8601 yyyy-mm-dd 格式),或者将它们保存在您自己构造的或来自库的不同对象中。
ECMAScript TC39 Temporal 提案旨在修复 JavaScript 中的此类缺陷。特别是,该Temporal.Date
对象(初步名称)将能够用于仅限日期的值,而不会出现您和许多其他人遇到的转移问题。该提案目前处于 ECMAScript 进程的第 2 阶段,因此今天无法使用,但这个问题最终会得到解决!
TA贡献1883条经验 获得超3个赞
使用 ISO_8601 日期尝试此功能,然后更改计算机设置中的时区并使用新时区重试。它应该在您的网页上为两个时区打印相同的日期。
getDateFromISO(iso_string: string): string | Date {
if (!iso_string)
return null;
const isIsoDate = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/.test(iso_string); // check if string is in format 2022-01-01T00:00:00.000Z
const isDateTimeWithoutZone = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(iso_string); // check if string is in format 2022-01-01T00:00:00
const isDateYMD = /\d{4}-\d{2}-\d{2}/.test(iso_string); // check if string is in format 2022-01-01
if (!isIsoDate && isDateTimeWithoutZone)
iso_string += '.000Z';
else if (!isIsoDate && isDateYMD)
iso_string += 'T00:00:00.000Z';
else if (isIsoDate)
iso_string = iso_string;
else
return iso_string;
const dateFromServer = new Date(iso_string);
const localOffset = new Date().getTimezoneOffset(); // in minutes
const localOffsetMillis = 60 * 1000 * localOffset;
const localDate = new Date(dateFromServer.getTime() + localOffsetMillis);
return localDate;
}
添加回答
举报