成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

dayjs 源碼解析(四)(Dayjs 類(lèi))

BicycleWarrior / 2059人閱讀

摘要:前言上一篇源碼解析三構(gòu)造函數(shù)介紹了的源碼中的函數(shù)。接下來(lái),本篇將解讀一下中的類(lèi)。首先,我們看的構(gòu)造函數(shù),該構(gòu)造函數(shù)調(diào)用了實(shí)例方法,傳入?yún)?shù)在上一篇有講到。下一篇源碼解析五插件詳解

前言

上一篇 dayjs 源碼解析(三)(dayjs 構(gòu)造函數(shù))介紹了 dayjs 的源碼中的 dayjs 函數(shù)。接下來(lái),本篇將解讀一下 index.js 中的 Dayjs 類(lèi)。

class Dayjs {
  constructor(cfg) {
    this.parse(cfg) // for plugin
  }

  parse(cfg) {
    this.$d = parseDate(cfg.date)
    this.init(cfg)
  }

  init(cfg) {
    this.$y = this.$d.getFullYear() // 年
    this.$M = this.$d.getMonth() // 月(注意從 0 開(kāi)始)
    this.$D = this.$d.getDate() // 日
    this.$W = this.$d.getDay() // 周幾(0 表示周日)
    this.$H = this.$d.getHours() // 時(shí)
    this.$m = this.$d.getMinutes() // 分
    this.$s = this.$d.getSeconds() // 秒
    this.$ms = this.$d.getMilliseconds() // 毫秒
    this.$L = this.$L || parseLocale(cfg.locale, null, true) || L // 語(yǔ)言,默認(rèn)為 "en"
  }

  // 下面的都是實(shí)例方法
  $utils() {
    return Utils
  }

  isValid() {
    return !(this.$d.toString() === "Invalid Date")
  }

  isLeapYear() {
    return ((this.$y % 4 === 0) && (this.$y % 100 !== 0)) || (this.$y % 400 === 0)
  }

  $compare(that) {
    return this.valueOf() - dayjs(that).valueOf()
  }

  isSame(that) {
    return this.$compare(that) === 0
  }

  isBefore(that) {
    return this.$compare(that) < 0
  }

  isAfter(that) {
    return this.$compare(that) > 0
  }

  year() {
    return this.$y
  }

  month() {
    return this.$M
  }

  day() {
    return this.$W
  }

  date() {
    return this.$D
  }

  hour() {
    return this.$H
  }

  minute() {
    return this.$m
  }

  second() {
    return this.$s
  }

  millisecond() {
    return this.$ms
  }

  unix() {
    return Math.floor(this.valueOf() / 1000)
  }

  valueOf() {
    // timezone(hour) * 60 * 60 * 1000 => ms
    return this.$d.getTime()
  }

  startOf(units, startOf) { // startOf -> endOf
    const isStartOf = !Utils.isUndefined(startOf) ? startOf : true
    const unit = Utils.prettyUnit(units)
    const instanceFactory = (d, m) => {
      const ins = wrapper(new Date(this.$y, m, d), this)
      return isStartOf ? ins : ins.endOf(C.D)
    }
    const instanceFactorySet = (method, slice) => {
      const argumentStart = [0, 0, 0, 0]
      const argumentEnd = [23, 59, 59, 999]
      return wrapper(this.toDate()[method].apply( // eslint-disable-line prefer-spread
        this.toDate(),
        isStartOf ? argumentStart.slice(slice) : argumentEnd.slice(slice)
      ), this)
    }
    switch (unit) {
      case C.Y:
        return isStartOf ? instanceFactory(1, 0) :
          instanceFactory(31, 11)
      case C.M:
        return isStartOf ? instanceFactory(1, this.$M) :
          instanceFactory(0, this.$M + 1)
      case C.W:
        return isStartOf ? instanceFactory(this.$D - this.$W, this.$M) :
          instanceFactory(this.$D + (6 - this.$W), this.$M)
      case C.D:
      case C.DATE:
        return instanceFactorySet("setHours", 0)
      case C.H:
        return instanceFactorySet("setMinutes", 1)
      case C.MIN:
        return instanceFactorySet("setSeconds", 2)
      case C.S:
        return instanceFactorySet("setMilliseconds", 3)
      default:
        return this.clone()
    }
  }

