DayJs源码(四)Dayjs类中API

2021-05-06  本文已影响0人  小q

Dayjs中的API被定义在Dayjs类中,因为有很多,所以这里将挑选部分来记录。

• isValid() 验证Day.js对象是否包含有效日期。

isValid() {
    return !(this.$d.toString() === C.INVALID_DATE_STRING) // Invalid Date
 }

• startOf()方法 定义开始时间

  startOf(units, startOf) { // startOf -> endOf
    const isStartOf = !Utils.u(startOf) ? startOf : true // startof调用时不传,endof调用时传false
    const unit = Utils.p(units) // 解析以什么单位开始
    const instanceFactory = (d, m) => {
      const ins = Utils.w(this.$u ?
        Date.UTC(this.$y, m, d) : 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 Utils.w(this.toDate()[method].apply( // eslint-disable-line prefer-spread // Utils.w 就是wrapper方法
        this.toDate('s'),
        (isStartOf ? argumentStart : argumentEnd).slice(slice)
      ), this)
    }
    const { $W, $M, $D } = this
    const utcPad = `set${this.$u ? 'UTC' : ''}` // UTC() 方法可根据世界时返回 1970 年 1 月 1 日 到指定日期的毫秒数
    switch (unit) {
      case C.Y: // 选择年
        return isStartOf ? instanceFactory(1, 0) :
          instanceFactory(31, 11)
      case C.M: // 选择分钟
        return isStartOf ? instanceFactory(1, $M) :
          instanceFactory(0, $M + 1)
      case C.W: { // 选择星期
        const weekStart = this.$locale().weekStart || 0
        const gap = ($W < weekStart ? $W + 7 : $W) - weekStart
        return instanceFactory(isStartOf ? $D - gap : $D + (6 - gap), $M)
      }
      case C.D: // 选择天
      case C.DATE:
        return instanceFactorySet(`${utcPad}Hours`, 0)
      case C.H: // 选择时
        return instanceFactorySet(`${utcPad}Minutes`, 1)
      case C.MIN: // 选择分
        return instanceFactorySet(`${utcPad}Seconds`, 2)
      case C.S: // 选择秒
        return instanceFactorySet(`${utcPad}Milliseconds`, 3)
      default:
        return this.clone()
    }
  }

  endOf(arg) {
    return this.startOf(arg, false)
  }
  format(formatStr) {
    if (!this.isValid()) return C.INVALID_DATE_STRING // return Invalid Date

    const str = formatStr || C.FORMAT_DEFAULT // 不传的话按YYYY-MM-DDTHH:mm:ssZ格式
    const zoneStr = Utils.z(this) // Utils.z 为 padZoneStr方法 ,具体如下Utils中代码
    const locale = this.$locale()
    const { $H, $m, $M } = this
    const {
      weekdays, months, meridiem
    } = locale
    const getShort = (arr, index, full, length) => ( // 返回月份,如Aug || August
      (arr && (arr[index] || arr(this, str))) || full[index].substr(0, length)
    )
    const get$H = num => (
      Utils.s($H % 12 || 12, num, '0')
    )

    const meridiemFunc = meridiem || ((hour, minute, isLowercase) => { // 返回 大小写的上/下午
      const m = (hour < 12 ? 'AM' : 'PM')
      return isLowercase ? m.toLowerCase() : m
    })

    const matches = {
      YY: String(this.$y).slice(-2), // 如2021,截取21
      YYYY: this.$y, // 2021
      M: $M + 1, // 1
      MM: Utils.s($M + 1, 2, '0'), // 01
      MMM: getShort(locale.monthsShort, $M, months, 3), // Aug
      MMMM: getShort(months, $M), // August
      D: this.$D, // 1
      DD: Utils.s(this.$D, 2, '0'), // 01
      d: String(this.$W),
      dd: getShort(locale.weekdaysMin, this.$W, weekdays, 2),
      ddd: getShort(locale.weekdaysShort, this.$W, weekdays, 3),
      dddd: weekdays[this.$W],
      H: String($H),
      HH: Utils.s($H, 2, '0'),
      h: get$H(1),
      hh: get$H(2),
      a: meridiemFunc($H, $m, true), // am || pm
      A: meridiemFunc($H, $m, false), // AM || PM
      m: String($m),
      mm: Utils.s($m, 2, '0'), // Utils.s 为padStart方法
      s: String(this.$s),
      ss: Utils.s(this.$s, 2, '0'),
      SSS: Utils.s(this.$ms, 3, '0'),
      Z: zoneStr // 'ZZ' logic below
    }

    return str.replace(C.REGEX_FORMAT, (match, $1) => $1 || matches[match] || zoneStr.replace(':', '')) // 'ZZ'
  }
// utils.js
const padStart = (string, length, pad) => {
  const s = String(string)
  if (!s || s.length >= length) return string
  return `${Array((length + 1) - s.length).join(pad)}${string}` // 在前面拼接“0”如padStart(3,2,'0'),返回“03”
}

const padZoneStr = (instance) => {
  const negMinutes = -instance.utcOffset() // 返回格林威治时间和本地时间之间的时差
  const minutes = Math.abs(negMinutes)
  const hourOffset = Math.floor(minutes / 60)
  const minuteOffset = minutes % 60 
  return `${negMinutes <= 0 ? '+' : '-'}${padStart(hourOffset, 2, '0')}:${padStart(minuteOffset, 2, '0')}` // 返回如 +03:30
}

// index.js
  utcOffset() {
    // Because a bug at FF24, we're rounding the timezone offset around 15 minutes
    //因为FF24有一个bug,我们将时区偏移取整为15分钟
    // https://github.com/moment/moment/pull/1871
    return -Math.round(this.$d.getTimezoneOffset() / 15) * 15 // 返回格林威治时间和本地时间之间的时差,以分钟为单位
  }
  diff(input, units, float) {
    const unit = Utils.p(units) // Utils中 prettyUnit 方法
    const that = dayjs(input)
    const zoneDelta = (that.utcOffset() - this.utcOffset()) * C.MILLISECONDS_A_MINUTE // 60 * 1e3
    const diff = this - that
    let result = Utils.m(this, that)

    result = {
      [C.Y]: result / 12,
      [C.M]: result,
      [C.Q]: result / 3,
      [C.W]: (diff - zoneDelta) / C.MILLISECONDS_A_WEEK,
      [C.D]: (diff - zoneDelta) / C.MILLISECONDS_A_DAY,
      [C.H]: diff / C.MILLISECONDS_A_HOUR,
      [C.MIN]: diff / C.MILLISECONDS_A_MINUTE,
      [C.S]: diff / C.MILLISECONDS_A_SECOND
    }[unit] || diff // milliseconds

    return float ? result : Utils.a(result)
  }

以上是Dayjs类中部分API,接下来会总结DayJs插件

上一篇 下一篇

猜你喜欢

热点阅读