但是并不是任何时候都需要引入这些库,如果你足够了解日期对象的话它其实很简单,在这篇文章中我将带你了解所有关于日期对象的信息。
首先,先从时区开始。
时区
世界上有几百个时区,但在 JavaScript 中,你只需要了解两个就行:当地时间和世界协调时(UTC)。
当地时间:指你的计算机所在的时区
世界协调时:是最主要的世界时间标准,是最接近格林威治标准时间(GMT),默认情况下,Date 对象创建的都是当地时间,只有在指定 UTC 时它才会创建世界协调时。
有了这个,就可以来谈论日期创建了。
创建日期
你可以通过 new Date()
来创建日期,它有四种使用方式:
- 日期字符串
- 日期参数
- 时间戳
- 无参数
1.日期字符串
给 new Date
传递一个日期字符串来创建
new Date('1988-03-21');
在创建日期时,我们倾向于这种日期字符串方法。因为这很自然符合我们的默认习惯。如果你写成 21-03-1988
,在 JavaScript 中它是无效的。
原因是因为:
在世界上不同的地方,对日期字符有不同的理解,例如: 11-06-2019
你可以认为是 11th June, 2019
你也可以认为是 6th November 2019
。如果不告诉你时间系统,根本无法得知到底该是哪个。
JavaScript 中,如果你想使用日期字符串,就必须使用一种全世界通用的格式,其中的一种格式就是 ISO 8601 Extended format
// ISO 8601 Extended format
`YYYY-MM-DDTHH:mm:ss:sssZ`
其中:
- YYYY:4 位数的年份
- MM:2 位数的月份(01-12)
- DD:2 位数的日期(0-31)
- -:日期分隔符
- T:指示时间的开始
- HH: 小时 (0 to 23)
- mm: 分钟 (0 to 59)
- ss: 秒数 (0 to 59)
- sss: 毫秒 (0 to 999)
- : :时间分隔符
- Z:时区,有 Z 采用 UTC 时区,没有则是当地时区(仅限有时间的情况)
注意:原文中的 DD:2 位数的日期(0-31)有误,经求证 DD 应为 (01 to 31)可查看Date Time String Format
其中,小时、分钟、秒和毫秒是可选的。因此,如果想创建一个日期 2019年6月11日,你可以这么做:
new Date('2019-06-11')
请注意,如果你用 console.log
打印出这个日期,会发现存在一个很大的问题。
如果此时你在 GMT 时区「之后」的地区,得到的是:6月10日。
如果此时你是在 GMT 时区「之前」的地区,你得到的是:6月11日。
出现这种现象的原因是:当使用日期字符串时它会有一个特殊的行为:如果创建一个不指定时间的日期,它会以 UTC(世界协调时) 为时区。
所以如果你想创建本地时间,你需要加上 HH
和 mm
。
new Date('2019-06-11T00:00')
通过上面能够看出使用日期字符串时,可能会因为本地时间和世界协调时出现何难捕捉的错误。
所以推荐你不要使用日期字符串来创建日期
顺便说一下,MDN 也警告不要使用日期字符串方法,因为浏览器可能会以不同的方式解析日期字符串。
如果要创建日期,请使用参数或时间戳。
2.参数
你最多可以传递 7 个参数来创建日期。
- Year: 4 为数年份
- Month: 月份 (0-11),默认值为 0
- Day:天(1-31),默认值为 1
- Hour:小时(0-23),默认值为 0
- Minutes:分钟 (0-59),默认值为 0
- Seconds:秒数(0-59),默认值为 0
- Milliseconds: 毫秒数 (0-999),默认值为 0
// 11th June 2019, 5:23:59am, Local Time
new Date(2019, 5, 11, 5, 23, 59)
因为它看起来复杂,导致很多开发人员都不经常使用此方法来创建日期,但事实上却很简单。
它的参数从左到右分别为:年,月,日,时,分,秒,毫秒。就是这么简单。
new Date(2017, 3, 22, 5, 23, 50)
// This date can be easily read if you follow the left-right formula.
// Year: 2017,
// Month: April (because month is zero-indexed)
// Date: 22
// Hours: 05
// Minutes: 23
// Seconds: 50
唯一最大的问题就是月份的索引是从 0 开始的。如1月=== 0,2月=== 1,3月=== 2等等。
我们不知道为什么月份的索引是从 0 开始的,但确实如此,与其争论为什么不从 1 开始,不如试着去接收,一旦你接收了这个事实,它就变得容易多了。
通过几个例子熟悉一下:
// 21st March 1988, 12am, Local Time.
new Date(1988, 2, 21)
// 25th December 2019, 8am, Local Time.
new Date(2019, 11, 25, 8)
// 6th November 2023, 2:20am, Local Time
new Date(2023, 10, 6, 2, 20)
// 11th June 2019, 5:23:59am, Local Time
new Date(2019, 5, 11, 5, 23, 59)
你会发现使用参数创建的时间都是本地时间,这也是它的好处之一,不会像日期字符串那样会产生不同的结果。
如果你想创建UTC(世界协调时)的话,可以这么做:
// 11th June 2019, 12am, UTC.
new Date(Date.UTC(2019, 5, 11))
3.时间戳
在 JavaScript 中,时间戳是指自1970年1月1日到现在的毫秒数。据我的经验很少有人用它来创建日期,因为这个数字往往大的惊人,很不好计算。更多的是使用它来比较两个日期的大小。
// 11th June 2019, 8am (in my Local Time, Singapore)
new Date(1560211200000)
4.无参数
如果创建不带有任何的参数,它会返回当前的日期(本地时间)
new Date()
总结
- 你可以通过
new Date()
来创建一个日期 - 有四种语法可以创建:
- 日期字符串
- 日期参数
- 时间戳
- 无参数
- 不推荐使用日期字符串,因为它会有不同的结果。
- 最好的方式是使用参数方式创建,分别对应为:年,月,日,时,分,秒,毫秒
- 记住用参数创建时月份的索引从0开始。
接下来我们来谈谈日期格式的转换。
格式化日期
在其他语言中会提供格式化工具来创建一个你想要的日期格式,例如:在 PHP 中你可以用 date("d M Y")
来创建一个像23 Jan 2019
这种格式的。
但是在 JavaScript 中格式化日期并没有简单的方法。原生 Date
对象提供了 7 种格式化的方法,但是这 7 种方法返回的都是一个特定的值,并无使用价值。
const date = new Date(2019, 0, 23, 17, 23, 42)
- toString:返回 Wed Jan 23 2019 17:23:42 GMT+0800 (中国标准时间)
- toDateString:Wed Jan 23 2019
- toLocaleString:返回 23/01/2019, 17:23:42
- toLocaleDateString:23/01/2019
- toGMTString:Wed, 23 Jan 2019 09:23:42 GMT
- toUTCString:Wed, 23 Jan 2019 09:23:42 GMT
- toISOString:2019-01-23T09:23:42.079Z
如果想要一个自定义的值,此时就需要自己动手实现。
自定义格式
比如你想要一个像 Thu, 23 January 2019
这种日期,你需要用到下面四种方法:
- getFullYear:根据当地时间获取4位数的年份
- getMonth:根据当地时间获取一年中的月份(0-11)。月份是零索引的
- getDate:根据当地时间获取一个月中的某一天(1-31)
- getDay:根据当地时间获取一周中的某一天(0-6)。一周中的一天从星期日(0)开始,到星期六(6)结束。
获取年份和日期非常简单,直接使用 getFullYear
和 getDate
即可。
const d = new Date(2019, 0, 23)
const year = d.getFullYear() // 2019
const date = d.getDate() // 23
难的是获取Thu
和 January
。
想要获取January
可以创建一个对象,然后让十二个月的值映射到各自的名称上。
const months = {
0: 'January',
1: 'February',
2: 'March',
3: 'April',
4: 'May',
5: 'June',
6: 'July',
7: 'August',
8: 'September',
9: 'October',
10: 'November',
11: 'December'
}
因为月份的索引是从 0 开始的,所以我们可以使用数组来代替对象,其结果是一样的。
const months = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
]
获取January
,你需要:
- 使用
getMonth
获取到索引 - 从 months 获取到名称。
const monthIndex = d.getMonth()
const monthName = months[monthIndex]
console.log(monthName) // January
可合并为
const monthName = months(d.getMonth())
console.log(monthName) // January
同样的你可以用相同的方式来获取到 Thu
。
const days = [
'Sun',
'Mon',
'Tue',
'Wed',
'Thu',
'Fri',
'Sat'
]
然后:
- 使用
getDay
获取索引 - 从 days 获取到名称。
const dayName = days[d.getDay()] // Thu
至此,我们把上面的字符全部连接起来,就可以得到想要的结果。
const formatted = `${dayName}, ${date} ${monthName} ${year}`
console.log(formatted) // Thu, 23 January 2019
如果想创建自定义时间格式,可以用下面几个方法:
- getHours:根据当地时间获取小时数(0-23)。
- getMinutes: 根据当地时间获取分钟数(0-59)。
- getSeconds: 根据当地时间获取秒(0-59)。
- getMilliseconds: 根据本地时间获取毫秒(0-999)。
接下来,我们来继续谈日期的比较。
日期比较
如果想比较两个日期的大小,可直接使用比较符 >、<、>=、<= 。
const earlier = new Date(2019, 0, 26)
const later = new Date(2019, 0, 27)
console.log(earlier < later) // true
但如果你想比较两个日期是否相等,此时使用 == 或 === 却无能为力了。
const a = new Date(2019, 0, 26)
const b = new Date(2019, 0, 26)
console.log(a == b) // false
console.log(a === b) // false
想要比较两个日期是否相等,可以使用 getTime
来获取时间戳来进行比较。
const isSameTime = (a, b) => {
return a.getTime() === b.getTime()
}
const a = new Date(2019, 0, 26)
const b = new Date(2019, 0, 26)
console.log(isSameTime(a, b)) // true
如果想检查两个日期是否在同一天,可以检查它们的 getFullYear、getMonth 和 getDate 的值。
const isSameDay = (a, b) => {
return a.getFullYear() === b.getFullYear() &&
a.getMonth() === b.getMonth() &&
a.getDate()=== b.getDate()
}
const a = new Date(2019, 0, 26, 10) // 26 Jan 2019, 10am
const b = new Date(2019, 0, 26, 12) // 26 Jan 2019, 12pm
console.log(isSameDay(a, b)) // true
最后我们在谈一件事
计算日期
有两种可能的情况:
- 设置特定日期/时间
- 增加/减少日期
设定特定日期
你可以用以下方法设定日期:
- setFullYear:设置年份
- setMonth:设置月份
- setDate:设置天
- setHours:设置时
- setMinutes:设置分钟
- setSeconds:设置秒数
- setMilliseconds:设置毫秒数
例如可以将日期设置为 15号:
const d = new Date(2019, 0, 10)
d.setDate(15)
console.log(d) // 15 January 2019
如果想将月份设置为 6 月,可以用 setMonth
(月的索引要从 0 开始)
const d = new Date(2019, 0, 10)
d.setMonth(5)
console.log(d) // 10 June 2019
注意:上面的方法我们都修改了原始的对象,实际上我们不应该这么改变对象为什么在这里,应该创建一个新的对象进行操作。
const d = new Date(2019, 0, 10)
const newDate = new Date(d)
newDate.setMonth(5)
console.log(d) // 10 January 2019
console.log(newDate) // 10 June 2019
增加/减少 日期
想要计算改变后的日期,首先你需要获取到它们:
- getFullYear:根据当地时间获取4位数的年份
- getMonth:根据当地时间获取一年中的月份(0-11)。月份是零索引的
- getDate:根据当地时间获取一个月中的某一天(1-31)
- getHours:根据当地时间获取小时数(0-23)。
- getMinutes: 根据当地时间获取分钟数(0-59)。
- getSeconds: 根据当地时间获取秒(0-59)。
- getMilliseconds: 根据本地时间获取毫秒(0-999)。
通常有两种方法实现日期的增加或减少。第一种:简介但难理解,第二种,冗长但好理解。
一起来看
假设现在是2019年3月28日,我想要得到三天后的日期。
第一种方法:
const today = new Date(2019, 2, 28)
const finalDate = new Date(today)
finalDate.setDate(today.getDate() + 3)
console.log(finalDate) // 31 March 2019
第二种方法:
在这里,我们使用getFullYear、getMonth、getDate 和其他getter方法,直到找到想要更改的值的类型。然后我们用新日期创建最终日期。
const today = new Date(2019, 2, 28)
// Getting required values
const year = today.getFullYear()
const month = today.getMonh()
const day = today.getDate()
// Creating a new Date (with the delta)
const finalDate = new Date(year, month, day + 3)
console.log(finalDate) // 31 March 2019
以上两种方式都是有效的,你可以选择一种去做。
自动修正
如果你提供的日期值超出了其可接受的范围,JavaScript 会自动重新计算日期。
比如:把日期定在2019年3月33日,在这种情况下,JavaScript会自动将3月33日调整到4月2日。
// 33rd March => 2nd April
new Date(2019, 2, 33)
这意味着我们不需要担心计算分钟、小时、天、月等。 JavaScript 会自动帮助我们处理。
// 33rd March => 2nd April
new Date(2019, 2, 30 + 3)
到这里,有关于日期对象的所有东西你都已经了解啦。
原文:https://css-tricks.com/everything-you-need-to-know-about-date-in-javascript/
翻译:六小登登
更多优质文章:六小登登的博客
我是一名爱写作的技术人。
关注公众号:六小登登,后台回复「1024」即可免费获取惊喜福利!后台回复「加群」群里每天都会全网搜罗好文章给你。