isDate.mjs

import get from 'lodash-es/get.js'
import isbol from './isbol.mjs'
import isestr from './isestr.mjs'
import isnum from './isnum.mjs'
import cdbl from './cdbl.mjs'


/**
 * 判斷是否為時間(Date)
 *
 * 預設可輸入Date、可解析為時間之字串或數值,判斷是否為有效時間
 * 若opt.onlyCheckDateObject為true,則僅以Object.prototype.toString.call(v)判斷是否為Date物件,不解析字串與數值,無效日期(Invalid Date)與跨realm(例如iframe、vm)之Date亦回傳true
 *
 * Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/isDate.test.mjs Github}
 * @memberOf wsemi
 * @param {*} v 輸入任意資料
 * @param {Object} [opt={}] 輸入設定物件,預設{}
 * @param {Boolean} [opt.onlyCheckDateObject=false] 輸入是否僅判斷是否為Date物件布林值,若為true則以Object.prototype.toString.call(v)==='[object Date]'判斷,預設false
 * @returns {Boolean} 回傳判斷布林值
 * @example
 *
 * console.log(isDate('2019-01-01', { onlyCheckDateObject: true }))
 * // => false
 *
 * console.log(isDate(new Date('2019-01-01'), { onlyCheckDateObject: true }))
 * // => true
 *
 * console.log(isDate(new Date('x'), { onlyCheckDateObject: true }))
 * // => true (無效日期亦為Date物件)
 *
 * let c
 *
 * c = '2019-01-01T12:34:56:7891+08:00'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56:7891+08:00 false Invalid Date
 *
 * c = '2019-01-01T12:34:56.7891+08:00'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56.7891+08:00 true 2019-01-01T04:34:56.789Z
 *
 * c = '2019-01-01T12:34:56:789+08:00'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56:789+08:00 false Invalid Date
 *
 * c = '2019-01-01T12:34:56.789+08:00'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56.789+08:00 true 2019-01-01T04:34:56.789Z
 *
 * c = '2019-01-01T12:34:56:78+08:00'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56:78+08:00 false Invalid Date
 *
 * c = '2019-01-01T12:34:56.78+08:00'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56.78+08:00 true 2019-01-01T04:34:56.780Z
 *
 * c = '2019-01-01T12:34:56+08:00'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56+08:00 true 2019-01-01T04:34:56.000Z
 *
 * c = '2019-01-01T12:34+08:00'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34+08:00 true 2019-01-01T04:34:00.000Z
 *
 * c = '2019-01-01T12+08:00'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12+08:00 false Invalid Date
 *
 * c = '2019-01-01+08:00'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01+08:00 false Invalid Date
 *
 * c = '2019-01+08:00'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01+08:00 false Invalid Date
 *
 * c = '2019+08:00'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019+08:00 false Invalid Date
 *
 * c = '2019-01-01T12:34:56:7891Z'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56:7891Z false Invalid Date
 *
 * c = '2019-01-01T12:34:56.7891Z'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56.7891Z true 2019-01-01T12:34:56.789Z
 *
 * c = '2019-01-01T12:34:56:789Z'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56.789Z true 2019-01-01T12:34:56.789Z
 *
 * c = '2019-01-01T12:34:56.789Z'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56:789Z false Invalid Date
 *
 * c = '2019-01-01T12:34:56:78Z'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56:78Z false Invalid Date
 *
 * c = '2019-01-01T12:34:56.78Z'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56.78Z true 2019-01-01T12:34:56.780Z
 *
 * c = '2019-01-01T12:34:56Z'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56Z true 2019-01-01T12:34:56.000Z
 *
 * c = '2019-01-01T12:34Z'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34Z true 2019-01-01T12:34:00.000Z
 *
 * c = '2019-01-01T12Z'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12Z false Invalid Date
 *
 * c = '2019-01-01Z'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01Z true 2019-01-01T00:00:00.000Z
 *
 * c = '2019-01Z'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01Z true 2019-01-01T00:00:00.000Z
 *
 * c = '2019Z'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019Z true 2019-01-01T00:00:00.000Z
 *
 * c = '2019-01-01T12:34:56:7891'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56:7891 false Invalid Date
 *
 * c = '2019-01-01T12:34:56.7891'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56.7891 true 2019-01-01T04:34:56.789Z
 *
 * c = '2019-01-01T12:34:56:789'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56:789 false Invalid Date
 *
 * c = '2019-01-01T12:34:56.789'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56.789 true 2019-01-01T04:34:56.789Z
 *
 * c = '2019-01-01T12:34:56:78'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56:78 false Invalid Date
 *
 * c = '2019-01-01T12:34:56.78'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56.78 true 2019-01-01T04:34:56.780Z
 *
 * c = '2019-01-01T12:34:56'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56 true 2019-01-01T04:34:56.000Z
 *
 * c = '2019-01-01T12:34'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34 true 2019-01-01T04:34:00.000Z
 *
 * c = '2019-01-01T12'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12 false Invalid Date
 *
 * c = '2019-01-01'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01 true 2019-01-01T00:00:00.000Z
 *
 * c = '2019-01'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01 true 2019-01-01T00:00:00.000Z
 *
 * c = '2019'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019 true 2019-01-01T00:00:00.000Z
 *
 * c = '2019-01-01T12:34:56A'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56A false Invalid Date
 *
 * c = '1256'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56:789+08:00 false Invalid Date
 *
 * c = '1.25'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56:789+08:00 false Invalid Date
 *
 * c = '-1.25'
 * console.log(c, isDate(c), new Date(c))
 * // => 2019-01-01T12:34:56:789+08:00 false Invalid Date
 *
 */
function isDate(v, opt = {}) {

    //onlyCheckDateObject
    let onlyCheckDateObject = get(opt, 'onlyCheckDateObject', null)
    if (!isbol(onlyCheckDateObject)) {
        onlyCheckDateObject = false
    }

    //onlyCheckDateObject, 僅判斷是否為Date物件, 不解析字串與數值
    if (onlyCheckDateObject) {
        return Object.prototype.toString.call(v) === '[object Date]'
    }

    let t = v
    if (isestr(v)) {
        t = new Date(v)
    }
    if (isnum(v)) {
        t = cdbl(v)
        t = new Date(v)
    }
    return t instanceof Date && !isNaN(t)
}


export default isDate