  endOf(arg) {
    return this.startOf(arg, false)
  }

  $set(units, int) { // private set
    const unit = Utils.prettyUnit(units)
    switch (unit) {
      case C.DATE:
        this.$d.setDate(int)
        break
      case C.M:
        this.$d.setMonth(int)
        break
      case C.Y:
        this.$d.setFullYear(int)
        break
      case C.H:
        this.$d.setHours(int)
        break
      case C.MIN:
        this.$d.setMinutes(int)
        break
      case C.S:
        this.$d.setSeconds(int)
        break
      case C.MS:
        this.$d.setMilliseconds(int)
        break
      default:
        break
    }
    this.init()
    return this
  }


  set(string, int) {
    return this.clone().$set(string, int)
  }

  add(number, units) {
    number = Number(number) // eslint-disable-line no-param-reassign
    const unit = Utils.prettyUnit(units)
    const instanceFactory = (u, n) => {
      const date = this.set(C.DATE, 1).set(u, n + number)
      return date.set(C.DATE, Math.min(this.$D, date.daysInMonth()))
    }
    if (unit === C.M) {
      return instanceFactory(C.M, this.$M)
    }
    if (unit === C.Y) {
      return instanceFactory(C.Y, this.$y)
    }
    let step
    switch (unit) {
      case C.MIN:
        step = C.MILLISECONDS_A_MINUTE
        break
      case C.H:
        step = C.MILLISECONDS_A_HOUR
        break
      case C.D:
        step = C.MILLISECONDS_A_DAY
        break
      case C.W:
        step = C.MILLISECONDS_A_WEEK
        break
      case C.S:
        step = C.MILLISECONDS_A_SECOND
        break
      default: // ms
        step = 1
    }
    const nextTimeStamp = this.valueOf() + (number * step)
    return wrapper(nextTimeStamp, this)
  }

  subtract(number, string) {
    return this.add(number * -1, string)
  }

  format(formatStr) {
    const str = formatStr || C.FORMAT_DEFAULT
    const zoneStr = Utils.padZoneStr(this.$d.getTimezoneOffset())
    const locale = this.$locale()
    const {
      weekdays, months
    } = locale
    const getShort = (arr, index, full, length) => (
      (arr && arr[index]) || full[index].substr(0, length)
    )
    return str.replace(C.REGEX_FORMAT, (match) => {
      if (match.indexOf("[") > -1) return match.replace(/[|]/g, "")
      switch (match) {
        case "YY":
          return String(this.$y).slice(-2)
        case "YYYY":
          return String(this.$y)
        case "M":
          return String(this.$M + 1)
        case "MM":
          return Utils.padStart(this.$M + 1, 2, "0")
        case "MMM":
          return getShort(locale.monthsShort, this.$M, months, 3)
        case "MMMM":
          return months[this.$M]
        case "D":
          return String(this.$D)
        case "DD":
          return Utils.padStart(this.$D, 2, "0")
        case "d":
          return String(this.$W)
        case "dd":
          return getShort(locale.weekdaysMin, this.$W, weekdays, 2)
        case "ffffd":
          return getShort(locale.weekdaysShort, this.$W, weekdays, 3)
        case "ffffdd":
          return weekdays[this.$W]
        case "H":
          return String(this.$H)
        case "HH":
          return Utils.padStart(this.$H, 2, "0")
        case "h":
        case "hh":
          if (this.$H === 0) return 12
          return Utils.padStart(this.$H < 13 ? this.$H : this.$H - 12, match === "hh" ? 2 : 1, "0")
        case "a":
          return this.$H < 12 ? "am" : "pm"
        case "A":
          return this.$H < 12 ? "AM" : "PM"
        case "m":
          return String(this.$m)
        case "mm":
          return Utils.padStart(this.$m, 2, "0")
        case "s":
          return String(this.$s)
        case "ss":
          return Utils.padStart(this.$s, 2, "0")
        case "SSS":
          return Utils.padStart(this.$ms, 3, "0")
        case "Z":
          return zoneStr
        default: // "ZZ"
          return zoneStr.replace(":", "")
      }
    })
  }

