2 回答

TA貢獻(xiàn)1810條經(jīng)驗(yàn) 獲得超4個(gè)贊
該Date對(duì)象,盡管它的名字,并不代表一個(gè)“日期”。它代表一個(gè)時(shí)間戳。它在內(nèi)部存儲(chǔ)的所有內(nèi)容都是自 Unix 紀(jì)元(基于 UTC)以來的毫秒數(shù)。它根據(jù)正在調(diào)用的函數(shù),根據(jù) UTC 或運(yùn)行機(jī)器的本地時(shí)區(qū)輸出值。
因此,如果您Date從僅限日期的值構(gòu)造對(duì)象,那么您實(shí)際上是從該時(shí)區(qū)獲取“午夜時(shí)間”并將其調(diào)整為 UTC。2002-01-01您的in示例證明了這一點(diǎn)Europe/Berlin。您將其視為2002-01-01T00:00:00.000+01:00,它確實(shí)具有相當(dāng)于 的 UTC 2001-12-31T23:00:00.000Z,因此不包含與預(yù)期時(shí)區(qū)相同的年、月和日元素。
如果你想防止它們移動(dòng),你真的只有兩個(gè)選項(xiàng)來處理僅限日期的值:
您的第一個(gè)選擇是使用該Date對(duì)象,但將輸入視為 UTC 并且僅使用基于 UTC 的函數(shù)。例如:
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"
如果您需要解析日期字符串,請(qǐng)注意當(dāng)前的ECMAScript 規(guī)范將僅限日期的值視為 UTC(這正是您想要的),但在過去這種行為是未定義的。因此,某些瀏覽器可能會(huì)從
new Date('2002-01-01')
.?Z
為了new Date('2002-01-01' + 'T00:00:00.000Z')
安全起見,您可能希望明確添加時(shí)間和。如果您打算使用 date-fns,請(qǐng)小心 -
parseISO
和formatISO
函數(shù)使用本地時(shí)間,而不是 UTC。
第二種選擇是不使用該
Date
對(duì)象。將日期保存為字符串形式(采用 ISO 8601 yyyy-mm-dd 格式),或者將它們保存在您自己構(gòu)造的或來自庫(kù)的不同對(duì)象中。
ECMAScript TC39?Temporal 提案旨在修復(fù) JavaScript 中的此類缺陷。特別是,該Temporal.Date
對(duì)象(初步名稱)將能夠用于僅限日期的值,而不會(huì)出現(xiàn)您和許多其他人遇到的轉(zhuǎn)移問題。該提案目前處于 ECMAScript 進(jìn)程的第 2 階段,因此今天無法使用,但這個(gè)問題最終會(huì)得到解決!

TA貢獻(xiàn)1883條經(jīng)驗(yàn) 獲得超3個(gè)贊
使用 ISO_8601 日期嘗試此功能,然后更改計(jì)算機(jī)設(shè)置中的時(shí)區(qū)并使用新時(shí)區(qū)重試。它應(yīng)該在您的網(wǎng)頁(yè)上為兩個(gè)時(shí)區(qū)打印相同的日期。
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;
}
添加回答
舉報(bào)