• 【译】JavaScript中的Date对象


    原文:https://css-tricks.com/everything-you-need-to-know-about-date-in-javascript/
    作者:Zell Liew

    日期在JavaScript中很奇怪。当我们需要处理日期和时间的时候,它会让我们非常紧张,以至于我们需要借助于date -fnsMoment这样的库
    但是我们并不总是需要使用库。如果你知道哪些地方需要注意,日期对象其实很简单。在本文中,我将带您了解关于Date对象的所有内容。
    首先,让我们讨论下时区

    时区

    世界上有上百个时区,在JavaScript中,我们只关心两个时区:本地时间和协调世界时(UTC)

    • 本地时间是指您的计算机所在的时区。
    • UTC实际上就是格林威治标准时间(GMT)。

    默认情况下,JavaScript中的几乎每个日期方法(除了一个)都以本地时间显示日期/时间。只有当指定UTC时才会得到UTC。在这个前提下,我们来讨论创建日期对象

    创造一个日期对象

    你可以使用new date创建一个日期。有四种方式使用new Date():

    • 日期格式的字符串
    • 日期类型的参数
    • 时间戳
    • 空参数

    日期字符串形式

    在构造方法中,通过将日期格式的字符串传递给new date来创建一个日期。

    new Date('1988-03-21')
    

    我们更倾向于这种方式,这更贴*我们*常生活的书写方式
    如果写成21-03-1988,我们可以推断出正确的日期1988年3月21日,但是在js里面,21-03-1988是无效的日期,你会得到Invalid Date

    new Date('21-03-1988') returns Invalid Date.

    在世界的不同地方,对日期字符串的解释是不同的。例如11-06-2019不是2019年6月11日就是2019年11月6日。但是你不能确定我指的是哪一个,除非你知道我使用的哪种日期系统。

    在JavaScript中,如果想使用日期字符串,需要使用一种全世界都接受的格式。其中一种格式是 ISO 8601 Extended format

    // ISO 8601 Extended format
    `YYYY-MM-DDTHH:mm:ss:sssZ`
    

    这些值代表:

    • YYYY:四位数字的年
    • MM:两数字的月(一月是01,12月是12)
    • DD:两位数字的日期(0-31)
    • -:日期分隔符
    • T: 指定开始时间
    • HH: 24小时制时间表示(0-23)
    • mm: 分钟 (0 to 59)
    • ss: 秒 (0 to 59)
    • sss: 毫秒 (0 to 999)
    • :: 时间分隔符
    • Z: 如果制定了Z,日期就会被表示为UTC. 如果 Z 没有指定,则为当地时间. (仅只适用于提供时间的情况)

    如果要创建日期,小时、分钟、秒和毫秒都是可选的。所以,如果你想为2019年6月11日设定一个日期,你可以这样写:

    new Date('2019-06-11')
    

    这里要特别注意。使用日期字符串创建日期有一个很大的问题。如果console.log这个日期,就会发现问题。

    如果你住在格林威治标准时间之后的地区,你会得到一个日期是6月10日。

    new Date('2019-06-11') produces 10th June if you're in a place behind GMT.

    如果你住在格林尼治时间之前,你会得到一个日期是6月11

    new Date('2019-06-11')produces 11th June if you're in a place after GMT.

    这是因为日期字符串这种方式有一个特殊的行为:如果你创建一个日期(不指定时间),您将得到一个UTC中的日期集。

    在上面的场景中,当new Date('2019-06-11')时,实际上创建的日期是2019年6月11日,UTC时间上午12点。这就是为什么住在格林尼治标准时间之后的地区的人得到的是6月10日而不是6月11日

    如果希望使用日期字符串的形式在本地时间创建日期,则需要包含时间。当你包括时间,你至少需要HHmm(或谷歌Chrome返回一个无效的日期)。

    new Date('2019-06-11T00:00')
    
    Date created in Local Time vsl. Date created in UTC.

    本地时间和UTC类型的日期字符串这两者可能会产生错误,而且难以被发现。所以,我建议你不要使用日期字符串创建日期。(顺便说一下,MDN也警告不要使用日期字符串方法,因为浏览器可能以不同的方式解析日期字符串)

    MDN recommends against creating date with date strings.
    如果要创建日期,请使用参数或时间戳。

    使用参数创建日期

    你可以传递给new Date()七种类型的参数来创建一个日期/时间

    1. Year: 四位数的年.
    2. Month: 月份 (0-11). 月份从0开始,如果省略,默认是0.
    3. Day: 天 (1-31). 如果省略,默认是1.
    4. Hour: 小时 (0-23). 如果省略,默认是0.
    5. Minutes: 分钟 (0-59). 如果省略,默认是0.
    6. Seconds: 秒 (0-59). 如果省略,默认是0.
    7. Milliseconds: 毫秒 (0-999). 如果省略,默认是0。
    // 11th June 2019, 5:23:59am, Local Time
    new Date(2019, 5, 11, 5, 23, 59)
    

    许多开发人员(包括我自己)都避免使用arguments方法,因为它看起来很复杂。其实很简单。

    试着从左到右阅读数字,依次递减为:年、月、日、小时、分钟、秒和毫秒。

    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
    

    Date中最让人费解的地方是月份的值是从0开始的,例如,January === 0, February === 1, March === 2等等。

    我们不知道为什么会这样,但确实javascript就是这么设计的。所以与其争论不如接受。 一旦你接受了这个事实,日期变得非常容易使用。

    这里还有一些例子可以让你熟悉下:

    // 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之间混淆。 如果您需要UTC,请以这种方式创建UTC日期:

    // 11th June 2019, 12am, UTC.
    new Date(Date.UTC(2019, 5, 11))
    

    用时间戳创建日期

    在JavaScript中,时间戳是自1970年1月1日以来经过的毫秒数(1970年1月1日也称为Unix纪元时间)。 根据我的经验,您很少使用时间戳来创建日期。 您只能使用时间戳来比较不同的日期(稍后会详细介绍)。

    // 11th June 2019, 8am (in my Local Time, Singapore)
    new Date(1560211200000)
    

    空参数创建日期

    如果您创建一个没有任何参数的日期,您将得到一个设置为当前时间的日期(在本地时间中)。

    当前时间
    你可以从图像中看出,当我写这篇文章时,它是5月25日上午11点10分在新加坡。

    创建日期方式总结

    1. 你可以使用 new Date()创建日期.
    2. 有四种可行的语法:
      1. 日期字符串
      2. 参数形式
      3. 时间戳
      4. 空参数
    3. 不要使用日期字符串形式.
    4. 最好使用参数形式.
    5. 谨记月份是从0开始索引的.

    接下来,让我们讨论将日期转换为可读字符串。

    格式化日期

    大多数编程语言都提供了格式化工具来创建所需的任何日期格式。例如,在PHP中,可以使用date(“d M Y”)将日期格式化为2019年1月23日。

    但在javascript中没有这种简便的方式

    原生Date对象提供了7种格式化方法。这七个方法中的每一个都为您提供了一个特定的值(它们非常无用)。

    const date = new Date(2019, 0, 23, 17, 23, 42)
    
    1. toString --> Wed Jan 23 2019 17:23:42 GMT+0800 (Singapore Standard Time)
    2. toDateString --> Wed Jan 23 2019
    3. toLocaleString --> 23/01/2019, 17:23:42
    4. toLocaleDateString --> 23/01/2019
    5. toGMTString --> Wed, 23 Jan 2019 09:23:42 GMT
    6. toUTCString --> Wed, 23 Jan 2019 09:23:42 GMT
    7. toISOString --> 2019-01-23T09:23:42.079Z

    如果您需要自定义格式,则需要自己创建。

    自定义日期格式

    假设你想要的是Thu, 23 January 2019 这种格式,你需要使用Date对象提供的方法。
    要获取日期,可以使用以下四种方法:

    1. getFullYear: 根据当地时间获取四位数表示的年
    2. getMonth: 根据当地时间获月 (0-11).
    3. getDate: 根据当地时间获取日期,一个月中的第多少天 (1-31).
    4. getDay: 根据当地时间获取一周中的第多少天 (0-6),一周是指 Sunday (0) 到 Saturday (6).

    所以,为了创建Thu, 23 January 2019这种格式,我们可以这样来做:

    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'
    }
    

    由于Month是零索引的,所以我们可以使用数组而不是对象。它会产生相同的结果。

    const months = [
      'January',
      'February',
      'March',
      'April',
      'May',
      'June',
      'July',
      'August',
      'September',
      'October',
      'November',
      'December'
    ]
    

    现在你可以这么做:

    1. 使用 getMonth 得到月份对应的索引.
    2. 根据索引从 months 获取对应的月份
    const monthIndex = d.getMonth()
    const monthName = months[monthIndex]
    console.log(monthName) // January
    

    相同方法可以获取到Thu,创建一个包含一周七天的数组。

    const days = [
      'Sun',
      'Mon',
      'Tue',
      'Wed',
      'Thu',
      'Fri',
      'Sat'
    ]
    

    然后:

    1. 使用 getDay 得到 dayIndex
    2. 根据 dayIndex 得到 dayName
    const dayIndex = d.getDay()
    const dayName = days[dayIndex] // Thu
    

    然后,将创建的所有变量组合起来以获得格式化的字符串。

    const formatted = `${dayName}, ${date} ${monthName} ${year}`
    console.log(formatted) // Thu, 23 January 2019
    

    的确,这样做很麻烦,但是一旦你掌握了,就简单了

    如果需要创建自定义格式的时间,可以使用以下方法(全部是根据当地时间):

    1. getHours: 小时 (0-23).
    2. getMinutes: 分钟 (0-59).
    3. getSeconds: 秒 (0-59).
    4. 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
    

    如果想检查两个日期是否在同一天,可以比较它们的getFullYeargetMonthgetDate值。

    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
    

    还有最后一个问题,我们需要讨论

    根据一个日期获得另一个日期

    有两种可能的情况,您希望从一个日期获取另一个日期。

    1. 相对于另一个日期开始,设置某个时间/日期值.
    2. 相对于另一个日期开始,增加或者减少某个值.

    设置某个时间/日期值

    你可以使用下列方法,为某个日期设置时间/日期值,方法都是比较语义化的:

    1. setFullYear: Set 4-digit year in Local Time.
    2. setMonth: Set month of the year in Local Time.
    3. setDate: Set day of the month in Local Time.
    4. setHours: Set hours in Local Time.
    5. setMinutes: Set minutes in Local Time.
    6. setSeconds: Set seconds in Local Time.
    7. setMilliseconds: Set milliseconds in Local Time.

    例如,如果想将日期设置为一个月中的15号,可以使用setDate(15)

    const d = new Date(2019, 0, 10)
    d.setDate(15)
    
    console.log(d) // 15 January 2019
    

    月份也是一样,记住,月份是从0开始的

    const d = new Date(2019, 0, 10)
    d.setMonth(5)
    
    console.log(d) // 10 June 2019
    

    注意:上面的setter方法会改变原始日期对象。 在实际中,我们不应该改变原对象(了解更多 )我们应该在新的日期对象上执行这些操作。

    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
    

    从某个日期的基础上增加或者减少值

    通过在另一个日期添加/减去delta,我的意思是:您希望从另一个日期获得X的日期。 它可以是X年,X月,X天等。

    要获得delta,您需要知道当前日期的值。 您可以使用以下方法获取它:

    1. getFullYear: Gets 4-digit year according to local time
    2. getMonth: Gets month of the year (0-11) according to local time.
    3. getDate: Gets day of the month (1-31) according to local time.
    4. getHours: Gets hours (0-23) according to local time.
    5. getMinutes: Gets minutes (0-59) according to local time.
    6. getSeconds: Gets seconds (0-59) according to local time.
    7. getMilliseconds: Gets milliseconds (0-999) according to local time.

    添加/减去delta有两种通用方法。 第一种方法在Stack Overflow上更受欢迎。 它简洁,但更难掌握。 第二种方法更冗长,但更容易理解。

    我们假设今天是2019年3月28日,你想要一个三天以后的日期

    第一种方式

    // Assumes today is 28 March 2019
    const today = new Date(2019, 2, 28)
    

    首先,我们创建一个新的Date对象(这样我们就不会更改原始日期)

    const finalDate = new Date(today)
    

    接下来,我们需要知道我们想要改变的值。 由于我们想改变的天数,所以我们可以通过getDate获得天。

    const currentDate = today.getDate()
    

    想获得三天以后的日期,我们将使用将delta(3)添加到当前日期

    finalDate.setDate(currentDate + 3)
    

    完整代码:

    const today = new Date(2019, 2, 28)
    const finalDate = new Date(today)
    finalDate.setDate(today.getDate() + 3)
    
    console.log(finalDate) // 31 March 2019
    

    第一种方式

    我们使用getFullYeargetMonthgetDate和其他getter方法,直到得到我们想要更改的类型。然后,使用 new Date 来创建日期。

    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
    

    日期自动纠错

    如果为Date提供一个超出其可接受范围的值,JavaScript将自动重新计算日期。

    假如我们将日期设置为33rd March 2019,这是个无效的日期,JavaScript 会自动将 33rd March 调整到 2nd April.

    // 33rd March => 2nd April
    new Date(2019, 2, 33)
    
    33rd March gets converted to 2nd April automatically.

    这意味着在创建一个增量时,您不需要担心计算分钟、小时、天、月等。JavaScript自动为您处理它。

    // 33rd March => 2nd April
    new Date(2019, 2, 30 + 3)
    
    30 + 3 = 33. 33rd March gets converted to 2nd April automatically.

    以上就是你需要了解的关于JavaScript的原生日期对象的知识

  • 相关阅读:
    设计模式(八): 策略模式
    设计模式(七): 迭代器模式
    设计模式(六): 建造者模式
    设计模式(五): 装饰者模式
    设计模式(四): 适配器模式
    设计模式(三): 抽象工厂模式
    设计模式(二): 工厂模式
    设计模式(一): 单例模式
    Hibernate三种状态,缓存,以及update更新问题
    Servlet 生命周期、工作原理
  • 原文地址:https://www.cnblogs.com/zlv2snote/p/11103020.html
Copyright © 2020-2023  润新知