  diff(input, units, float) {
    const unit = Utils.prettyUnit(units)
    const that = dayjs(input)
    const diff = this - that
    let result = Utils.monthDiff(this, that)
    switch (unit) {
      case C.Y:
        result /= 12
        break
      case C.M:
        break
      case C.Q:
        result /= 3
        break
      case C.W:
        result = diff / C.MILLISECONDS_A_WEEK
        break
      case C.D:
        result = diff / C.MILLISECONDS_A_DAY
        break
      case C.H:
        result = diff / C.MILLISECONDS_A_HOUR
        break
      case C.MIN:
        result = diff / C.MILLISECONDS_A_MINUTE
        break
      case C.S:
        result = diff / C.MILLISECONDS_A_SECOND
        break
      default: // milliseconds
        result = diff
    }
    return float ? result : Utils.absFloor(result)
  }

  daysInMonth() {
    return this.endOf(C.M).$D
  }

  $locale() { // get locale object
    return Ls[this.$L]
  }

  locale(preset, object) {
    const that = this.clone()
    that.$L = parseLocale(preset, object, true)
    return that
  }

  clone() {
    return wrapper(this.toDate(), this)
  }

  toDate() {
    return new Date(this.$d)
  }

  toArray() {
    return [
      this.$y,
      this.$M,
      this.$D,
      this.$H,
      this.$m,
      this.$s,
      this.$ms
    ]
  }

  toJSON() {
    return this.toISOString()
  }

  toISOString() {
    // ie 8 return
    // new Dayjs(this.valueOf() + this.$d.getTimezoneOffset() * 60000)
    // .format("YYYY-MM-DDTHH:mm:ss.SSS[Z]")
    return this.toDate().toISOString()
  }

  toObject() {
    return {
      years: this.$y,
      months: this.$M,
      date: this.$D,
      hours: this.$H,
      minutes: this.$m,
      seconds: this.$s,
      milliseconds: this.$ms
    }
  }

  toString() {
    return this.$d.toUTCString()
  }
}

上面是類(lèi) Dayjs 中的所有代碼。

首先,我們看 Dayjs 的構(gòu)造函數(shù),該構(gòu)造函數(shù)調(diào)用了 Dayjs 實(shí)例方法 parse ,傳入 cfg 參數(shù)(cfg 在 上一篇 有講到)。

在 parse 實(shí)例方法中,會(huì)使用 parseDate 函數(shù),傳入 cfg.date 屬性,得到 JavaScript 中原生的 Date 對(duì)象,且將 Date 對(duì)象保存在 Dayjs 實(shí)例屬性(實(shí)例中的屬性)中。然后再調(diào)用實(shí)例方法 init 來(lái)初始化 Dayjs 實(shí)例的其他屬性。

在 init 實(shí)例方法中,使用實(shí)例屬性 $d(為 JavaScript 原生 Date 對(duì)象)來(lái)獲取 年、月、日、周幾、時(shí)、分、秒、毫秒,且保存在實(shí)例中。并且調(diào)用 parseLocale 函數(shù)來(lái)獲取語(yǔ)言,賦值給 Dayjs 實(shí)例的 $L 屬性。

再下面的代碼,便是實(shí)例方法了,即在 第一篇 所講的 api 都是實(shí)例方法,源碼都可以在這里找到。

在 Dayjs 類(lèi)中 add、subtract 等方法,都會(huì)返回一個(gè)新的 Dayjs 實(shí)例,是通過(guò)使用 Dayjs 類(lèi)中的 clone() 方法實(shí)現(xiàn)的。所以,通過(guò)這個(gè) clone() 方法,實(shí)現(xiàn)了 dayjs 的 immutable 特性。

下一篇:dayjs 源碼解析(五)(dayjs 插件詳解)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/95984.html

