formatTime.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. import dayjs from 'dayjs'
  2. import type { TableColumnCtx } from 'element-plus'
  3. /**
  4. * 日期快捷选项适用于 el-date-picker
  5. */
  6. export const defaultShortcuts = [
  7. {
  8. text: '今天',
  9. value: () => {
  10. return new Date()
  11. }
  12. },
  13. {
  14. text: '昨天',
  15. value: () => {
  16. const date = new Date()
  17. date.setTime(date.getTime() - 3600 * 1000 * 24)
  18. return [date, date]
  19. }
  20. },
  21. {
  22. text: '最近七天',
  23. value: () => {
  24. const date = new Date()
  25. date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
  26. return [date, new Date()]
  27. }
  28. },
  29. {
  30. text: '最近 30 天',
  31. value: () => {
  32. const date = new Date()
  33. date.setTime(date.getTime() - 3600 * 1000 * 24 * 30)
  34. return [date, new Date()]
  35. }
  36. },
  37. {
  38. text: '本月',
  39. value: () => {
  40. const date = new Date()
  41. date.setDate(1) // 设置为当前月的第一天
  42. return [date, new Date()]
  43. }
  44. },
  45. {
  46. text: '今年',
  47. value: () => {
  48. const date = new Date()
  49. return [new Date(`${date.getFullYear()}-01-01`), date]
  50. }
  51. }
  52. ]
  53. /**
  54. * 时间日期转换
  55. * @param date 当前时间,new Date() 格式
  56. * @param format 需要转换的时间格式字符串
  57. * @description format 字符串随意,如 `YYYY-MM、YYYY-MM-DD`
  58. * @description format 季度:"YYYY-MM-DD HH:mm:ss QQQQ"
  59. * @description format 星期:"YYYY-MM-DD HH:mm:ss WWW"
  60. * @description format 几周:"YYYY-MM-DD HH:mm:ss ZZZ"
  61. * @description format 季度 + 星期 + 几周:"YYYY-MM-DD HH:mm:ss WWW QQQQ ZZZ"
  62. * @returns 返回拼接后的时间字符串
  63. */
  64. export function formatDate(date: Date, format?: string): string {
  65. // 日期不存在,则返回空
  66. if (!date) {
  67. return ''
  68. }
  69. // 日期存在,则进行格式化
  70. return date ? dayjs(date).format(format ?? 'YYYY-MM-DD HH:mm:ss') : ''
  71. }
  72. /**
  73. * 后端时间展示:支持秒/毫秒时间戳、纯数字字符串、Date、可解析的日期字符串
  74. * @param value 秒级时间戳(10 位左右)、毫秒时间戳、或其它可解析值
  75. * @param pattern dayjs 格式,默认 YYYY-MM-DD HH:mm:ss
  76. */
  77. export function formatBackendDateTime(value: unknown, pattern = 'YYYY-MM-DD HH:mm:ss'): string {
  78. if (value == null || value === '') return ''
  79. if (value instanceof Date) {
  80. const d = dayjs(value)
  81. return d.isValid() ? d.format(pattern) : ''
  82. }
  83. if (typeof value === 'number' && Number.isFinite(value)) {
  84. const ms = value < 1e12 ? value * 1000 : value
  85. const d = dayjs(ms)
  86. return d.isValid() ? d.format(pattern) : ''
  87. }
  88. const s = String(value).trim()
  89. if (!s) return ''
  90. if (/^\d+$/.test(s)) {
  91. const n = Number(s)
  92. const ms = n < 1e12 ? n * 1000 : n
  93. const d = dayjs(ms)
  94. return d.isValid() ? d.format(pattern) : ''
  95. }
  96. const d = dayjs(s)
  97. return d.isValid() ? d.format(pattern) : ''
  98. }
  99. /**
  100. * 获取当前的日期+时间
  101. */
  102. export function getNowDateTime() {
  103. return dayjs()
  104. }
  105. /**
  106. * 获取当前日期是第几周
  107. * @param dateTime 当前传入的日期值
  108. * @returns 返回第几周数字值
  109. */
  110. export function getWeek(dateTime: Date): number {
  111. const temptTime = new Date(dateTime.getTime())
  112. // 周几
  113. const weekday = temptTime.getDay() || 7
  114. // 周1+5天=周六
  115. temptTime.setDate(temptTime.getDate() - weekday + 1 + 5)
  116. let firstDay = new Date(temptTime.getFullYear(), 0, 1)
  117. const dayOfWeek = firstDay.getDay()
  118. let spendDay = 1
  119. if (dayOfWeek != 0) spendDay = 7 - dayOfWeek + 1
  120. firstDay = new Date(temptTime.getFullYear(), 0, 1 + spendDay)
  121. const d = Math.ceil((temptTime.valueOf() - firstDay.valueOf()) / 86400000)
  122. return Math.ceil(d / 7)
  123. }
  124. /**
  125. * 将时间转换为 `几秒前`、`几分钟前`、`几小时前`、`几天前`
  126. * @param param 当前时间,new Date() 格式或者字符串时间格式
  127. * @param format 需要转换的时间格式字符串
  128. * @description param 10秒: 10 * 1000
  129. * @description param 1分: 60 * 1000
  130. * @description param 1小时: 60 * 60 * 1000
  131. * @description param 24小时:60 * 60 * 24 * 1000
  132. * @description param 3天: 60 * 60* 24 * 1000 * 3
  133. * @returns 返回拼接后的时间字符串
  134. */
  135. export function formatPast(param: string | Date, format = 'YYYY-MM-DD HH:mm:ss'): string {
  136. // 传入格式处理、存储转换值
  137. let t: any, s: number
  138. // 获取js 时间戳
  139. let time: number = new Date().getTime()
  140. // 是否是对象
  141. typeof param === 'string' || 'object' ? (t = new Date(param).getTime()) : (t = param)
  142. // 当前时间戳 - 传入时间戳
  143. time = Number.parseInt(`${time - t}`)
  144. if (time < 10000) {
  145. // 10秒内
  146. return '刚刚'
  147. } else if (time < 60000 && time >= 10000) {
  148. // 超过10秒少于1分钟内
  149. s = Math.floor(time / 1000)
  150. return `${s}秒前`
  151. } else if (time < 3600000 && time >= 60000) {
  152. // 超过1分钟少于1小时
  153. s = Math.floor(time / 60000)
  154. return `${s}分钟前`
  155. } else if (time < 86400000 && time >= 3600000) {
  156. // 超过1小时少于24小时
  157. s = Math.floor(time / 3600000)
  158. return `${s}小时前`
  159. } else if (time < 259200000 && time >= 86400000) {
  160. // 超过1天少于3天内
  161. s = Math.floor(time / 86400000)
  162. return `${s}天前`
  163. } else {
  164. // 超过3天
  165. const date = typeof param === 'string' || 'object' ? new Date(param) : param
  166. return formatDate(date, format)
  167. }
  168. }
  169. /**
  170. * 时间问候语
  171. * @param param 当前时间,new Date() 格式
  172. * @description param 调用 `formatAxis(new Date())` 输出 `上午好`
  173. * @returns 返回拼接后的时间字符串
  174. */
  175. export function formatAxis(param: Date): string {
  176. const hour: number = new Date(param).getHours()
  177. if (hour < 6) return '凌晨好'
  178. else if (hour < 9) return '早上好'
  179. else if (hour < 12) return '上午好'
  180. else if (hour < 14) return '中午好'
  181. else if (hour < 17) return '下午好'
  182. else if (hour < 19) return '傍晚好'
  183. else if (hour < 22) return '晚上好'
  184. else return '夜里好'
  185. }
  186. /**
  187. * 将毫秒,转换成时间字符串。例如说,xx 分钟
  188. *
  189. * @param ms 毫秒
  190. * @returns {string} 字符串
  191. */
  192. export function formatPast2(ms: number): string {
  193. const day = Math.floor(ms / (24 * 60 * 60 * 1000))
  194. const hour = Math.floor(ms / (60 * 60 * 1000) - day * 24)
  195. const minute = Math.floor(ms / (60 * 1000) - day * 24 * 60 - hour * 60)
  196. const second = Math.floor(ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60)
  197. if (day > 0) {
  198. return day + ' 天' + hour + ' 小时 ' + minute + ' 分钟'
  199. }
  200. if (hour > 0) {
  201. return hour + ' 小时 ' + minute + ' 分钟'
  202. }
  203. if (minute > 0) {
  204. return minute + ' 分钟'
  205. }
  206. if (second > 0) {
  207. return second + ' 秒'
  208. } else {
  209. return 0 + ' 秒'
  210. }
  211. }
  212. /**
  213. * element plus 的时间 Formatter 实现,使用 YYYY-MM-DD HH:mm:ss 格式
  214. *
  215. * @param row 行数据
  216. * @param column 字段
  217. * @param cellValue 字段值
  218. */
  219. export function dateFormatter(_row: any, _column: TableColumnCtx<any>, cellValue: any): string {
  220. return formatBackendDateTime(cellValue)
  221. }
  222. /**
  223. * element plus 的时间 Formatter 实现,使用 YYYY-MM-DD 格式
  224. *
  225. * @param row 行数据
  226. * @param column 字段
  227. * @param cellValue 字段值
  228. */
  229. export function dateFormatter2(_row: any, _column: TableColumnCtx<any>, cellValue: any): string {
  230. return formatBackendDateTime(cellValue, 'YYYY-MM-DD')
  231. }
  232. /**
  233. * 设置起始日期,时间为00:00:00
  234. * @param param 传入日期
  235. * @returns 带时间00:00:00的日期
  236. */
  237. export function beginOfDay(param: Date): Date {
  238. return new Date(param.getFullYear(), param.getMonth(), param.getDate(), 0, 0, 0)
  239. }
  240. /**
  241. * 设置结束日期,时间为23:59:59
  242. * @param param 传入日期
  243. * @returns 带时间23:59:59的日期
  244. */
  245. export function endOfDay(param: Date): Date {
  246. return new Date(param.getFullYear(), param.getMonth(), param.getDate(), 23, 59, 59)
  247. }
  248. /**
  249. * 计算两个日期间隔天数
  250. * @param param1 日期1
  251. * @param param2 日期2
  252. */
  253. export function betweenDay(param1: Date, param2: Date): number {
  254. param1 = convertDate(param1)
  255. param2 = convertDate(param2)
  256. // 计算差值
  257. return Math.floor((param2.getTime() - param1.getTime()) / (24 * 3600 * 1000))
  258. }
  259. /**
  260. * 日期计算
  261. * @param param1 日期
  262. * @param param2 添加的时间
  263. */
  264. export function addTime(param1: Date, param2: number): Date {
  265. param1 = convertDate(param1)
  266. return new Date(param1.getTime() + param2)
  267. }
  268. /**
  269. * 日期转换
  270. * @param param 日期
  271. */
  272. export function convertDate(param: Date | string): Date {
  273. if (typeof param === 'string') {
  274. return new Date(param)
  275. }
  276. return param
  277. }
  278. /**
  279. * 指定的两个日期, 是否为同一天
  280. * @param a 日期 A
  281. * @param b 日期 B
  282. */
  283. export function isSameDay(a: dayjs.ConfigType, b: dayjs.ConfigType): boolean {
  284. if (!a || !b) return false
  285. const aa = dayjs(a)
  286. const bb = dayjs(b)
  287. return aa.year() == bb.year() && aa.month() == bb.month() && aa.day() == bb.day()
  288. }
  289. /**
  290. * 获取一天的开始时间、截止时间
  291. * @param date 日期
  292. * @param days 天数
  293. */
  294. export function getDayRange(
  295. date: dayjs.ConfigType,
  296. days: number
  297. ): [dayjs.ConfigType, dayjs.ConfigType] {
  298. const day = dayjs(date).add(days, 'd')
  299. return getDateRange(day, day)
  300. }
  301. /**
  302. * 获取最近7天的开始时间、截止时间
  303. */
  304. export function getLast7Days(): [dayjs.ConfigType, dayjs.ConfigType] {
  305. const lastWeekDay = dayjs().subtract(7, 'd')
  306. const yesterday = dayjs().subtract(1, 'd')
  307. return getDateRange(lastWeekDay, yesterday)
  308. }
  309. /**
  310. * 获取最近30天的开始时间、截止时间
  311. */
  312. export function getLast30Days(): [dayjs.ConfigType, dayjs.ConfigType] {
  313. const lastMonthDay = dayjs().subtract(30, 'd')
  314. const yesterday = dayjs().subtract(1, 'd')
  315. return getDateRange(lastMonthDay, yesterday)
  316. }
  317. /**
  318. * 获取最近1年的开始时间、截止时间
  319. */
  320. export function getLast1Year(): [dayjs.ConfigType, dayjs.ConfigType] {
  321. const lastYearDay = dayjs().subtract(1, 'y')
  322. const yesterday = dayjs().subtract(1, 'd')
  323. return getDateRange(lastYearDay, yesterday)
  324. }
  325. /**
  326. * 获取指定日期的开始时间、截止时间
  327. * @param beginDate 开始日期
  328. * @param endDate 截止日期
  329. */
  330. export function getDateRange(
  331. beginDate: dayjs.ConfigType,
  332. endDate: dayjs.ConfigType
  333. ): [string, string] {
  334. return [
  335. dayjs(beginDate).startOf('d').format('YYYY-MM-DD HH:mm:ss'),
  336. dayjs(endDate).endOf('d').format('YYYY-MM-DD HH:mm:ss')
  337. ]
  338. }