utils.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. import { computed } from 'vue'
  2. import dayjs from '../../dayjs'
  3. import { isArray, isFunction, padZero } from '../common/util'
  4. import { useTranslate } from '../composables/useTranslate'
  5. import type { CalendarDayType, CalendarItem, CalendarTimeFilter, CalendarType } from './types'
  6. const { translate } = useTranslate('calendar-view')
  7. const weeks = computed(() => {
  8. return [
  9. translate('weeks.sun'),
  10. translate('weeks.mon'),
  11. translate('weeks.tue'),
  12. translate('weeks.wed'),
  13. translate('weeks.thu'),
  14. translate('weeks.fri'),
  15. translate('weeks.sat')
  16. ]
  17. })
  18. /**
  19. * 比较两个时间的日期是否相等
  20. * @param {timestamp} date1
  21. * @param {timestamp} date2
  22. */
  23. export function compareDate(date1: number, date2: number | null) {
  24. const dateValue1 = new Date(date1)
  25. const dateValue2 = new Date(date2 || '')
  26. const year1 = dateValue1.getFullYear()
  27. const year2 = dateValue2.getFullYear()
  28. const month1 = dateValue1.getMonth()
  29. const month2 = dateValue2.getMonth()
  30. const day1 = dateValue1.getDate()
  31. const day2 = dateValue2.getDate()
  32. if (year1 === year2) {
  33. if (month1 === month2) {
  34. return day1 === day2 ? 0 : day1 > day2 ? 1 : -1
  35. }
  36. return month1 === month2 ? 0 : month1 > month2 ? 1 : -1
  37. }
  38. return year1 > year2 ? 1 : -1
  39. }
  40. /**
  41. * 判断是否是范围选择
  42. * @param {string} type
  43. */
  44. export function isRange(type: CalendarType) {
  45. return type.indexOf('range') > -1
  46. }
  47. /**
  48. * 比较两个日期的月份是否相等
  49. * @param {timestamp} date1
  50. * @param {timestamp} date2
  51. */
  52. export function compareMonth(date1: number, date2: number) {
  53. const dateValue1 = new Date(date1)
  54. const dateValue2 = new Date(date2)
  55. const year1 = dateValue1.getFullYear()
  56. const year2 = dateValue2.getFullYear()
  57. const month1 = dateValue1.getMonth()
  58. const month2 = dateValue2.getMonth()
  59. if (year1 === year2) {
  60. return month1 === month2 ? 0 : month1 > month2 ? 1 : -1
  61. }
  62. return year1 > year2 ? 1 : -1
  63. }
  64. /**
  65. * 比较两个日期的年份是否一致
  66. * @param {timestamp} date1
  67. * @param {timestamp} date2
  68. */
  69. export function compareYear(date1: number, date2: number) {
  70. const dateValue1 = new Date(date1)
  71. const dateValue2 = new Date(date2)
  72. const year1 = dateValue1.getFullYear()
  73. const year2 = dateValue2.getFullYear()
  74. return year1 === year2 ? 0 : year1 > year2 ? 1 : -1
  75. }
  76. /**
  77. * 获取一个月的最后一天
  78. * @param {number} year
  79. * @param {number} month
  80. */
  81. export function getMonthEndDay(year: number, month: number) {
  82. return 32 - new Date(year, month - 1, 32).getDate()
  83. }
  84. /**
  85. * 格式化年月
  86. * @param {timestamp} date
  87. */
  88. export function formatMonthTitle(date: number) {
  89. return dayjs(date).format(translate('monthTitle'))
  90. }
  91. /**
  92. * 根据下标获取星期
  93. * @param {number} index
  94. */
  95. export function getWeekLabel(index: number) {
  96. if (index >= 7) {
  97. index = index % 7
  98. }
  99. return weeks.value[index]
  100. }
  101. /**
  102. * 格式化年份
  103. * @param {timestamp} date
  104. */
  105. export function formatYearTitle(date: number) {
  106. return dayjs(date).format(translate('yearTitle'))
  107. }
  108. /**
  109. * 根据最小日期和最大日期获取这之间总共有几个月份
  110. * @param {timestamp} minDate
  111. * @param {timestamp} maxDate
  112. */
  113. export function getMonths(minDate: number, maxDate: number) {
  114. const months: number[] = []
  115. const month = new Date(minDate)
  116. month.setDate(1)
  117. while (compareMonth(month.getTime(), maxDate) < 1) {
  118. months.push(month.getTime())
  119. month.setMonth(month.getMonth() + 1)
  120. }
  121. return months
  122. }
  123. /**
  124. * 根据最小日期和最大日期获取这之间总共有几年
  125. * @param {timestamp} minDate
  126. * @param {timestamp} maxDate
  127. */
  128. export function getYears(minDate: number, maxDate: number) {
  129. const years: number[] = []
  130. const year = new Date(minDate)
  131. year.setMonth(0)
  132. year.setDate(1)
  133. while (compareYear(year.getTime(), maxDate) < 1) {
  134. years.push(year.getTime())
  135. year.setFullYear(year.getFullYear() + 1)
  136. }
  137. return years
  138. }
  139. /**
  140. * 获取一个日期所在周的第一天和最后一天
  141. * @param {timestamp} date
  142. */
  143. export function getWeekRange(date: number, firstDayOfWeek: number) {
  144. if (firstDayOfWeek >= 7) {
  145. firstDayOfWeek = firstDayOfWeek % 7
  146. }
  147. const dateValue = new Date(date)
  148. dateValue.setHours(0, 0, 0, 0)
  149. const year = dateValue.getFullYear()
  150. const month = dateValue.getMonth()
  151. const day = dateValue.getDate()
  152. const week = dateValue.getDay()
  153. const weekStart = new Date(year, month, day - ((7 + week - firstDayOfWeek) % 7))
  154. const weekEnd = new Date(year, month, day + 6 - ((7 + week - firstDayOfWeek) % 7))
  155. return [weekStart.getTime(), weekEnd.getTime()]
  156. }
  157. /**
  158. * 获取日期偏移量
  159. * @param {timestamp} date1
  160. * @param {timestamp} date2
  161. */
  162. export function getDayOffset(date1: number, date2: number) {
  163. return (date1 - date2) / (24 * 60 * 60 * 1000) + 1
  164. }
  165. /**
  166. * 获取偏移日期
  167. * @param {timestamp} date
  168. * @param {number} offset
  169. */
  170. export function getDayByOffset(date: number, offset: number) {
  171. const dateValue = new Date(date)
  172. dateValue.setDate(dateValue.getDate() + offset)
  173. return dateValue.getTime()
  174. }
  175. export const getPrevDay = (date: number) => getDayByOffset(date, -1)
  176. export const getNextDay = (date: number) => getDayByOffset(date, 1)
  177. /**
  178. * 获取月份偏移量
  179. * @param {timestamp} date1
  180. * @param {timestamp} date2
  181. */
  182. export function getMonthOffset(date1: number, date2: number) {
  183. const dateValue1 = new Date(date1)
  184. const dateValue2 = new Date(date2)
  185. const year1 = dateValue1.getFullYear()
  186. const year2 = dateValue2.getFullYear()
  187. let month1 = dateValue1.getMonth()
  188. const month2 = dateValue2.getMonth()
  189. month1 = (year1 - year2) * 12 + month1
  190. return month1 - month2 + 1
  191. }
  192. /**
  193. * 获取偏移月份
  194. * @param {timestamp} date
  195. * @param {number} offset
  196. */
  197. export function getMonthByOffset(date: number, offset: number) {
  198. const dateValue = new Date(date)
  199. dateValue.setMonth(dateValue.getMonth() + offset)
  200. return dateValue.getTime()
  201. }
  202. /**
  203. * 获取默认时间,格式化为数组
  204. * @param {array|string|null} defaultTime
  205. */
  206. export function getDefaultTime(defaultTime: string[] | string | null) {
  207. if (isArray(defaultTime)) {
  208. const startTime = (defaultTime[0] || '00:00:00').split(':').map((item: string) => {
  209. return parseInt(item)
  210. })
  211. const endTime = (defaultTime[1] || '00:00:00').split(':').map((item) => {
  212. return parseInt(item)
  213. })
  214. return [startTime, endTime]
  215. } else {
  216. const time = (defaultTime || '00:00:00').split(':').map((item) => {
  217. return parseInt(item)
  218. })
  219. return [time, time]
  220. }
  221. }
  222. /**
  223. * 根据默认时间获取日期
  224. * @param {timestamp} date
  225. * @param {array} defaultTime
  226. */
  227. export function getDateByDefaultTime(date: number, defaultTime: number[]) {
  228. const dateValue = new Date(date)
  229. dateValue.setHours(defaultTime[0])
  230. dateValue.setMinutes(defaultTime[1])
  231. dateValue.setSeconds(defaultTime[2])
  232. return dateValue.getTime()
  233. }
  234. /**
  235. * 获取经过 iteratee 格式化后的长度为 n 的数组
  236. * @param {number} n
  237. * @param {function} iteratee
  238. */
  239. const times = (n: number, iteratee: (index: number) => CalendarItem) => {
  240. let index: number = -1
  241. const result: CalendarItem[] = Array(n < 0 ? 0 : n)
  242. while (++index < n) {
  243. result[index] = iteratee(index)
  244. }
  245. return result
  246. }
  247. /**
  248. * 获取时分秒
  249. * @param {timestamp}} date
  250. */
  251. const getTime = (date: number) => {
  252. const dateValue = new Date(date)
  253. return [dateValue.getHours(), dateValue.getMinutes(), dateValue.getSeconds()]
  254. }
  255. /**
  256. * 根据最小最大日期获取时间数据,用于填入picker
  257. * @param {*} param0
  258. */
  259. export function getTimeData({
  260. date,
  261. minDate,
  262. maxDate,
  263. isHideSecond,
  264. filter
  265. }: {
  266. date: number
  267. minDate: number
  268. maxDate: number
  269. isHideSecond: boolean
  270. filter?: CalendarTimeFilter
  271. }) {
  272. const compareMin = compareDate(date, minDate)
  273. const compareMax = compareDate(date, maxDate)
  274. let minHour = 0
  275. let maxHour = 23
  276. let minMinute = 0
  277. let maxMinute = 59
  278. let minSecond = 0
  279. let maxSecond = 59
  280. if (compareMin === 0) {
  281. const minTime = getTime(minDate)
  282. const currentTime = getTime(date)
  283. minHour = minTime[0]
  284. if (minTime[0] === currentTime[0]) {
  285. minMinute = minTime[1]
  286. if (minTime[1] === currentTime[1]) {
  287. minSecond = minTime[2]
  288. }
  289. }
  290. }
  291. if (compareMax === 0) {
  292. const maxTime = getTime(maxDate)
  293. const currentTime = getTime(date)
  294. maxHour = maxTime[0]
  295. if (maxTime[0] === currentTime[0]) {
  296. maxMinute = maxTime[1]
  297. if (maxTime[1] === currentTime[1]) {
  298. maxSecond = maxTime[2]
  299. }
  300. }
  301. }
  302. let columns: CalendarItem[][] = []
  303. let hours = times(24, (index) => {
  304. return {
  305. label: translate('hour', padZero(index)),
  306. value: index,
  307. disabled: index < minHour || index > maxHour
  308. }
  309. })
  310. let minutes = times(60, (index) => {
  311. return {
  312. label: translate('minute', padZero(index)),
  313. value: index,
  314. disabled: index < minMinute || index > maxMinute
  315. }
  316. })
  317. let seconds: CalendarItem[] = []
  318. if (filter && isFunction(filter)) {
  319. hours = filter({
  320. type: 'hour',
  321. values: hours
  322. })
  323. minutes = filter({
  324. type: 'minute',
  325. values: minutes
  326. })
  327. }
  328. if (!isHideSecond) {
  329. seconds = times(60, (index) => {
  330. return {
  331. label: translate('second', padZero(index)),
  332. value: index,
  333. disabled: index < minSecond || index > maxSecond
  334. }
  335. })
  336. if (filter && isFunction(filter)) {
  337. seconds = filter({
  338. type: 'second',
  339. values: seconds
  340. })
  341. }
  342. }
  343. columns = isHideSecond ? [hours, minutes] : [hours, minutes, seconds]
  344. return columns
  345. }
  346. /**
  347. * 获取当前是第几周
  348. * @param {timestamp} date
  349. */
  350. export function getWeekNumber(date: number | Date) {
  351. date = new Date(date)
  352. date.setHours(0, 0, 0, 0)
  353. // Thursday in current week decides the year.
  354. date.setDate(date.getDate() + 3 - ((date.getDay() + 6) % 7))
  355. // January 4 is always in week 1.
  356. const week = new Date(date.getFullYear(), 0, 4)
  357. // Adjust to Thursday in week 1 and count number of weeks from date to week 1.
  358. // Rounding should be fine for Daylight Saving Time. Its shift should never be more than 12 hours.
  359. return 1 + Math.round(((date.getTime() - week.getTime()) / 86400000 - 3 + ((week.getDay() + 6) % 7)) / 7)
  360. }
  361. export function getItemClass(monthType: CalendarDayType, value: number | null | (number | null)[], type: CalendarType) {
  362. const classList = ['is-' + monthType]
  363. if (type.indexOf('range') > -1 && isArray(value)) {
  364. if (!value || !value[1]) {
  365. classList.push('is-without-end')
  366. }
  367. }
  368. return classList.join(' ')
  369. }