相關(guān)文章

  • dayjs 源碼解析(五)(dayjs 插件詳解)

    摘要:前言上一篇源碼解析四類(lèi)介紹了的源碼目錄結(jié)構(gòu)。接下來(lái),本篇將分析一下中插件功能的用法源碼以及如何編寫(xiě)自己的插件。并且,可以通過(guò)插件選項(xiàng),來(lái)對(duì)插件進(jìn)行配置。 前言 上一篇 dayjs 源碼解析(四)(Dayjs 類(lèi))介紹了 dayjs 的源碼目錄結(jié)構(gòu)。接下來(lái),本篇將分析一下 dayjs 中插件功能的用法、源碼以及如何編寫(xiě)自己的 dayjs 插件。 dayjs 插件用法 dayjs 的插件,...

    RaoMeng 評(píng)論0 收藏0
  • dayjs 源碼解析(三)(dayjs 構(gòu)造函數(shù))

    摘要:接下來(lái),本篇將解讀一下中的構(gòu)造函數(shù)。最后將傳入類(lèi)的構(gòu)造函數(shù),生成一個(gè)對(duì)象,作為函數(shù)的返回值給返回了。參數(shù)通過(guò)上面對(duì)參數(shù)的分析知道了參數(shù)其實(shí)是當(dāng)參數(shù)為實(shí)例對(duì)象時(shí),最后又會(huì)調(diào)用函數(shù),此時(shí)才會(huì)傳入?yún)?shù)。 前言 上一篇 dayjs 源碼解析(二)(目錄結(jié)構(gòu))介紹了 dayjs 的源碼目錄結(jié)構(gòu)。接下來(lái),本篇將解讀一下 index.js 中的 dayjs 構(gòu)造函數(shù)。 dayjs 構(gòu)造函數(shù) // ...

    ityouknow 評(píng)論0 收藏0
  • dayjs 源碼解析(一)(api)

    摘要:下面,我將自己閱讀的源碼的過(guò)程記錄下來(lái)。閱讀庫(kù)的代碼,首先先要知道這個(gè)庫(kù)的作用是一個(gè)輕量的時(shí)間日期處理庫(kù),其用法和完全一樣。介紹首先,閱讀的源碼,我們應(yīng)該從的入手。對(duì)象是不可變的,即所有改變的操作都會(huì)返回一個(gè)新的實(shí)例。 前言 作為一個(gè)程序員,閱讀別人優(yōu)秀代碼是提升自己技術(shù)能力的一個(gè)很好的方法。下面,我將自己閱讀 dayjs(v1.6.10)的源碼的過(guò)程記錄下來(lái)。 閱讀庫(kù)的代碼,首先先要...

    BlackMass 評(píng)論0 收藏0
  • dayjs 源碼解析(二)(目錄結(jié)構(gòu))

    摘要:前言上一篇源碼解析一,介紹了一下的,知道了如何使用。本篇,介紹項(xiàng)目的目錄結(jié)構(gòu)。源碼解析三構(gòu)造函數(shù) 前言 上一篇 dayjs 源碼解析(一)(api),介紹了一下 dayjs 的 api,知道了如何使用 dayjs。本篇,介紹 dayjs 項(xiàng)目的目錄結(jié)構(gòu)。 目錄結(jié)構(gòu) showImg(https://segmentfault.com/img/bVbcW0Q?w=229&h=832); 在 ...

    Youngs 評(píng)論0 收藏0
  • ?Day.js 2kB超輕量時(shí)間庫(kù) 和Moment.js一樣的API

    showImg(https://segmentfault.com/img/bV9wV7?w=1952&h=712);Moment.js 是一個(gè)大而全的 JS 時(shí)間庫(kù),很大地方便了我們處理日期和時(shí)間。但是 Moment.js太重了(200k+ with locals),可能一般項(xiàng)目也只使用到了她幾個(gè)常用的API。雖然社區(qū)也有幾個(gè)輕量的時(shí)間庫(kù),要想遷移過(guò)去又會(huì)增加新的學(xué)習(xí)和遷移成本。 如果能有一個(gè)和 ...

    CoreDump 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<