date.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /**
  2. * @class DateTime
  3. * @description 日期处理模块
  4. */
  5. module.exports = class DateTime {
  6. constructor() {
  7. //默认日期展示格式
  8. this.defaultDateFormat = 'Y-m-d H:i:s'
  9. //默认时区
  10. this.defaultTimezone = 8
  11. this.setTimeZone(this.defaultTimezone)
  12. }
  13. /**
  14. * 设置时区
  15. * @param {Number} timezone 时区
  16. */
  17. setTimeZone(timezone) {
  18. if (timezone) {
  19. this.timezone = parseInt(timezone)
  20. }
  21. return this
  22. }
  23. /**
  24. * 获取 Date对象
  25. * @param {Date|Time} time
  26. */
  27. getDateObj(time) {
  28. return time ? new Date(time) : new Date()
  29. }
  30. /**
  31. * 获取毫秒/秒级时间戳
  32. * @param {DateTime} datetime 日期 例:'2022-04-21 00:00:00'
  33. * @param {Boolean} showSenconds 是否显示为秒级时间戳
  34. */
  35. getTime(datetime, showSenconds) {
  36. let time = this.getDateObj(datetime).getTime()
  37. if (showSenconds) {
  38. time = Math.trunc(time / 1000)
  39. }
  40. return time
  41. }
  42. /**
  43. * 获取日期
  44. * @param {String} dateFormat 日期格式
  45. * @param {Time} time 时间戳
  46. */
  47. getDate(dateFormat, time) {
  48. return this.dateFormat(dateFormat, time)
  49. }
  50. /**
  51. * 获取日期在不同时区下的时间戳
  52. * @param {Date|Time}} time 日期或时间戳
  53. * @param {Object} timezone 时区
  54. */
  55. getTimeByTimeZone(time, timezone) {
  56. this.setTimeZone(timezone)
  57. const thisDate = time ? new Date(time) : new Date()
  58. const localTime = thisDate.getTime()
  59. const offset = thisDate.getTimezoneOffset()
  60. const utc = offset * 60000 + localTime
  61. return utc + (3600000 * this.timezone)
  62. }
  63. /**
  64. * 获取时间信息
  65. * @param {Time} time 时间戳
  66. * @param {Boolean} full 是否完整展示, 为true时小于10的位会自动补0
  67. */
  68. getTimeInfo(time, full = true) {
  69. time = this.getTimeByTimeZone(time)
  70. const date = this.getDateObj(time)
  71. const retData = {
  72. nYear: date.getFullYear(),
  73. nMonth: date.getMonth() + 1,
  74. nWeek: date.getDay() || 7,
  75. nDay: date.getDate(),
  76. nHour: date.getHours(),
  77. nMinutes: date.getMinutes(),
  78. nSeconds: date.getSeconds()
  79. }
  80. if (full) {
  81. for (const k in retData) {
  82. if (retData[k] < 10) {
  83. retData[k] = '0' + retData[k]
  84. }
  85. }
  86. }
  87. return retData
  88. }
  89. /**
  90. * 时间格式转换
  91. * @param {String} format 展示格式如:Y-m-d H:i:s
  92. * @param {Time} time 时间戳
  93. */
  94. dateFormat(format, time) {
  95. const timeInfo = this.getTimeInfo(time)
  96. format = format || this.defaultDateFormat
  97. let date = format
  98. if (format.indexOf('Y') > -1) {
  99. date = date.replace(/Y/, timeInfo.nYear)
  100. }
  101. if (format.indexOf('m') > -1) {
  102. date = date.replace(/m/, timeInfo.nMonth)
  103. }
  104. if (format.indexOf('d') > -1) {
  105. date = date.replace(/d/, timeInfo.nDay)
  106. }
  107. if (format.indexOf('H') > -1) {
  108. date = date.replace(/H/, timeInfo.nHour)
  109. }
  110. if (format.indexOf('i') > -1) {
  111. date = date.replace(/i/, timeInfo.nMinutes)
  112. }
  113. if (format.indexOf('s') > -1) {
  114. date = date.replace(/s/, timeInfo.nSeconds)
  115. }
  116. return date
  117. }
  118. /**
  119. * 获取utc格式时间
  120. * @param {Date|Time} datetime 日期或时间戳
  121. */
  122. getUTC(datetime) {
  123. return this.getDateObj(datetime).toUTCString()
  124. }
  125. /**
  126. * 获取ISO 格式时间
  127. * @param {Date|Time} datetime 日期或时间戳
  128. */
  129. getISO(datetime) {
  130. return this.getDateObj(datetime).toISOString()
  131. }
  132. /**
  133. * 获取两时间相差天数
  134. * @param {Time} time1 时间戳
  135. * @param {Time} time2 时间戳
  136. */
  137. getDiffDays(time1, time2) {
  138. if (!time1) {
  139. return false
  140. }
  141. time2 = time2 ? time2 : this.getTime()
  142. let diffTime = time2 - time1
  143. if (diffTime < 0) {
  144. diffTime = Math.abs(diffTime)
  145. }
  146. return Math.ceil(diffTime / 86400000)
  147. }
  148. /**
  149. * 字符串转时间戳
  150. * @param {Object} str 字符串类型的时间戳
  151. */
  152. strToTime(str) {
  153. if (Array.from(str).length === 10) {
  154. str += '000'
  155. }
  156. return this.getTime(parseInt(str))
  157. }
  158. /**
  159. * 根据设置的天数获取指定日期N天后(前)的时间戳
  160. * @param {Number} days 天数
  161. * @param {Date|Time} time 指定的日期或时间戳
  162. * @param {Boolean} getAll 是否获取完整时间戳,为 false 时返回指定日期初始时间戳(当天00:00:00的时间戳)
  163. */
  164. getTimeBySetDays(days, time, getAll = false) {
  165. const date = this.getDateObj(time)
  166. date.setDate(date.getDate() + days)
  167. let startTime = date.getTime()
  168. if (!getAll) {
  169. const realdate = this.getDate('Y-m-d 00:00:00', startTime)
  170. startTime = this.getTimeByDateAndTimezone(realdate)
  171. }
  172. return startTime
  173. }
  174. /**
  175. * 根据设置的小时数获取指定日期N小时后(前)的时间戳
  176. * @param {Number} hours 小时数
  177. * @param {Date|Time} time 指定的日期或时间戳
  178. * @param {Boolean} getAll 是否获取完整时间戳,为 false 时返回指定时间初始时间戳(该小时00:00的时间戳)
  179. */
  180. getTimeBySetHours(hours, time, getAll = false) {
  181. const date = this.getDateObj(time)
  182. date.setHours(date.getHours() + hours)
  183. let startTime = date.getTime()
  184. if (!getAll) {
  185. const realdate = this.getDate('Y-m-d H:00:00', startTime)
  186. startTime = this.getTimeByDateAndTimezone(realdate)
  187. }
  188. return startTime
  189. }
  190. /**
  191. * 根据设置的周数获取指定日期N周后(前)的时间戳
  192. * @param {Number} weeks 周数
  193. * @param {Date|Time} time 指定的日期或时间戳
  194. * @param {Boolean} getAll 是否获取完整时间戳,为 false 时返回指定日期初始时间戳(当天00:00:00的时间戳)
  195. */
  196. getTimeBySetWeek(weeks, time, getAll = false) {
  197. const date = this.getDateObj(time)
  198. const dateInfo = this.getTimeInfo(time)
  199. const day = dateInfo.nWeek
  200. const offsetDays = 1 - day
  201. weeks = weeks * 7 + offsetDays
  202. date.setDate(date.getDate() + weeks)
  203. let startTime = date.getTime()
  204. if (!getAll) {
  205. const realdate = this.getDate('Y-m-d 00:00:00', startTime)
  206. startTime = this.getTimeByDateAndTimezone(realdate)
  207. }
  208. return startTime
  209. }
  210. /**
  211. * 根据设置的月数获取指定日期N月后(前)的时间戳
  212. * @param {Number} monthes 月数
  213. * @param {Date|Time} time 指定的日期或时间戳
  214. * @param {Boolean} getAll 是否获取完整时间戳,为 false 时返回指定日期初始时间戳(当天00:00:00的时间戳)
  215. */
  216. getTimeBySetMonth(monthes, time, getAll = false) {
  217. const date = this.getDateObj(time)
  218. date.setMonth(date.getMonth() + monthes)
  219. let startTime = date.getTime()
  220. if (!getAll) {
  221. const realdate = this.getDate('Y-m-01 00:00:00', startTime)
  222. startTime = this.getTimeByDateAndTimezone(realdate)
  223. }
  224. return startTime
  225. }
  226. /**
  227. * 根据设置的季度数获取指定日期N个季度后(前)的时间戳
  228. * @param {Number} quarter 季度
  229. * @param {Date|Time} time 指定的日期或时间戳
  230. * @param {Boolean} getAll 是否获取完整时间戳,为 false 时返回指定日期初始时间戳(当天00:00:00的时间戳)
  231. */
  232. getTimeBySetQuarter(quarter, time, getAll = false) {
  233. const date = this.getDateObj(time)
  234. const dateInfo = this.getTimeInfo(time)
  235. date.setMonth(date.getMonth() + quarter * 3)
  236. const month = date.getMonth() + 1;
  237. let quarterN;
  238. let mm;
  239. if ([1,2,3].indexOf(month) > -1) {
  240. // 第1季度
  241. mm = "01";
  242. } else if ([4,5,6].indexOf(month) > -1) {
  243. // 第2季度
  244. mm = "04";
  245. } else if ([7,8,9].indexOf(month) > -1) {
  246. // 第3季度
  247. mm = "07";
  248. } else if ([10,11,12].indexOf(month) > -1) {
  249. // 第4季度
  250. mm = "10";
  251. }
  252. let yyyy = date.getFullYear();
  253. let startTime = date.getTime()
  254. if (!getAll) {
  255. const realdate = this.getDate(`${yyyy}-${mm}-01 00:00:00`, startTime)
  256. startTime = this.getTimeByDateAndTimezone(realdate)
  257. }
  258. return startTime
  259. }
  260. /**
  261. * 根据设置的年数获取指定日期N年后(前)的时间戳
  262. * @param {Number} year 月数
  263. * @param {Date|Time} time 指定的日期或时间戳
  264. * @param {Boolean} getAll 是否获取完整时间戳,为 false 时返回指定日期初始时间戳(当天00:00:00的时间戳)
  265. */
  266. getTimeBySetYear(year, time, getAll = false) {
  267. const date = this.getDateObj(time)
  268. date.setFullYear(date.getFullYear() + year)
  269. let startTime = date.getTime()
  270. if (!getAll) {
  271. const realdate = this.getDate('Y-01-01 00:00:00', startTime)
  272. startTime = this.getTimeByDateAndTimezone(realdate)
  273. }
  274. return startTime
  275. }
  276. /**
  277. * 根据时区获取指定时间的偏移时间
  278. * @param {Date|Time} 指定的日期或时间戳
  279. * @param {Number} timezone 时区
  280. */
  281. getTimeByDateAndTimezone(date, timezone) {
  282. if (!timezone) {
  283. timezone = this.timezone
  284. }
  285. const thisDate = this.getDateObj(date)
  286. const thisTime = thisDate.getTime()
  287. const offset = thisDate.getTimezoneOffset()
  288. const offsetTime = offset * 60000 + timezone * 3600000
  289. return thisTime - offsetTime
  290. }
  291. /**
  292. * 根据指定的时间类型获取时间范围
  293. * @param {String} type 时间类型 hour:小时 day:天 week:周 month:月
  294. * @param {Number} offset 时间的偏移量
  295. * @param {Date|Time} thistime 指定的日期或时间戳
  296. * @param {Boolean} getAll 是否获取完整时间戳,为 false 时返回指定日期初始时间戳(当天00:00:00的时间戳)
  297. */
  298. getTimeDimensionByType(type, offset = 0, thistime, getAll = false) {
  299. let startTime = 0
  300. let endTime = 0
  301. switch (type) {
  302. case 'hour': {
  303. startTime = this.getTimeBySetHours(offset, thistime, getAll)
  304. endTime = getAll ? startTime : startTime + 3599999
  305. break
  306. }
  307. case 'day': {
  308. startTime = this.getTimeBySetDays(offset, thistime, getAll)
  309. endTime = getAll ? startTime : startTime + 86399999
  310. break
  311. }
  312. case 'week': {
  313. startTime = this.getTimeBySetWeek(offset, thistime, getAll)
  314. endTime = getAll ? startTime + 86400000 * 6 : startTime + 86400000 * 6 + 86399999
  315. break
  316. }
  317. case 'month': {
  318. startTime = this.getTimeBySetMonth(offset, thistime, getAll)
  319. const date = this.getDateObj(this.getDate('Y-m-d H:i:s', startTime))
  320. const nextMonthFirstDayTime = new Date(date.getFullYear(), date.getMonth() + 1, 1).getTime()
  321. endTime = getAll ? nextMonthFirstDayTime - 86400000 : this.getTimeByDateAndTimezone(
  322. nextMonthFirstDayTime) - 1
  323. break
  324. }
  325. case 'quarter': {
  326. startTime = this.getTimeBySetQuarter(offset, thistime, getAll)
  327. const date = this.getDateObj(this.getDate('Y-m-d H:i:s', startTime))
  328. const nextMonthFirstDayTime = new Date(date.getFullYear(), date.getMonth() + 3, 1).getTime()
  329. endTime = getAll ? nextMonthFirstDayTime - 86400000 : this.getTimeByDateAndTimezone(
  330. nextMonthFirstDayTime) - 1
  331. break
  332. }
  333. case 'year': {
  334. startTime = this.getTimeBySetYear(offset, thistime, getAll)
  335. const date = this.getDateObj(this.getDate('Y-m-d H:i:s', startTime))
  336. const nextFirstDayTime = new Date(date.getFullYear() + 1, 0, 1).getTime()
  337. endTime = getAll ? nextFirstDayTime - 86400000 : this.getTimeByDateAndTimezone(
  338. nextFirstDayTime) - 1
  339. break
  340. }
  341. }
  342. return {
  343. startTime,
  344. endTime
  345. }
  346. }
  347. }