element3
Version:
A Component Library for Vue3
340 lines (292 loc) • 9.25 kB
JavaScript
import fecha from './date'
import { t } from '../locale'
const weeks = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']
const months = [
'jan',
'feb',
'mar',
'apr',
'may',
'jun',
'jul',
'aug',
'sep',
'oct',
'nov',
'dec'
]
const newArray = function (start, end) {
const result = []
for (let i = start; i <= end; i++) {
result.push(i)
}
return result
}
export const getI18nSettings = () => {
return {
dayNamesShort: weeks.map((week) => t(`el.datepicker.weeks.${week}`)),
dayNames: weeks.map((week) => t(`el.datepicker.weeks.${week}`)),
monthNamesShort: months.map((month) => t(`el.datepicker.months.${month}`)),
monthNames: months.map((month, index) =>
t(`el.datepicker.month${index + 1}`)
),
amPm: ['am', 'pm']
}
}
export const toDate = function (date) {
return isDate(date) ? new Date(date) : null
}
export const isDate = function (date) {
if (date === null || date === undefined) return false
if (isNaN(new Date(date).getTime())) return false
if (Array.isArray(date)) return false // deal with `new Date([ new Date() ]) -> new Date()`
return true
}
export const isDateObject = function (val) {
return val instanceof Date
}
export const formatDate = function (date, format) {
date = toDate(date)
if (!date) return ''
return fecha.format(date, format || 'yyyy-MM-dd', getI18nSettings())
}
export const parseDate = function (string, format) {
return fecha.parse(string, format || 'yyyy-MM-dd', getI18nSettings())
}
export const getDayCountOfMonth = function (year, month) {
if (month === 3 || month === 5 || month === 8 || month === 10) {
return 30
}
if (month === 1) {
if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
return 29
} else {
return 28
}
}
return 31
}
export const getDayCountOfYear = function (year) {
const isLeapYear = year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0)
return isLeapYear ? 366 : 365
}
export const getFirstDayOfMonth = function (date) {
const temp = new Date(date.getTime())
temp.setDate(1)
return temp.getDay()
}
// see: https://stackoverflow.com/questions/3674539/incrementing-a-date-in-javascript
// {prev, next} Date should work for Daylight Saving Time
// Adding 24 * 60 * 60 * 1000 does not work in the above scenario
export const prevDate = function (date, amount = 1) {
return new Date(date.getFullYear(), date.getMonth(), date.getDate() - amount)
}
export const nextDate = function (date, amount = 1) {
return new Date(date.getFullYear(), date.getMonth(), date.getDate() + amount)
}
export const getStartDateOfMonth = function (year, month) {
const result = new Date(year, month, 1)
const day = result.getDay()
if (day === 0) {
return prevDate(result, 7)
} else {
return prevDate(result, day)
}
}
export const getWeekNumber = function (src) {
if (!isDate(src)) return null
const date = new Date(src.getTime())
date.setHours(0, 0, 0, 0)
// Thursday in current week decides the year.
date.setDate(date.getDate() + 3 - ((date.getDay() + 6) % 7))
// January 4 is always in week 1.
const week1 = new Date(date.getFullYear(), 0, 4)
// Adjust to Thursday in week 1 and count number of weeks from date to week 1.
// Rounding should be fine for Daylight Saving Time. Its shift should never be more than 12 hours.
return (
1 +
Math.round(
((date.getTime() - week1.getTime()) / 86400000 -
3 +
((week1.getDay() + 6) % 7)) /
7
)
)
}
export const getRangeHours = function (ranges) {
const hours = []
let disabledHours = []
;(ranges || []).forEach((range) => {
const value = range.map((date) => date.getHours())
disabledHours = disabledHours.concat(newArray(value[0], value[1]))
})
if (disabledHours.length) {
for (let i = 0; i < 24; i++) {
hours[i] = disabledHours.indexOf(i) === -1
}
} else {
for (let i = 0; i < 24; i++) {
hours[i] = false
}
}
return hours
}
export const getPrevMonthLastDays = (date, amount) => {
if (amount <= 0) return []
const temp = new Date(date.getTime())
temp.setDate(0)
const lastDay = temp.getDate()
return range(amount).map((_, index) => lastDay - (amount - index - 1))
}
export const getMonthDays = (date) => {
const temp = new Date(date.getFullYear(), date.getMonth() + 1, 0)
const days = temp.getDate()
return range(days).map((_, index) => index + 1)
}
function setRangeData(arr, start, end, value) {
for (let i = start; i < end; i++) {
arr[i] = value
}
}
export const getRangeMinutes = function (ranges, hour) {
const minutes = new Array(60)
if (ranges.length > 0) {
ranges.forEach((range) => {
const start = range[0]
const end = range[1]
const startHour = start.getHours()
const startMinute = start.getMinutes()
const endHour = end.getHours()
const endMinute = end.getMinutes()
if (startHour === hour && endHour !== hour) {
setRangeData(minutes, startMinute, 60, true)
} else if (startHour === hour && endHour === hour) {
setRangeData(minutes, startMinute, endMinute + 1, true)
} else if (startHour !== hour && endHour === hour) {
setRangeData(minutes, 0, endMinute + 1, true)
} else if (startHour < hour && endHour > hour) {
setRangeData(minutes, 0, 60, true)
}
})
} else {
setRangeData(minutes, 0, 60, true)
}
return minutes
}
export const range = function (n) {
// see https://stackoverflow.com/questions/3746725/create-a-javascript-array-containing-1-n
return Array.apply(null, { length: n }).map((_, n) => n)
}
export const modifyDate = function (date, y, m, d) {
return new Date(
y,
m,
d,
date.getHours(),
date.getMinutes(),
date.getSeconds(),
date.getMilliseconds()
)
}
export const modifyTime = function (date, h, m, s) {
return new Date(
date.getFullYear(),
date.getMonth(),
date.getDate(),
h,
m,
s,
date.getMilliseconds()
)
}
export const modifyWithTimeString = (date, time) => {
if (date == null || !time) {
return date
}
time = parseDate(time, 'HH:mm:ss')
return modifyTime(date, time.getHours(), time.getMinutes(), time.getSeconds())
}
export const clearTime = function (date) {
return new Date(date.getFullYear(), date.getMonth(), date.getDate())
}
export const clearMilliseconds = function (date) {
return new Date(
date.getFullYear(),
date.getMonth(),
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
0
)
}
export const limitTimeRange = function (date, ranges, format = 'HH:mm:ss') {
// TODO: refactory a more elegant solution
if (ranges.length === 0) return date
const normalizeDate = (date) =>
fecha.parse(fecha.format(date, format), format)
const ndate = normalizeDate(date)
const nranges = ranges.map((range) => range.map(normalizeDate))
if (nranges.some((nrange) => ndate >= nrange[0] && ndate <= nrange[1]))
return date
let minDate = nranges[0][0]
let maxDate = nranges[0][0]
nranges.forEach((nrange) => {
minDate = new Date(Math.min(nrange[0], minDate))
maxDate = new Date(Math.max(nrange[1], minDate))
})
const ret = ndate < minDate ? minDate : maxDate
// preserve Year/Month/Date
return modifyDate(ret, date.getFullYear(), date.getMonth(), date.getDate())
}
export const timeWithinRange = function (date, selectableRange, format) {
const limitedDate = limitTimeRange(date, selectableRange, format)
return limitedDate.getTime() === date.getTime()
}
export const changeYearMonthAndClampDate = function (date, year, month) {
// clamp date to the number of days in `year`, `month`
// eg: (2010-1-31, 2010, 2) => 2010-2-28
const monthDate = Math.min(date.getDate(), getDayCountOfMonth(year, month))
return modifyDate(date, year, month, monthDate)
}
export const prevMonth = function (date) {
const year = date.getFullYear()
const month = date.getMonth()
return month === 0
? changeYearMonthAndClampDate(date, year - 1, 11)
: changeYearMonthAndClampDate(date, year, month - 1)
}
export const nextMonth = function (date) {
const year = date.getFullYear()
const month = date.getMonth()
return month === 11
? changeYearMonthAndClampDate(date, year + 1, 0)
: changeYearMonthAndClampDate(date, year, month + 1)
}
export const prevYear = function (date, amount = 1) {
const year = date.getFullYear()
const month = date.getMonth()
return changeYearMonthAndClampDate(date, year - amount, month)
}
export const nextYear = function (date, amount = 1) {
const year = date.getFullYear()
const month = date.getMonth()
return changeYearMonthAndClampDate(date, year + amount, month)
}
export const extractDateFormat = function (format) {
return format
.replace(/\W?m{1,2}|\W?ZZ/g, '')
.replace(/\W?h{1,2}|\W?s{1,3}|\W?a/gi, '')
.trim()
}
export const extractTimeFormat = function (format) {
return format
.replace(/\W?D{1,2}|\W?Do|\W?d{1,4}|\W?M{1,4}|\W?y{2,4}/g, '')
.trim()
}
export const validateRangeInOneMonth = function (start, end) {
return (
start.getMonth() === end.getMonth() &&
start.getFullYear() === end.getFullYear()
)
}