八个关于 new Date() 的陷阱,你需要知道一下

2023年 7月 18日 64.6k 0

new Date() 构造函数是魔鬼 - 哦,我害怕它!这导致我在工作中犯了很多错误,其中一些非常奇怪。

我们必须非常小心地对待它,否则我们很容易陷入它的陷阱。

1. Safari浏览器不支持YYYY-MM-DD形式的格式化日期

你知道吗?“Safari”浏览器不支持“YYYY-MM-DD”形式的初始化时间。除它之外的很多浏览器,例如Chrome浏览器,都完美支持这种格式。

如果您编写这样的代码,您的应用程序将在“Safari”浏览器中收到无效日期错误。

new Date('2023-05-28') // Invalid Date

为了正确处理这个问题,我们需要以“YYYY/MM/DD”的形式初始化时间。

new Date('2023/05/28')

2.使用0作为月份的起始索引

我们应该如何初始化日期 2023 年 5 月 28 日?

const d = new Date(2023, 4, 28)


console.log(d.getMonth()) // 4

我们将 4 作为第二个参数传递给 Date,但为什么不传递 5?

啊! 我讨厌这个功能。处理月份时,日期以 0 开头,0 表示一月,1 表示二月,等等。这个函数很糟糕,非常混乱且有错误。

3.关于其自动日期校正的陷阱

很难猜测下面的代码代表的真实日期是什么。

也许是 2023 年 2 月的日期?但二月并没有32天,很奇怪,那么到底是什么呢?

const d = new Date(2023, 1, 32)

让我们编写一个解析日期对象的函数。

const parseDate = (date) => {
  const year = date.getFullYear()
  const month = date.getMonth() + 1 //Since the index of the month starts from 0, we need to add 1
  const day = date.getDate()


  return { year, month, day }
}


console.log(parseDate(new Date(2023, 1, 32)))
/*
{
  "year": 2023,
  "month": 3,
  "day": 4
}
*/

哦,新的日期(2023, 1, 32)是2023年3月4日,这太离谱了。

4. 无法轻松格式化日期?

如何将数组转换为指定格式的字符串?很简单,我们可以使用数组的join方法。

const array = [ '2023', '5', '28' ]


console.log(array.join('/')) // 2023/5/28
console.log(array.join('-')) // 2023-5-28
console.log(array.join(':')) // 2023:5:28

但是Date对象并没有提供直接方便的方式来格式化日期,所以我们必须自己编写代码来实现。

const formatDate = (date, format = '/') => {
  return date.getFullYear() + format + (date.getMonth() + 1) + format + date.getDate()
}


formatDate(new Date(2023, 4, 28), ':') // 2023:5:28
formatDate(new Date(2023, 4, 28), '/') // 2023/5/28
formatDate(new Date(2023, 4, 28), ':') // 2023-5-28

5. 无法确定日期对象是否有效

就像上面的例子一样,由于Date对象会自动固定日期,所以,我们无法判断一个日期是否真的有效。

const d = new Date(2023, 15, 1) // this is a date that does not exist


formatDate(d) // 2024/4/1

6. string类型的日期无法正确解析

很多时候我们会通过传递日期字符串来初始化日期,因为它比 new Date(2023, 4, 28) 使用起来方便得多。

const d1 = new Date('2023-5-28')


console.log(formatDate(d1)) // 2023/5/28

这里也有陷阱,我的朋友,我们必须小心。

const d2 = new Date('5-28-2023')


console.log(formatDate(d2)) // 2023/5/28

如果您传入这样的日期,您将收到无效错误警告。

const d3 = new Date('28-5-2023') // Invalid Date
const d4 = new Date('2023-28-5') // Invalid Date

7. 无法判断Date是否为闰年

哇,有时我们需要在工作中确定一年是否是闰年,这有点麻烦,因为 Date 对象也没有提供执行此操作的对象方法。

const isLeapYear = (date) => {
  const year = date.getFullYear()
  return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0
}


isLeapYear(new Date(2023, 4, 28)) // false
isLeapYear(new Date(2020, 4, 28)) // true

8. 新日期(xx, xx, xx) 是一年中的哪一周?

Date对象提供了获取年、月、日、小时、分钟等的函数。

我们如何确定日期是一年中的第几周?我们只能通过复杂的计算来完成这个目标。

const getWeekNumber = (date) => {
  // Creates a new Date object, set to a copy of the given date
  const newDate = new Date(date.getTime())
  // Set the time part of the date object to 0 so that only the date is considered
  newDate.setHours(0, 0, 0, 0)
  // Sets the date object to the first day of the year
  newDate.setDate(1)
  newDate.setMonth(0)
  // Gets the day of the week for the first day (0 for Sunday, 1 for Monday, etc.
  const firstDayOfWeek = newDate.getDay()
  // Calculates the difference in days from a given date to the start of the first week
  const diff = (date.getTime() - newDate.getTime()) / (24 * 60 * 60 * 1000)
  // Determines the start date of the first week according to the ISO 8601 standard
  let weekStart = 1 - firstDayOfWeek
  if (firstDayOfWeek > 4) {
    weekStart += 7 // If the first day is a Friday or later, move the first week back by one week
  }
  // Calculate week number (rounded down)
  const weekNumber = Math.floor((diff + weekStart) / 7) + 1
  return weekNumber
}


getWeekNumber(new Date(2023, 4, 28)) // 22

这是一种常见的计算,使用 ISO 8601 标准来计算日期是一年中的第几周。

但显然,它太复杂了,我无法理解这个功能。

写在最后

Date对象有很多奇怪的行为,我们可以使用一些强大的库来帮助我们。例如Moment.js、Day.js、date-fns等。

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论