好的,似乎无法避免这种行为,因此您应该手动解析日期。但是解析它的方法很简单。
如果我们以 ISO 8601 格式解析日期,日期字符串的掩码如下所示:
<yyyy>-<mm>-<dd>T<hh>:<mm>:<ss>(.<ms>)?(Z|(+|-)<hh>:<mm>)?
1。分别获取日期和时间
字符串中的T 将日期与时间分开。所以,我们可以用T分割ISO字符串
var isoString = `2019-05-09T13:26:10.979Z`
var [dateString, timeString] = isoString.split("T")
2。从日期字符串中提取日期参数
所以,我们有dateString == "2019-05-09"。现在单独获取这些参数非常简单
var [year, month, date] = dateString.split("-").map(Number)
3。处理时间字符串
对于时间字符串,由于其可变性,我们应该执行更复杂的操作。
我们有timeString == "13:26:10Z"
也可以timeString == "13:26:10" 和timeString == "13:26:10+01:00
var clearTimeString = timeString.split(/[Z+-]/)[0]
var [hours, minutes, seconds] = clearTimeString.split(":").map(Number)
var offset = 0 // we will store offset in minutes, but in negation of native JS Date getTimezoneOffset
if (timeString.includes("Z")) {
// then clearTimeString references the UTC time
offset = new Date().getTimezoneOffset() * -1
} else {
var clearOffset = timeString.split(/[+-]/)[1]
if (clearOffset) {
// then we have offset tail
var negation = timeString.includes("+") ? 1 : -1 // detecting is offset positive or negative
var [offsetHours, offsetMinutes] = clearOffset.split(":").map(Number)
offset = (offsetMinutes + offsetHours * 60) * negation
} // otherwise we do nothing because there is no offset marker
}
此时,我们的数据以数字格式表示:
year、month、date、hours、minutes、seconds 和 offset 以分钟为单位。
4。使用 ...native JS Date 构造函数
是的,我们无法避免它,因为它太酷了。 JS Date 自动匹配所有负值和太大值的日期。所以我们可以只传递原始格式的所有参数,JS Date 构造函数会自动为我们创建正确的日期!
new Date(year, month - 1, date, hours, minutes + offset, seconds)
瞧!这是完整的工作示例。
function convertHistoricalDate(isoString) {
var [dateString, timeString] = isoString.split("T")
var [year, month, date] = dateString.split("-").map(Number)
var clearTimeString = timeString.split(/[Z+-]/)[0]
var [hours, minutes, seconds] = clearTimeString.split(":").map(Number)
var offset = 0 // we will store offset in minutes, but in negation of native JS Date getTimezoneOffset
if (timeString.includes("Z")) {
// then clearTimeString references the UTC time
offset = new Date().getTimezoneOffset() * -1
} else {
var clearOffset = timeString.split(/[+-]/)[1]
if (clearOffset) {
// then we have offset tail
var negation = timeString.includes("+") ? 1 : -1 // detecting is offset positive or negative
var [offsetHours, offsetMinutes] = clearOffset.split(":").map(Number)
offset = (offsetMinutes + offsetHours * 60) * negation
} // otherwise we do nothing because there is no offset marker
}
return new Date(year, month - 1, date, hours, minutes + offset, seconds)
}
var testDate1 = convertHistoricalDate("1894-01-01T00:00:00+01:00")
var testDate2 = convertHistoricalDate("1893-01-01T00:00:00+01:00")
var testDate3 = convertHistoricalDate("1894-01-01T00:00:00-01:00")
var testDate4 = convertHistoricalDate("1893-01-01T00:00:00-01:00")
console.log(testDate1.toLocaleDateString(), testDate1.toLocaleTimeString())
console.log(testDate2.toLocaleDateString(), testDate2.toLocaleTimeString())
console.log(testDate3.toLocaleDateString(), testDate3.toLocaleTimeString())
console.log(testDate4.toLocaleDateString(), testDate4.toLocaleTimeString())
注意
在这种情况下,我们将获得 Date 实例,其所有自己的值(如 .getHours())都被规范化,包括时区偏移。 testDate1.toISOString 仍然会返回奇怪的结果。但是,如果您使用这个日期,它可能会 100% 满足您的需求。
希望有所帮助:)