1 js 获取当月天数
function getCurrentMonthDays() {
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth() + 1; // 注意月份从 0 开始,所以要加 1
// 获取当月的最后一天
const lastDay = new Date(year, month, 0);
return lastDay.getDate();
}
const days = getCurrentMonthDays();
console.log(days); // 输出当前月份的天数
2 alt=‘abc’ def" js 如何 拿到 alt= 后面’’ 中的值
const str = "alt='abc' def";
const match = str.match(/alt='([^']*)'/);
const result = match ? match[1] : null;
console.log(result); // 输出 'abc'
3 “alt=‘abc’ de alt=‘a’ f” js 如何 拿到 alt= 后面’’ 中的值
const str = "alt='abc' de alt='a' f";
const regex = /alt='([^']*)'/g;
const matches = [];
let match;
while ((match = regex.exec(str)) !== null) {
matches.push(match[1]);
}
console.log(matches); // 输出 ['abc', 'a']
4 数组去重
const array = [{ name: 1, age: 23 }, { age: 23, name: 1,name:2 }];
function removeDuplicates(array) {
const seen = new Set();
return array.filter(obj => {
const sorted = JSON.stringify(Object.keys(obj).sort().reduce((result, key) => {
result[key] = obj[key];
return result;
}, {}));
if (!seen.has(sorted)) {
seen.add(sorted);
return true;
}
return false;
});
}
const uniqueArray = removeDuplicates(array);//[ { "name": 1, "age": 23}]
5 如何获取 30天后的日期
let today = new Date().getTime()
let lastDay = getTimeByDay(30) //获取30天后的日期
let lastTime = formatTime(lastDay)
console.log(lastTime);//2024-01-19
/*
num 获取当天多少天后的日期
*/
function getTimeByDay(num) {
return today + 60 * 60 * 1000 * 24 * num;
}
function formatTime(time) {
//new Date(time).toISOString() => 2019-02-23T08:40:35.825Z
return new Date(time).toISOString().split('T')[0];
}
6 URL查询字符串中提取指定参数名的参数值
getUrlParam(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的 //正则表达式对象
var r = window.location.search.substr(1).match(reg) || window.location.hash.substring((window.location.hash
.search(/\?/)) + 1).match(reg); //匹配目标参数
if (r != null) return unescape(r[2]);
return null; //返回参数值
},
解释:
(^|&): 匹配字符串开始或者&符号,表示参数名的起始位置。
name: 这是通过变量传入的参数名,将在实际使用时替换。
=([^&]*): 匹配等号后面的参数值,其中([^&]*)表示零个或多个非&字符的任意字符。
(&|$): 匹配&符号或字符串的结尾,表示参数值的结束位置。
这个正则表达式可以用于从URL查询字符串中提取指定参数名的参数值。例如,如果name是"example",那么它将匹配类似于?example=value或&example=value&这样的字符串,提取出value作为匹配的结果。
7 防抖函数使用
防抖函数是一种常见的前端开发技术,用于控制在连续触发某个事件时,只有在一定时间间隔内没有新的触发事件时,才执行相应的操作。这对于处理频繁触发的事件,如输入框输入、窗口调整大小等,是很有用的。
function debounce(func, delay) {
let timeoutId;
return function (...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
是否每次触发都会执行 let timeoutId;
不会! 绑定的是debounce(func, delay) !这个括号不可忽视,实际上每次触发事件执行的是它的回调,也就是 return 里面的内容,
let timeoutId; 只会在初始化的时候执行一次。
使用示例 1:
// 假设有一个需要防抖的函数
function handleInput(value) {
console.log(value);
}
// 创建防抖函数
const debouncedHandleInput = debounce(handleInput, 500);
// 模拟输入事件
document.getElementById('inputElement').addEventListener('input', function(event) {
debouncedHandleInput(event.target.value);
});
使用示例 2:
document.getElementById('inputElement').addEventListener('input', debounce(function(event) {
handleInput(event.target.value);
}, 500));
8 URL 获取参数对象
param2Obj(url) {
url = sessionStorage.getItem('url')
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
if (!search) {
return {}
}
const obj = {}
const searchArr = search.split('&')
// token
searchArr.forEach(v => {
const index = v.indexOf('=')
if (index !== -1) {
const name = v.substring(0, index)
const val = v.substring(index + 1, v.length)
obj[name] = val
}
})
this.paramDetails = obj
uni.setStorageSync('details', obj)
//最开始设想 我的动态页面由移动端 传入个人参数
this.uidOrUsername = this.paramDetails.uidOrUsername || ''
return obj
},
9 input 上传展示图片
clickAvatar() {
// 创建附件上传
var input = document.createElement('input'); //创建元素
console.log(input, 'input12');
input.type = 'file' //添加file类型
input.ref = 'myChangePic' //添加file类型
input.className = 'addinput'
input.style.position = 'absolute'
input.style.top = '0'
// input.multiple = true;
input.style.width = '0'
input.style.left = '10%'
input.style.height = '0px'
input.style.background = 'red'
input.style.lineHeight = '50px'
// input.style.display = 'none'
input.accept = "image/jpeg, image/jpg, image/png"
document.body.appendChild(input);
input.onchange = (e) => {
console.log(input, e, 12);
// 1、获取文件
var file = input.files[0];
//这就是文件路径
const filePath = URL.createObjectURL(e.target.files[0]);
}
input.addEventListener('click', () => {
console.log('input 触发了');
})
input.click()
input.remove()
},
10 常用的校验方法
/**
* 金钱格式化
*
* 在正则表达式中,`\b` 表示单词边界。它匹配一个单词的开头或结尾,即位于单词字符(字母、数字或下划线)和非单词字符之间的位置。
相应地,`\B` 表示非单词边界,它匹配不位于单词边界的位置。`\B` 是 `\b` 的补集,它匹配任何不是单词边界的位置。
举例说明:
- `\bword\b` 匹配整个单词 "word",但不匹配 "password" 中的 "word"。
- `\Bword\B` 匹配 "password" 中的 "word",但不匹配整个单词 "word"。
在你提供的代码中,使用 `\B` 的目的是确保逗号 `,` 只在数字的千位分隔符位置插入,而不在单词边界的位置插入。这样可以确保只对数字进行逗号的插入,而不会影响单词或其他字符。
(?= 开始一个正向零宽断言。这意味着在当前位置之后的字符要满足一定的条件,但匹配的字符本身不会被包含在结果中。
(\d{3})+ 匹配三个数字的重复,且重复次数可以是一次或多次。这表示在当前位置之后的字符中,要有一组三个数字。
(?!\d) 是一个负向零宽断言,确保在当前位置之后的字符不是数字。这是为了避免在匹配的三个数字组之后继续匹配更多的数字。
零宽断言(zero-width assertions)是正则表达式中的一种特殊元字符,它不匹配实际的字符,而是匹配在字符串中的某个位置的条件。零宽断言用于指定一个位置前面或后面必须满足的条件,但匹配的内容本身不包括在最终的匹配结果中。
在正则表达式中,有四种常见的零宽断言:
正向零宽断言 (?=...)(Positive Lookahead):匹配在当前位置之后的字符串,该字符串必须满足断言中的条件。例如,foo(?=bar) 匹配 "foo",但仅当后面跟着 "bar" 的时候。
负向零宽断言 (?!...)(Negative Lookahead):匹配在当前位置之后的字符串,该字符串不能满足断言中的条件。例如,foo(?!bar) 匹配 "foo",但仅当后面不跟着 "bar" 的时候。
正向零宽断言 (?<=...)(Positive Lookbehind):匹配在当前位置之前的字符串,该字符串必须满足断言中的条件。例如,(?<=foo)bar 匹配 "bar",但仅当前面是 "foo" 的时候。
负向零宽断言 (?<!...)(Negative Lookbehind):匹配在当前位置之前的字符串,该字符串不能满足断言中的条件。例如,(?<!foo)bar 匹配 "bar",但仅当前面不是 "foo" 的时候。
*/
var test1 = '1234567890'
var format = test1.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
console.log(format) // 1,234,567,890
/**
* 验证电子邮箱格式
*/
function email(value) {
return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value)
}
/**
* 验证手机格式
*/
function mobile(value) {
return /^1[3456789]\d{9}$/.test(value)
}
/**
* 验证URL格式
*/
function url(value) {
return /^((https|http|ftp|rtsp|mms):\/\/)(([0-9a-zA-Z_!~*'().&=+$%-]+: )?[0-9a-zA-Z_!~*'().&=+$%-]+@)?(([0-9]{1,3}.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z].[a-zA-Z]{2,6})(:[0-9]{1,4})?((\/?)|(\/[0-9a-zA-Z_!~*'().;?:@&=+$,%#-]+)+\/?)$/
.test(value)
}
/**
* 验证日期格式
*/
function date(value) {
if (!value) return false
// 判断是否数值或者字符串数值(意味着为时间戳),转为数值,否则new Date无法识别字符串时间戳
if (number(value)) value = +value
return !/Invalid|NaN/.test(new Date(value).toString())
}
/**
* 验证ISO类型的日期格式
*/
function dateISO(value) {
return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value)
}
/**
* 验证十进制数字
*/
function number(value) {
return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value)
}
/**
* 验证字符串
*/
function string(value) {
return typeof value === 'string'
}
/**
* 验证整数
*/
function digits(value) {
return /^\d+$/.test(value)
}
/**
* 验证身份证号码
*/
function idCard(value) {
return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
value
)
}
/**
* 是否车牌号
*/
function carNo(value) {
// 新能源车牌
const xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/
// 旧车牌
const creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/
if (value.length === 7) {
return creg.test(value)
} if (value.length === 8) {
return xreg.test(value)
}
return false
}
/**
* 金额,只允许2位小数
*/
function amount(value) {
// 金额,只允许保留两位小数
return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value)
}
/**
* 中文
*/
function chinese(value) {
const reg = /^[\u4e00-\u9fa5]+$/gi
return reg.test(value)
}
/**
* 只能输入字母
*/
function letter(value) {
return /^[a-zA-Z]*$/.test(value)
}
/**
* 只能是字母或者数字
*/
function enOrNum(value) {
// 英文或者数字
const reg = /^[0-9a-zA-Z]*$/g
return reg.test(value)
}
/**
* 验证是否包含某个值
*/
function contains(value, param) {
return value.indexOf(param) >= 0
}
/**
* 验证一个值范围[min, max]
*/
function range(value, param) {
return value >= param[0] && value <= param[1]
}
/**
* 验证一个长度范围[min, max]
*/
function rangeLength(value, param) {
return value.length >= param[0] && value.length <= param[1]
}
/**
* 是否固定电话
*/
function landline(value) {
const reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/
return reg.test(value)
}
/**
* 判断是否为空
*/
function empty(value) {
switch (typeof value) {
case 'undefined':
return true
case 'string':
if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true
break
case 'boolean':
if (!value) return true
break
case 'number':
if (value === 0 || isNaN(value)) return true
break
case 'object':
if (value === null || value.length === 0) return true
for (const i in value) {
return false
}
return true
}
return false
}
/**
* 是否json字符串
*/
function jsonString(value) {
if (typeof value === 'string') {
try {
const obj = JSON.parse(value)
if (typeof obj === 'object' && obj) {
return true
}
return false
} catch (e) {
return false
}
}
return false
}
/**
* 是否数组
*/
function array(value) {
if (typeof Array.isArray === 'function') {
return Array.isArray(value)
}
return Object.prototype.toString.call(value) === '[object Array]'
}
/**
* 是否对象
*/
function object(value) {
return Object.prototype.toString.call(value) === '[object Object]'
}
/**
* 是否短信验证码
*/
function code(value, len = 6) {
return new RegExp(`^\\d{${len}}$`).test(value)
}
/**
* 是否函数方法
* @param {Object} value
*/
function func(value) {
return typeof value === 'function'
}
/**
* 是否promise对象
* @param {Object} value
*/
function promise(value) {
return object(value) && func(value.then) && func(value.catch)
}
/** 是否图片格式
* @param {Object} value
*/
function image(value) {
const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i
return IMAGE_REGEXP.test(value)
}
/**
* 是否视频格式
* @param {Object} value
*/
function video(value) {
const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv)/i
return VIDEO_REGEXP.test(value)
}
/**
* 是否为正则对象
* @param {Object}
* @return {Boolean}
*/
function regExp(o) {
return o && Object.prototype.toString.call(o) === '[object RegExp]'
}
function copyText(text) {
// 数字没有 .length 不能执行selectText 需要转化成字符串
const textString = text.toString()
let input = document.querySelector('#copy-input')
if (!input) {
input = document.createElement('input')
input.id = 'copy-input'
input.readOnly = 'readOnly' // 防止ios聚焦触发键盘事件
input.style.position = 'absolute'
input.style.left = '-1000px'
input.style.zIndex = '-1000'
document.body.appendChild(input)
}
input.value = textString
// ios必须先选中文字且不支持 input.select();
selectText(input, 0, textString.length)
// console.log(document.execCommand('copy'), 'execCommand')
return document.execCommand('copy')
// input自带的select()方法在苹果端无法进行选择,所以需要自己去写一个类似的方法
// 选择文本。createTextRange(setSelectionRange)是input方法
function selectText(textbox, startIndex, stopIndex) {
if (textbox.createTextRange) { // ie
const range = textbox.createTextRange()
range.collapse(true)
range.moveStart('character', startIndex)// 起始光标
range.moveEnd('character', stopIndex - startIndex)// 结束光标
range.select()// 不兼容苹果
} else { // firefox/chrome
textbox.setSelectionRange(startIndex, stopIndex)
textbox.focus()
}
}
}
export default {
email,
mobile,
url,
date,
dateISO,
number,
digits,
idCard,
carNo,
amount,
chinese,
letter,
enOrNum,
contains,
range,
rangeLength,
empty,
isEmpty: empty,
jsonString,
landline,
object,
array,
code,
func,
promise,
video,
image,
regExp,
string,
copyText
}
11 格式化日期
const date = new Date();
const formattedDate = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}:${date.getSeconds().toString().padStart(2, '0')}`;
console.log(formattedDate); //2023-12-25 14:03:32
12 获取32位一个随机数
function generateUUID() {
let d = new Date().getTime()
// 生成一个随机字符
if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
d += performance.now() // 获取更高精度的时间戳
}
const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = (d + Math.random() * 16) % 16 | 0
d = Math.floor(d / 16)
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16)
})
return uuid
}
13 复制
/**
* @param {string} path
* @returns
*/
export function copyText(text) {
// 数字没有 .length 不能执行selectText 需要转化成字符串
const textString = text
let input = document.querySelector('#copy-input')
if (!input) {
input = document.createElement('input')
input.id = 'copy-input'
input.readOnly = 'readOnly' // 防止ios聚焦触发键盘事件
input.style.position = 'absolute'
input.style.left = '-1000px'
input.style.zIndex = '-1000'
document.body.appendChild(input)
}
input.value = textString
// ios必须先选中文字且不支持 input.select();
selectText(input, 0, textString.length)
// console.log(document.execCommand('copy'), 'execCommand')
Message.success({
message: generateTitle('translate','Link_Copied'),
duration: 1000
})
return document.execCommand('copy')
// input自带的select()方法在苹果端无法进行选择,所以需要自己去写一个类似的方法
// 选择文本。createTextRange(setSelectionRange)是input方法
}
function selectText(textbox, startIndex, stopIndex) {
if (textbox.createTextRange) { // ie
const range = textbox.createTextRange()
range.collapse(true)
range.moveStart('character', startIndex)// 起始光标
range.moveEnd('character', stopIndex - startIndex)// 结束光标
} else { // firefox/chrome
textbox.setSelectionRange(startIndex, stopIndex)
textbox.focus()
}
}
14 base64 转二进制
export function base64ToBinary(base64String) {
const base64Data = base64String.split(",")[1]; // 获取实际的Base64数据部分,
//data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAACWCAYAA...... base64图片格式和 base-64 编码的字符串不是一回事
//如果传入字符串不是有效的 base64 字符串,比如其长度不是 4 的倍数,则抛出DOMException。
// atob() 对经过 base-64 编码的字符串进行解码
const binaryString = atob(base64Data)
const length = binaryString.length
const bytes = new Uint8Array(length)
for (let i = 0; i < length; ++i) {
bytes[i] = binaryString.charCodeAt(i)
}
return bytes
}
15 下载图片
download() {
const image = new Image()
// 解决跨域 Canvas 污染问题 图片下载 需后端同时支持
image.setAttribute('crossOrigin', 'anonymous')
image.onload = () => {
const canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
const context = canvas.getContext('2d')
context.drawImage(image, 0, 0, image.width, image.height)
canvas.toBlob((blob) => {
const url = URL.createObjectURL(blob)
// \/: 匹配斜杠 /,需要使用反斜杠进行转义。
// ([^ /]+): 这是一个捕获组,匹配任意数量的非斜杠字符。[^/] 表示不是斜杠的任意字符,+ 表示匹配一个或多个这样的字符。
// $: 表示匹配字符串的结尾。
// 整体来说,这个正则表达式的作用是从一个路径中提取出路径末尾的文件名。
// 例如,在路径 / path / to / some / file.txt 中,这个正则表达式会匹配到 / file.txt,捕获组中的内容就是 file.txt
// match[1] 获取内容
const regex = /\/([^/]+)$/;
const match = url.match(regex);
const fileName = match ? match[1] : null;
const a = document.createElement('a')
a.download = fileName // 设置文件名
a.href = url
a.click()
a.remove()
URL.revokeObjectURL(url)
})
}
image.src = this.url
},
16 有趣的js代码,让网页可编辑
document.body.contentEditable='true'; document.designMode='on'; void(0);
//这一行将文档的设计模式(designMode)设置为 'on'。designMode 属性是另一种使整个文档内容可编辑的方法。当设计模式打开时,整个文档都变成了一个可编辑区域。
//void 运算符通常用于执行一个表达式但不返回任何值。在这种情况下,它被用来防止浏览器导航到新页面。表达式 void(0) 本质上什么也不做,并返回 undefined。
17 判断 是移动端还是pc 端方法 以及rem 适配方案 1920 / 750 直接按照 ui 设计除100 就可以了
function isMobile() {
let flag = navigator.userAgent.match(
/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
);
return flag;
}
if (isMobile()) {
//手机
(function (doc, win) {
var docEl = doc.documentElement,
resizeEvt =
"orientationchange" in window ? "orientationchange" : "resize",
recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
if (clientWidth >= 750) {
docEl.style.fontSize = "100px";
} else {
docEl.style.fontSize = 100 * (clientWidth / 750) + "px";
}
};
if (!doc.addEventListener) return;
recalc();
win.addEventListener(resizeEvt, recalc, false);
})(document, window);
} else {
var deviceWidth;
setHtmlFontSize();
if (window.addEventListener) {
window.addEventListener(
"resize",
function () {
setHtmlFontSize();
},
false
);
}
function setHtmlFontSize() {
deviceWidth =
document.documentElement.clientWidth > 1920 ?
1920 :
document.documentElement.clientWidth;
document.getElementsByTagName("html")[0].style.cssText =
"font-size:" + deviceWidth / 19.2 + "px !important";
}
}
18 滚动到顶点
// 获取元素dom 调用scrollTo 方法
let scrollElem = this.$refs.homeContainer
scrollElem.scrollTo({
top: 0,
behavior: 'smooth'
})
19 动态给定元素宽度 (vue项目多语言时用到)
calculateLength(text) {
const span = document.createElement('span')
span.innerText = text
span.style.visibility = 'hidden'
span.style.position = 'absolute'
span.style.left = '-9999px'
document.body.appendChild(span)
const width2 = span.offsetWidth
document.body.removeChild(span)
console.log(`字符串长度为 ${width2}px`)
return width2
},
20 随机获取数组中一个数据
let arr =[1,2,3];
// Math.floor 向下取整
arr[Math.floor(Math.random()*arr.length)]
22 控制任务执行个数
class Controll {
constructor(limit) {
// 待执行的任务队列
this.waitTasks = [];
// 正在执行的任务队列
this.runTasks = [];
// 允许同时运行的任务数量
this.limit = limit;
}
//添加任务
add(task) {
//当前执行任务队列小于并发限制,就执行该任务
if (this.runTasks.length < this.limit) {
this.run(task);
} else {
//将该任务添加到等待队列
this.waitTasks.push(task);
}
}
//执行任务
run(task) {
//push添加元素并返回新的数组长度
const len = this.runTasks.push(task);
const index = len - 1;
task().then(() => {
//执行完后删除任务
this.runTasks.splice(index, 1);
if (this.waitTasks.length > 0) {
//执行并删除等待队列中的第一个任务
this.run(this.waitTasks.shift());
}
});
}
}
//测试:允许同时执行2个任务
const scheduler = new Controll(2);
//添加任务
const addTask = (time, order) => {
scheduler.add(async () => {
//定时器打印
await new Promise((resolve) => {
setTimeout(resolve, time);//定时器时间到了就resolve执行成功,然后打印结果
});
console.log(order);
});
};
//添加任务,参数为定时器时间和打印数字
addTask(1000, "1");
addTask(500, "2");
addTask(300, "3");
addTask(400, "4");
addTask(600, "5");
addTask(1600, "6");
// 2 3 1 4 5 6
23 日期格式化
dateFormat(row, column) {
var date = new Date(row.gmtModified);
var year = date.getFullYear();
var month = date.getMonth() < 9 ? "0" + (date.getMonth() + 1) : "" + (date.getMonth() + 1);
var day = date.getDate() < 10 ? "0" + date.getDate() : "" + date.getDate();
var hour = date.getHours() < 10 ? "0" + date.getHours() : "" + date.getHours();
var minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : "" + date.getMinutes();
var seconds = date.getSeconds() < 10 ? "0" + date.getSeconds() : "" + date.getSeconds();
return (year + "-" + month + "-" + day + " " + hour + ":" + minutes + ":" + seconds);
}