├── .gitignore ├── LICENSE ├── README.md ├── index.js ├── package.json └── tools ├── ajaxBox └── index.js ├── browserBox └── index.js ├── dataBox └── index.js ├── eventBox └── index.js ├── matchBox └── index.js ├── numberBox └── index.js ├── storeBox └── index.js ├── stringBox └── index.js └── timeBox └── index.js /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsToolBigBox/js-tool-big-box/8d05fab74a1cf399587afbefc247f6cd6f3dbc44/.gitignore -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 bigDog 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 学习文档 2 | 3 | ``` 4 | https://blog.csdn.net/xingyu_qie/category_12644939.html 5 | ``` 6 | 7 | ## 联系作者 8 | 9 | ``` 10 | https://blog.csdn.net/xingyu_qie 11 | ``` 12 | 13 | ## 《简历宝典》免费学 14 | 15 | ``` 16 | https://blog.csdn.net/xingyu_qie/category_12720425.html 17 | ``` 18 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import timeBox from './tools/timeBox/index.js'; 2 | import storeBox from './tools/storeBox/index.js'; 3 | import eventBox from './tools/eventBox/index.js'; 4 | import numberBox from './tools/numberBox/index.js'; 5 | import stringBox from './tools/stringBox/index.js'; 6 | import matchBox from './tools/matchBox/index.js'; 7 | import ajaxBox from './tools/ajaxBox/index.js'; 8 | import dataBox from './tools/dataBox/index.js'; 9 | import browserBox from './tools/browserBox/index.js'; 10 | 11 | export{ 12 | timeBox, 13 | storeBox, 14 | eventBox, 15 | numberBox, 16 | stringBox, 17 | matchBox, 18 | ajaxBox, 19 | dataBox, 20 | browserBox, 21 | } ; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-tool-big-box", 3 | "version": "1.0.53", 4 | "description": "", 5 | "keywords": [ 6 | "time", 7 | "date", 8 | "datetime", 9 | "cookie", 10 | "localStorage", 11 | "debounce", 12 | "throttle", 13 | "string", 14 | "number", 15 | "match", 16 | "jsonp", 17 | "data" 18 | ], 19 | "repository": "jsToolBigBox/js-tool-big-box", 20 | "main": "index.js", 21 | "type": "module", 22 | "scripts": { 23 | "test": "echo \"Error: no test specified\" && exit 1" 24 | }, 25 | "author": "经海路大白狗", 26 | "license": "MIT" 27 | } 28 | -------------------------------------------------------------------------------- /tools/ajaxBox/index.js: -------------------------------------------------------------------------------- 1 | const downFileFn = function(blob, fileName) { 2 | const a = document.createElement('a'); 3 | document.body.appendChild(a) 4 | a.style.display = 'none' 5 | const url = window.URL.createObjectURL(blob); 6 | a.href = url; 7 | a.download = fileName; 8 | a.click(); 9 | document.body.removeChild(a) 10 | window.URL.revokeObjectURL(url); 11 | } 12 | const ajaxBox = { 13 | sendJSONP: function(url, callbackName, callback) { 14 | const script = document.createElement('script'); 15 | // 设置script元素的src属性,拼接callback参数 16 | script.src = `${url}?callback=${callbackName}`; 17 | // 将script元素添加到页面中 18 | document.body.appendChild(script); 19 | // 定义全局的回调函数,用于接收JSONP响应 20 | window[callbackName] = function(data) { 21 | // 执行传入的回调函数,并将JSONP响应作为参数传递 22 | callback(data); 23 | // 执行完毕后移除script元素 24 | document.body.removeChild(script); 25 | // 删除全局的回调函数 26 | delete window[callbackName]; 27 | }; 28 | }, 29 | downFile: function(blob, fileName) { 30 | downFileFn(blob, fileName); 31 | }, 32 | downFileFetch: function(fillAddress, fileName, method, headers, params) { 33 | let options = { 34 | method: method || 'GET', 35 | } 36 | if (headers) { 37 | options['headers'] = headers; 38 | } 39 | if ((method === 'post' || method === 'POST') && params) { 40 | options['body'] = JSON.stringify(params) 41 | } 42 | fetch(fillAddress, options).then(res => res.blob()).then((blob) => { 43 | downFileFn(blob, fileName); 44 | }); 45 | } 46 | } 47 | export default ajaxBox; -------------------------------------------------------------------------------- /tools/browserBox/index.js: -------------------------------------------------------------------------------- 1 | const browserBox = { 2 | isMobileBrowser: function() { 3 | if ( 4 | window.navigator.userAgent.match( 5 | /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i, 6 | ) 7 | ) { 8 | return true; // 移动端 9 | } else { 10 | return false; // PC端 11 | } 12 | }, 13 | isElementInViewport: function(element) { 14 | const eleDom = document.querySelector(element); 15 | const rect = eleDom.getBoundingClientRect(); 16 | return ( 17 | rect.top >= 0 && 18 | rect.left >= 0 && 19 | rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && 20 | rect.right <= (window.innerWidth || document.documentElement.clientWidth) 21 | ); 22 | }, 23 | getScrollInfo: function(lastScrollTop) { 24 | let scrollTop = window.pageYOffset || document.documentElement.scrollTop; 25 | let windowHeight = window.innerHeight; 26 | let documentHeight = document.documentElement.scrollHeight; 27 | let scrollDirection = ''; 28 | // 判断滚动方向 29 | if (scrollTop > lastScrollTop){ 30 | scrollDirection = 'down'; 31 | } else { 32 | scrollDirection = 'up'; 33 | } 34 | // 判断距离顶部的距离 35 | lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; 36 | // 判断距离底部的距离 37 | let scrollBottom = scrollTop + windowHeight - documentHeight; 38 | 39 | return { 40 | scrollDirection, // 滚动方向 41 | lastScrollTop, // 距离顶部的距离 42 | scrollBottom, // 距离底部的距离 43 | } 44 | }, 45 | fullScreen: function(fullSwitch) { 46 | if (fullSwitch) { 47 | let element = document.documentElement; 48 | if (element.requestFullscreen) { 49 | element.requestFullscreen(); 50 | } else if (element.msRequestFullscreen) { 51 | element.msRequestFullscreen(); 52 | } else if (element.mozRequestFullScreen) { 53 | element.mozRequestFullScreen(); 54 | } else if (element.webkitRequestFullscreen) { 55 | element.webkitRequestFullscreen(); 56 | } 57 | } else { 58 | if (document.exitFullscreen) { 59 | document.exitFullscreen(); 60 | } else if (document.msExitFullscreen) { 61 | document.msExitFullscreen(); 62 | } else if (document.mozCancelFullScreen) { 63 | document.mozCancelFullScreen(); 64 | } else if (document.webkitExitFullscreen) { 65 | document.webkitExitFullscreen(); 66 | } 67 | } 68 | }, 69 | getBrowserInfo: function() { 70 | const info = { 71 | name: 'other', 72 | version: '0', 73 | ua: navigator.userAgent, 74 | } 75 | const browserData = [["WeiXin", /micromessenger\/([^\s]+)/], ["QQ", /qq\/([^\s]+)/], ["QQBrowser", /(?:qqbrowser|qqlivebrowser)\/([^\s]+)/], ["QIHU", /qihu|360se/], ["LieBao", /(?:lbbrowser|liebaofast)\/?([\d\.]+)?/], ["Sogou", /(?:metasr|sogou[\w]*)[ \/]([\d\.]+)/], ["Opera", /(?:opera|opr|oupeng)\/([\d\.]+)/], ["BaiduBrowser", /(?:bidubrowser|baidubrowser)[\/ ]?([\d\.\w]+)/], ["BaiduBox", /baiduboxapp|baiduboxpad/], ["UC", /(?:ucweb|ucbrowser)\/?([\d\.]+)/], ["Maxthon", /maxthon\/([\d\.]+)/], ["Samsung", /samsungbrowser\/([\d\.]+)/], ["Dolphin", /aphone|apad/], ["2345", /2345/], ["Miui", /miuibrowser\/([\d\.]+)/], ["OppoBrowser", /oppobrowser\/([\d\.]+)/], ["MeiZu", /mz-/], ["Weibo", /weibo/], ["Youku", /youku/], ["NewsApp", /newsapp/], ["AliApp", /aliapp/], ["Firefox", /firefox\/([\d\.\w]+)/], ["Edge", /edg\/([\d\.]+)/], ["Chrome", /chrome\/([\d\.]+)/], ["IE", /msie[ ](\d+\.\d+)/], ["Safari", /safari\/([\d\.]+)/]]; 76 | const uaLower = navigator.userAgent.toLowerCase(); 77 | let rName = null; 78 | 79 | for (let i=0;i { 20 | callback && callback(); 21 | }) 22 | .catch(err => { 23 | errorCallback && errorCallback(); 24 | }); 25 | }, 26 | uniqueArray: function(arr) { 27 | return arr.filter((value, index, self) => { 28 | return self.indexOf(value) === index; 29 | }); 30 | }, 31 | getDataType: function(value) { 32 | return Object.prototype.toString.call(value); 33 | }, 34 | sortArrayNum: function(arr, type) { 35 | let n = arr.length; 36 | for (let i = 0; i < n - 1; i++) { 37 | for (let j = 0; j < n - 1 - i; j++) { 38 | if (arr[j] > arr[j + 1]) { 39 | // 交换元素 40 | [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; 41 | } 42 | } 43 | } 44 | return type ? arr.reverse() : arr; 45 | }, 46 | sortByNumber: function(arr, attr, sortType) { 47 | if (Object.prototype.toString.call(arr[0][attr]) === '[object Number]') { 48 | let sortArr = arr.sort((a, b) => a[attr] - b[attr]); 49 | return sortType ? sortArr.reverse() : sortArr; 50 | } 51 | return arr; 52 | }, 53 | sortByletter: function(arr, attr, sortType) { 54 | let sortArr = arr.sort((a, b) => a[attr].localeCompare(b[attr], 'zh-Hans-CN')); 55 | return sortType ? sortArr.reverse() : sortArr; 56 | }, 57 | sortByTime: function(arr, attr, sortType) { 58 | const newDate = new Date(arr[0][attr]); 59 | if (Object.prototype.toString.call(newDate) === '[object Date]') { 60 | let sortArr = arr.sort((a, b) => new Date(a[attr]) - new Date(b[attr])); 61 | return sortType ? sortArr.reverse() : sortArr; 62 | } 63 | return arr; 64 | } 65 | } 66 | export default dataBox; -------------------------------------------------------------------------------- /tools/eventBox/index.js: -------------------------------------------------------------------------------- 1 | const eventBox = { 2 | debounce: function(func, delay) { 3 | delay = delay || 300; 4 | let timeoutId; 5 | 6 | return function() { 7 | const context = this; 8 | const args = arguments; 9 | 10 | clearTimeout(timeoutId); 11 | timeoutId = setTimeout(function() { 12 | func.apply(context, args); 13 | }, delay); 14 | }; 15 | }, 16 | throttle: function(func, delay) { 17 | delay = delay || 300; 18 | let lastCalledTime = 0; 19 | 20 | return function() { 21 | const now = Date.now(); 22 | 23 | if (now - lastCalledTime >= delay) { 24 | func.apply(this, arguments); 25 | lastCalledTime = now; 26 | } 27 | }; 28 | }, 29 | } 30 | export default eventBox; -------------------------------------------------------------------------------- /tools/matchBox/index.js: -------------------------------------------------------------------------------- 1 | const matchBox = { 2 | email: function(val) { 3 | const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; 4 | return emailRegex.test(val); 5 | }, 6 | phone: function(val) { 7 | const phoneRegex = /^1[3456789]\d{9}$/; 8 | return phoneRegex.test(val); 9 | }, 10 | url: function(val) { 11 | const urlRegex = /^(ftp|http|https):\/\/[^ "]+$/; 12 | return urlRegex.test(val); 13 | }, 14 | idCard: function(val) { 15 | const idCardRegex = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/; 16 | return idCardRegex.test(val); 17 | }, 18 | ip: function(val) { 19 | const ipRegex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/; 20 | return ipRegex.test(val); 21 | }, 22 | postal: function(val) { 23 | const postalCodeRegex = /^[0-9]\d{5}$/; 24 | return postalCodeRegex.test(val); 25 | }, 26 | checkUnicode: function(str) { 27 | const regex = /^[\s\S]$/u; 28 | return regex.test(str); 29 | }, 30 | checkPasswordStrength: function(password) { 31 | let strength = 0; 32 | if (!password || password.length < 6) { 33 | strength = 0; 34 | return strength; 35 | } 36 | if (/[a-z]/.test(password)) { 37 | strength += 1; 38 | } 39 | if (/[A-Z]/.test(password)) { 40 | strength += 1; 41 | } 42 | if (/\d/.test(password)) { 43 | strength += 1; 44 | } 45 | if (/[\W_]/.test(password)) { 46 | strength += 1; 47 | } 48 | return strength; 49 | } 50 | } 51 | export default matchBox; -------------------------------------------------------------------------------- /tools/numberBox/index.js: -------------------------------------------------------------------------------- 1 | const eventBox = { 2 | formatNumberWithCommas: function(number, decimalPlaces) { 3 | // 将数字转换为字符串,并按照小数点分割为整数部分和小数部分 4 | number = Number(number); 5 | let parts = number.toFixed(decimalPlaces).toString().split("."); 6 | let integerPart = parts[0]; 7 | let decimalPart = parts.length > 1 ? "." + parts[1] : ""; 8 | 9 | // 添加千位分隔符 10 | integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ","); 11 | 12 | // 返回格式化后的数字字符串 13 | return integerPart + decimalPart; 14 | }, 15 | isGreater0: function(number) { 16 | number = Number(number); 17 | if (isNaN(number)) { 18 | return false; 19 | } 20 | return number > 0; 21 | }, 22 | isGreater0Integer: function(number) { 23 | number = Number(number); 24 | if (isNaN(number)) { 25 | return false; 26 | } 27 | return number>0 && Number.isInteger(number); 28 | }, 29 | getRandomNumber: function(min, max, decimalPlaces) { 30 | if (decimalPlaces) { 31 | return parseFloat((Math.random() * (max - min) + min).toFixed(decimalPlaces)); 32 | } 33 | return Math.floor(Math.random() * (max - min + 1)) + min; 34 | }, 35 | generateUniqueRandomNumber: function(length) { 36 | let numbers = Array.from({ length: 10 }, (_, i) => i); 37 | // 打乱数组顺序 38 | for (let i = numbers.length - 1; i > 0; i--) { 39 | const j = Math.floor(Math.random() * (i + 1)); 40 | [numbers[i], numbers[j]] = [numbers[j], numbers[i]]; 41 | } 42 | // 取数组前 length 个元素拼接成字符串 43 | let result = numbers.slice(0, length).join(''); 44 | return result; 45 | }, 46 | numberToChinese: function(number, upperOrlower) { 47 | upperOrlower = upperOrlower || 'lower'; 48 | // 定义中文数字 49 | let chineseNumbers = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']; 50 | // 定义中文单位 51 | let chineseUnits = ['', '十', '百', '千', '万', '十', '百', '千', '亿']; 52 | if (upperOrlower === 'upper') { 53 | chineseNumbers = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']; 54 | chineseUnits = ['', '拾', '佰', '仟', '万', '拾', '佰', '仟', '亿']; 55 | } 56 | let numberString = number.toString(); 57 | let [integerPart, decimalPart] = numberString.split('.'); 58 | let integerArray = integerPart.split('').map(Number); 59 | 60 | // 构建整数部分的中文表示 61 | let chineseInteger = ''; 62 | for (let i = 0; i < integerArray.length; i++) { 63 | let digit = integerArray[i]; 64 | let unit = chineseUnits[integerArray.length - i - 1]; 65 | if (digit === 0) { 66 | if (i !== integerArray.length - 1 && integerArray[i + 1] !== 0) { 67 | chineseInteger += chineseNumbers[digit]; 68 | } 69 | } else { 70 | chineseInteger += chineseNumbers[digit] + unit; 71 | } 72 | } 73 | // 构建小数部分的中文表示 74 | let chineseDecimal = ''; 75 | if (decimalPart) { 76 | let decimalArray = decimalPart.split('').map(Number); 77 | for (let i = 0; i < decimalArray.length; i++) { 78 | chineseDecimal += chineseNumbers[decimalArray[i]]; 79 | } 80 | } 81 | // 拼接整数部分和小数部分的中文表示,并返回结果 82 | let result = chineseInteger + (decimalPart ? '点' + chineseDecimal : ''); 83 | return result || '零'; 84 | } 85 | } 86 | export default eventBox; -------------------------------------------------------------------------------- /tools/storeBox/index.js: -------------------------------------------------------------------------------- 1 | const storeBox = { 2 | getUrlParam: function(key) { 3 | const url = window.location.href; 4 | if (url.indexOf('?') === -1) { 5 | return null; 6 | } 7 | const params = url.split('?')[1]; 8 | const paramsArr = params.split('&'); 9 | for (let i=0;i num2 ? 1 : -1; 13 | } 14 | } 15 | // 如果所有子版本号都相等,则返回0,表示版本号相等 16 | return 0; 17 | }, 18 | hyphenToCamelCase: function(str, type) { 19 | type = type || 'small'; 20 | var parts = str.split("-"); 21 | // 遍历数组,将每个单词的首字母大写,并拼接起来 22 | for (var i = 1; i < parts.length; i++) { 23 | parts[i] = parts[i].charAt(0).toUpperCase() + parts[i].slice(1); 24 | } 25 | // 将数组中的元素连接起来,形成新的字符串 26 | var camelCaseStr = parts.join(""); 27 | // 返回转换后的字符串 28 | if (type === 'small') { 29 | return camelCaseStr; 30 | } else { 31 | let bigCamelCaseStr = camelCaseStr.charAt(0).toUpperCase() + camelCaseStr.slice(1); 32 | return bigCamelCaseStr; 33 | } 34 | }, 35 | reverseString: function(str) { 36 | let arr = str.split(''); 37 | // 反转数组,使用reverse()方法 38 | arr.reverse(); 39 | // 将数组转换回字符串,使用join()方法 40 | let reversedStr = arr.join(''); 41 | // 返回反转后的字符串 42 | return reversedStr; 43 | }, 44 | byteLength: function(str) { 45 | const utf8Bytes = new TextEncoder().encode(str); 46 | return utf8Bytes.length; 47 | }, 48 | generateUUID: function() { 49 | function s4() { 50 | return Math.floor((1 + Math.random()) * 0x10000) 51 | .toString(16) 52 | .substring(1); 53 | } 54 | // 返回格式化后的 UUID 55 | return ( 56 | s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4() 57 | ); 58 | }, 59 | maskString: function(str, startLen, endLen, maskType, num) { 60 | // 确保字符串足够长以进行处理 61 | if (str.length <= startLen + endLen) { 62 | return str; 63 | } 64 | const start = str.slice(0, startLen); 65 | const end = str.slice(-endLen); 66 | let maskStr = ''; 67 | for (let i=0;i currentYear) 102 | return false; 103 | if (monthNum > 12 || monthNum < 1) 104 | return false; 105 | 106 | if ((monthNum === 1 || monthNum === 3 || monthNum === 5 || monthNum === 7 || monthNum === 8 || monthNum === 10 || monthNum === 12) && dayNum > 31) 107 | return false; 108 | 109 | if ((monthNum === 4 || monthNum === 6 || monthNum === 9 || monthNum === 11) && dayNum > 30) 110 | return false; 111 | 112 | if (monthNum === 2) { 113 | let leapYear = null; 114 | // 闰年 115 | if (yearNum % 4 === 0 && yearNum % 100 !== 0 && yearNum % 400 === 0) 116 | leapYear = dayNum > 29 ? false : true; 117 | else {// 平年 118 | leapYear = dayNum > 28 ? false : true; 119 | } 120 | if (!leapYear) { 121 | return false; 122 | } 123 | } 124 | 125 | birthday = `${year}-${month}-${day}`; 126 | age = currentYear - year; 127 | if (certNo.length === 18) { 128 | gender = certNo.substring(16, 17) % 2 === 0 ? '女' : '男'; 129 | } else { 130 | gender = certNo.substring(13, 14) % 2 === 0 ? '女' : '男'; 131 | } 132 | 133 | // 校验 校验码 134 | const powerList = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; 135 | const paritybitList = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']; 136 | let num = 0; 137 | let certArr = certNo.split('').map(Number).slice(0, 17); 138 | 139 | for (let i = 0; i < certArr.length; i++) { 140 | num += (certArr[i] * powerList[i]); 141 | } 142 | 143 | if (certNo[17] != paritybitList[num % 11]) { 144 | if (num%11 === 2) { 145 | if(certNo[17] != 'x' && certNo[17] != 'X') 146 | return false; 147 | } else { 148 | return false; 149 | } 150 | } 151 | 152 | return { 153 | birthday, 154 | gender, 155 | age 156 | }; 157 | }, 158 | transformLetter: function(str, type) { 159 | if (type === 1) { 160 | const newStr = str.toLowerCase(); 161 | return newStr; 162 | } 163 | if (type === 2) { 164 | const newStr = str.toUpperCase(); 165 | return newStr; 166 | } 167 | if (type === 3) { 168 | const newLowerStr = str.toLowerCase(); 169 | const newStr = `${newLowerStr[0].toUpperCase()}${newLowerStr.slice(1)}` 170 | return newStr; 171 | } 172 | if (type === 4) { 173 | const newArr = str.split(' '); 174 | let newStr = ''; 175 | for (let i=0;i= octoberFirstSunday && date < aprilFirstSunday; 58 | } 59 | const isDaylightSavingTime = function(date) { 60 | // 检查是否在夏令时范围内(3月的最后一个周日到10月的最后一个周日) 61 | const year = date.getFullYear(); 62 | const marchLastSunday = getLastSundayOfMonth(year, 2); // 3月 63 | const octoberLastSunday = getLastSundayOfMonth(year, 9); // 10月 64 | return date >= marchLastSunday && date < octoberLastSunday; 65 | } 66 | const isDaylightSavingTimeNew = function(date) { 67 | // 检查是否在夏令时范围内(3月的第二个周日至11月的第一个周日) 68 | const year = date.getFullYear(); 69 | const marchSecondSunday = getSecondSundayOfMonth(year, 2); // 3月 70 | const novemberFirstSunday = getFirstSundayOfMonth(year, 10); // 11月 71 | return date >= marchSecondSunday && date < novemberFirstSunday; 72 | } 73 | 74 | const timeBox = { 75 | getMyYear: function(time, unit) { 76 | unit = unit || ''; 77 | const year = getYear(time); 78 | return year + String(unit); 79 | }, 80 | getMyMonth: function(time, unit) { 81 | unit = unit || ''; 82 | const month = getMonth(time); 83 | return month + String(unit); 84 | }, 85 | getMyDate: function(time, unit) { 86 | unit = unit || ''; 87 | const date = getDate(time); 88 | return date + String(unit); 89 | }, 90 | getMyHour: function(time, unit) { 91 | unit = unit || ''; 92 | const hour = getHour(time); 93 | return hour + String(unit); 94 | }, 95 | getMyMinutes: function(time, unit) { 96 | unit = unit || ''; 97 | const minutes = getMinutes(time); 98 | return minutes + String(unit); 99 | }, 100 | getMySeconds: function(time, unit) { 101 | unit = unit || ''; 102 | const seconds = getSeconds(time); 103 | return seconds + String(unit); 104 | }, 105 | getFullDateTime: function(time, showType, char) { 106 | const timeChar = char || '-'; 107 | const year = getYear(time); 108 | const month = getMonth(time); 109 | const date = getDate(time); 110 | const hour = getHour(time); 111 | const minutes = getMinutes(time); 112 | const seconds = getSeconds(time); 113 | if (showType === 'YYYY-MM-DD') { 114 | return `${year}${timeChar}${month}${timeChar}${date}`; 115 | } 116 | if (showType === 'YYYY-MM-DD hh:mm') { 117 | return `${year}${timeChar}${month}${timeChar}${date} ${hour}:${minutes}`; 118 | } 119 | if (showType === 'YYYY-MM-DD hh:mm:ss') { 120 | return `${year}${timeChar}${month}${timeChar}${date} ${hour}:${minutes}:${seconds}`; 121 | } 122 | }, 123 | getLeapYear: function(time) { 124 | const isLear = isLeapYear(time); 125 | return isLear; 126 | }, 127 | getDistanceNow: function(time, unitObj) { 128 | const distanceUnitObj = { 129 | beforeUnit: '以前', 130 | afterUnit: '之后', 131 | yearUnit: '年', 132 | monthUnit: '月', 133 | dateUnit: '天', 134 | hourUnit: '小时', 135 | minutesUnit: '分钟', 136 | secondUnit: '秒钟' 137 | } 138 | if (unitObj) { 139 | for (let i in unitObj) { 140 | distanceUnitObj[i] = unitObj[i]; 141 | } 142 | } 143 | const datetimeCompare = new Date(time); 144 | const datetimeCompareStamp = datetimeCompare.getTime(); 145 | const now = new Date(); 146 | const nowStamp = now.getTime(); 147 | if (datetimeCompareStamp - nowStamp > 0) { // 未来 148 | const yearCompare = getYear(time); 149 | const yearNow = getYear(null); 150 | const distanceYear = Number(yearCompare) - Number(yearNow); 151 | 152 | const monthCompare = Number(getMonth(time)); 153 | const monthNow = Number(getMonth(null)); 154 | const distanceMonth = distanceYear*12 + (monthCompare - monthNow); 155 | 156 | const distanceDate = Math.ceil((datetimeCompareStamp - nowStamp) / (1000*60*60*24)); 157 | 158 | const distanceHour = Math.ceil((datetimeCompareStamp - nowStamp) / (1000*60*60)); 159 | 160 | const distanceMinutes = Math.ceil((datetimeCompareStamp - nowStamp) / (1000*60)); 161 | 162 | const distanceSeconds = Math.ceil((datetimeCompareStamp - nowStamp) / 1000); 163 | 164 | ///////////////---fullDistanceShow---/////////////////////////////// 165 | let fullDistanceShow = ''; 166 | let fullDistanceYear = distanceYear; 167 | let fullDistanceMonth = Number(getMonth(time)) - Number(getMonth(null)); 168 | if (fullDistanceMonth <= 0) { 169 | fullDistanceYear = distanceYear - 1; 170 | fullDistanceMonth += 12; 171 | } 172 | let fullDistanceDate = Number(getDate(time)) - Number(getDate(null)); 173 | if (fullDistanceDate < 0) { 174 | fullDistanceMonth--; 175 | fullDistanceDate += daysInMonth(null, Number(getMonth(null))-1); 176 | } 177 | let fullDistanceHour = Number(getHour(time)) - Number(getHour(null)); 178 | if (fullDistanceHour < 0) { 179 | fullDistanceDate--; 180 | fullDistanceHour += 24; 181 | } 182 | let fullDistanceMintus = Number(getMinutes(time)) - Number(getMinutes(null)); 183 | if (fullDistanceMintus < 0) { 184 | fullDistanceHour--; 185 | fullDistanceMintus += 60; 186 | } 187 | let fullDistanceSeconds = Number(getSeconds(time)) - Number(getSeconds(null)); 188 | if (fullDistanceSeconds < 0) { 189 | fullDistanceMintus--; 190 | fullDistanceSeconds += 60; 191 | } 192 | // console.log('-----年----', fullDistanceYear); 193 | // console.log('-----月----', fullDistanceMonth); 194 | // console.log('-----日----', fullDistanceDate); 195 | // console.log('-----时----', fullDistanceHour); 196 | // console.log('-----分----', fullDistanceMintus); 197 | // console.log('-----秒----', fullDistanceSeconds); 198 | 199 | if (fullDistanceYear > 0) { 200 | fullDistanceShow += `${fullDistanceYear}${distanceUnitObj.yearUnit}`; 201 | } 202 | if (fullDistanceMonth > 0) { 203 | fullDistanceShow += `${fullDistanceMonth}${distanceUnitObj.monthUnit}`; 204 | } 205 | if (fullDistanceDate > 0) { 206 | fullDistanceShow += `${fullDistanceDate}${distanceUnitObj.dateUnit}`; 207 | } 208 | if (fullDistanceHour > 0) { 209 | fullDistanceShow += `${fullDistanceHour}${distanceUnitObj.hourUnit}`; 210 | } 211 | if (fullDistanceMintus > 0) { 212 | fullDistanceShow += `${fullDistanceMintus}${distanceUnitObj.minutesUnit}`; 213 | } 214 | if (fullDistanceSeconds > 0) { 215 | fullDistanceShow += `${fullDistanceSeconds}${distanceUnitObj.secondUnit}`; 216 | } 217 | 218 | return { 219 | year: distanceYear + distanceUnitObj.yearUnit + distanceUnitObj.afterUnit, 220 | month: distanceMonth + distanceUnitObj.monthUnit + distanceUnitObj.afterUnit, 221 | date: distanceDate + distanceUnitObj.dateUnit + distanceUnitObj.afterUnit, 222 | hour: distanceHour + distanceUnitObj.hourUnit + distanceUnitObj.afterUnit, 223 | minutes: distanceMinutes + distanceUnitObj.minutesUnit + distanceUnitObj.afterUnit, 224 | seconds: distanceSeconds + distanceUnitObj.secondUnit + distanceUnitObj.afterUnit, 225 | fullDateTime: `${fullDistanceShow}${distanceUnitObj.afterUnit}` 226 | }; 227 | } 228 | // 以前 229 | const yearCompare = getYear(time); 230 | const yearNow = getYear(null); 231 | const distanceYear = Number(yearNow) - Number(yearCompare); 232 | 233 | const monthCompare = Number(getMonth(time)); 234 | const monthNow = Number(getMonth(null)); 235 | const distanceMonth = distanceYear*12 + (monthNow - monthCompare); 236 | 237 | const distanceDate = Math.ceil((nowStamp - datetimeCompareStamp) / (1000*60*60*24)); 238 | 239 | const distanceHour = Math.ceil((nowStamp - datetimeCompareStamp) / (1000*60*60)); 240 | 241 | const distanceMinutes = Math.ceil((nowStamp - datetimeCompareStamp) / (1000*60)); 242 | 243 | const distanceSeconds = Math.ceil((nowStamp - datetimeCompareStamp) / 1000); 244 | 245 | ///////////////---fullDistanceShow---/////////////////////////////// 246 | let fullDistanceShow = ''; 247 | let fullDistanceYear = distanceYear; 248 | let fullDistanceMonth = Number(getMonth(null)) - Number(getMonth(time)); 249 | if (fullDistanceMonth < 0) { 250 | fullDistanceYear = distanceYear - 1; 251 | fullDistanceMonth += 12; 252 | } 253 | let fullDistanceDate = Number(getDate(null)) - Number(getDate(time)); 254 | if (fullDistanceDate < 0) { 255 | fullDistanceMonth--; 256 | fullDistanceDate += daysInMonth(null, Number(getMonth(null))-1); 257 | } 258 | let fullDistanceHour = Number(getHour(null)) - Number(getHour(time)); 259 | if (fullDistanceHour < 0) { 260 | fullDistanceDate--; 261 | fullDistanceHour += 24; 262 | } 263 | let fullDistanceMintus = Number(getMinutes(null)) - Number(getMinutes(time)); 264 | if (fullDistanceMintus < 0) { 265 | fullDistanceHour--; 266 | fullDistanceMintus += 60; 267 | } 268 | let fullDistanceSeconds = Number(getSeconds(null)) - Number(getSeconds(time)); 269 | if (fullDistanceSeconds < 0) { 270 | fullDistanceMintus--; 271 | fullDistanceSeconds += 60; 272 | } 273 | // console.log('-----年----', fullDistanceYear); 274 | // console.log('-----月----', fullDistanceMonth); 275 | // console.log('-----日----', fullDistanceDate); 276 | // console.log('-----时----', fullDistanceHour); 277 | // console.log('-----分----', fullDistanceMintus); 278 | // console.log('-----秒----', fullDistanceSeconds); 279 | 280 | if (fullDistanceYear > 0) { 281 | fullDistanceShow += `${fullDistanceYear}${distanceUnitObj.yearUnit}`; 282 | } 283 | if (fullDistanceMonth > 0) { 284 | fullDistanceShow += `${fullDistanceMonth}${distanceUnitObj.monthUnit}`; 285 | } 286 | if (fullDistanceDate > 0) { 287 | fullDistanceShow += `${fullDistanceDate}${distanceUnitObj.dateUnit}`; 288 | } 289 | if (fullDistanceHour > 0) { 290 | fullDistanceShow += `${fullDistanceHour}${distanceUnitObj.hourUnit}`; 291 | } 292 | if (fullDistanceMintus > 0) { 293 | fullDistanceShow += `${fullDistanceMintus}${distanceUnitObj.minutesUnit}`; 294 | } 295 | if (fullDistanceSeconds > 0) { 296 | fullDistanceShow += `${fullDistanceSeconds}${distanceUnitObj.secondUnit}`; 297 | } 298 | 299 | return { 300 | year: distanceYear + distanceUnitObj.yearUnit + distanceUnitObj.beforeUnit, 301 | month: distanceMonth + distanceUnitObj.monthUnit + distanceUnitObj.beforeUnit, 302 | date: distanceDate + distanceUnitObj.dateUnit + distanceUnitObj.beforeUnit, 303 | hour: distanceHour + distanceUnitObj.hourUnit + distanceUnitObj.beforeUnit, 304 | minutes: distanceMinutes + distanceUnitObj.minutesUnit + distanceUnitObj.beforeUnit, 305 | seconds: distanceSeconds + distanceUnitObj.secondUnit + distanceUnitObj.beforeUnit, 306 | fullDateTime: `${fullDistanceShow}${distanceUnitObj.beforeUnit}` 307 | }; 308 | }, 309 | getDaysInMonth: function(time, month) { 310 | const days = daysInMonth(time, month); 311 | return days; 312 | }, 313 | getAnimalOfBorn: function(time) { 314 | const year = getYear(time); 315 | const defaultYear = 1900; 316 | const remainYear = (year - defaultYear) % 12; 317 | const animals = ['rat|鼠', 'ox|牛', 'tiger|虎', 'hare|兔', 'dragon|龙', 'snake|蛇', 'horse|马', 'sheep|羊', 'monkey|猴', 'rooster|鸡', 'dog|狗', 'boar|猪']; 318 | return animals[remainYear]; 319 | }, 320 | getHoliday: function(time) { 321 | const year = getYear(time); 322 | if (year < 2024) { 323 | return null; 324 | } 325 | if (year === 2024) { 326 | return [ 327 | { 328 | name: '元旦', 329 | days: '01-01' 330 | }, 331 | { 332 | name: '春节', 333 | days: '02-10|02-11|02-12|02-13|02-14|02-15|02-16|02-17' 334 | }, 335 | { 336 | name: '清明', 337 | days: '04-04|04-05|04-06' 338 | }, 339 | { 340 | name: '劳动节', 341 | days: '05-01|05-02|05-03|05-04|05-05' 342 | }, 343 | { 344 | name: '端午节', 345 | days: '06-08|06-09|06-10' 346 | }, 347 | { 348 | name: '中秋节', 349 | days: '09-15|09-16|09-17' 350 | }, 351 | { 352 | name: '国庆节', 353 | days: '10-01|10-02|10-03|10-04|10-05|10-06|10-07' 354 | }, 355 | ] 356 | } 357 | }, 358 | getWorldTime: function() { 359 | const now = new Date(); 360 | // 获取 UTC 时间 361 | const utc = now.getTime() + (now.getTimezoneOffset() * 60000); 362 | // 创建北京时间,UTC+8小时 363 | const beijingTime = new Date(utc + (3600000 * 8)); 364 | const beijingTimeData = { 365 | hour: getHour(beijingTime), 366 | min: getMinutes(beijingTime), 367 | sec: getSeconds(beijingTime), 368 | } 369 | // 伦敦时间 370 | // 检查是否为夏令时 371 | const londonOffset = isDaylightSavingTime(now) ? 1 : 0; 372 | const londonTime = new Date(utc + (3600000 * londonOffset)); 373 | const londonTimeData = { 374 | hour: getHour(londonTime), 375 | min: getMinutes(londonTime), 376 | sec: getSeconds(londonTime), 377 | } 378 | // 纽约时间 379 | // 检查是否为夏令时 380 | const newYorkOffset = isDaylightSavingTimeNew(now) ? -4 : -5; 381 | const newYorkTime = new Date(utc + (3600000 * newYorkOffset)); 382 | const newYorkTimeData = { 383 | hour: getHour(newYorkTime), 384 | min: getMinutes(newYorkTime), 385 | sec: getSeconds(newYorkTime), 386 | } 387 | // 东京时间 388 | const tokyoTime = new Date(utc + (3600000 * 9)); 389 | const tokyoTimeData = { 390 | hour: getHour(tokyoTime), 391 | min: getMinutes(tokyoTime), 392 | sec: getSeconds(tokyoTime), 393 | } 394 | // 创建巴黎时间,UTC+1 或 UTC+2 395 | // 检查是否为夏令时 396 | const parisOffset = isDaylightSavingTime(now) ? 2 : 1; 397 | const parisTime = new Date(utc + (3600000 * parisOffset)); 398 | const parisTimeData = { 399 | hour: getHour(parisTime), 400 | min: getMinutes(parisTime), 401 | sec: getSeconds(parisTime), 402 | } 403 | // 悉尼澳大利亚时间 404 | // 检查是否为夏令时 405 | const sydneyOffset = isDaylightSavingTimeSydney(now) ? 11 : 10; 406 | const sydneyTime = new Date(utc + (3600000 * sydneyOffset)); 407 | const sydneyTimeData = { 408 | hour: getHour(sydneyTime), 409 | min: getMinutes(sydneyTime), 410 | sec: getSeconds(sydneyTime), 411 | } 412 | // 创建雅加达时间,UTC+7 413 | const jakartaTime = new Date(utc + (3600000 * 7)); 414 | const jakartaTimeData = { 415 | hour: getHour(jakartaTime), 416 | min: getMinutes(jakartaTime), 417 | sec: getSeconds(jakartaTime), 418 | } 419 | return { 420 | beijing: beijingTimeData, 421 | london: londonTimeData, 422 | newYork: newYorkTimeData, 423 | tokyo: tokyoTimeData, 424 | paris: parisTimeData, 425 | sydney: sydneyTimeData, 426 | jakarta: jakartaTimeData 427 | } 428 | } 429 | } 430 | export default timeBox; --------------------------------------------------------------------------------