| | |
| | | // yyyy-MM-dd hh:mm:ss.SSS 所有支持的类型 |
| | | function pad(str, length = 2) { |
| | | str += '' |
| | | while (str.length < length) { |
| | | str = '0' + str |
| | | } |
| | | return str.slice(-length) |
| | | } |
| | | |
| | | const parser = { |
| | | yyyy: (dateObj) => { |
| | | return pad(dateObj.year, 4) |
| | | }, |
| | | yy: (dateObj) => { |
| | | return pad(dateObj.year) |
| | | }, |
| | | MM: (dateObj) => { |
| | | return pad(dateObj.month) |
| | | }, |
| | | M: (dateObj) => { |
| | | return dateObj.month |
| | | }, |
| | | dd: (dateObj) => { |
| | | return pad(dateObj.day) |
| | | }, |
| | | d: (dateObj) => { |
| | | return dateObj.day |
| | | }, |
| | | hh: (dateObj) => { |
| | | return pad(dateObj.hour) |
| | | }, |
| | | h: (dateObj) => { |
| | | return dateObj.hour |
| | | }, |
| | | mm: (dateObj) => { |
| | | return pad(dateObj.minute) |
| | | }, |
| | | m: (dateObj) => { |
| | | return dateObj.minute |
| | | }, |
| | | ss: (dateObj) => { |
| | | return pad(dateObj.second) |
| | | }, |
| | | s: (dateObj) => { |
| | | return dateObj.second |
| | | }, |
| | | SSS: (dateObj) => { |
| | | return pad(dateObj.millisecond, 3) |
| | | }, |
| | | S: (dateObj) => { |
| | | return dateObj.millisecond |
| | | }, |
| | | } |
| | | |
| | | // 这都n年了iOS依然不认识2020-12-12,需要转换为2020/12/12 |
| | | function getDate(time) { |
| | | if (time instanceof Date) { |
| | | return time |
| | | } |
| | | switch (typeof time) { |
| | | case 'string': |
| | | { |
| | | // 2020-12-12T12:12:12.000Z、2020-12-12T12:12:12.000 |
| | | if (time.indexOf('T') > -1) { |
| | | return new Date(time) |
| | | } |
| | | return new Date(time.replace(/-/g, '/')) |
| | | } |
| | | default: |
| | | return new Date(time) |
| | | } |
| | | } |
| | | |
| | | export function formatDate(date, format = 'yyyy/MM/dd hh:mm:ss') { |
| | | if (!date && date !== 0) { |
| | | return '' |
| | | } |
| | | date = getDate(date) |
| | | const dateObj = { |
| | | year: date.getFullYear(), |
| | | month: date.getMonth() + 1, |
| | | day: date.getDate(), |
| | | hour: date.getHours(), |
| | | minute: date.getMinutes(), |
| | | second: date.getSeconds(), |
| | | millisecond: date.getMilliseconds() |
| | | } |
| | | const tokenRegExp = /yyyy|yy|MM|M|dd|d|hh|h|mm|m|ss|s|SSS|SS|S/ |
| | | let flag = true |
| | | let result = format |
| | | while (flag) { |
| | | flag = false |
| | | result = result.replace(tokenRegExp, function(matched) { |
| | | flag = true |
| | | return parser[matched](dateObj) |
| | | }) |
| | | } |
| | | return result |
| | | } |
| | | |
| | | export function friendlyDate(time, { |
| | | locale = 'zh', |
| | | threshold = [60000, 3600000], |
| | | format = 'yyyy/MM/dd hh:mm:ss' |
| | | }) { |
| | | if (time === '-') { |
| | | return time |
| | | } |
| | | if (!time && time !== 0) { |
| | | return '' |
| | | } |
| | | const localeText = { |
| | | zh: { |
| | | year: '年', |
| | | month: '月', |
| | | day: '天', |
| | | hour: '小时', |
| | | minute: '分钟', |
| | | second: '秒', |
| | | ago: '前', |
| | | later: '后', |
| | | justNow: '刚刚', |
| | | soon: '马上', |
| | | template: '{num}{unit}{suffix}' |
| | | }, |
| | | en: { |
| | | year: 'year', |
| | | month: 'month', |
| | | day: 'day', |
| | | hour: 'hour', |
| | | minute: 'minute', |
| | | second: 'second', |
| | | ago: 'ago', |
| | | later: 'later', |
| | | justNow: 'just now', |
| | | soon: 'soon', |
| | | template: '{num} {unit} {suffix}' |
| | | } |
| | | } |
| | | const text = localeText[locale] || localeText.zh |
| | | let date = getDate(time) |
| | | let ms = date.getTime() - Date.now() |
| | | let absMs = Math.abs(ms) |
| | | if (absMs < threshold[0]) { |
| | | return ms < 0 ? text.justNow : text.soon |
| | | } |
| | | if (absMs >= threshold[1]) { |
| | | return formatDate(date, format) |
| | | } |
| | | let num |
| | | let unit |
| | | let suffix = text.later |
| | | if (ms < 0) { |
| | | suffix = text.ago |
| | | ms = -ms |
| | | } |
| | | const seconds = Math.floor((ms) / 1000) |
| | | const minutes = Math.floor(seconds / 60) |
| | | const hours = Math.floor(minutes / 60) |
| | | const days = Math.floor(hours / 24) |
| | | const months = Math.floor(days / 30) |
| | | const years = Math.floor(months / 12) |
| | | switch (true) { |
| | | case years > 0: |
| | | num = years |
| | | unit = text.year |
| | | break |
| | | case months > 0: |
| | | num = months |
| | | unit = text.month |
| | | break |
| | | case days > 0: |
| | | num = days |
| | | unit = text.day |
| | | break |
| | | case hours > 0: |
| | | num = hours |
| | | unit = text.hour |
| | | break |
| | | case minutes > 0: |
| | | num = minutes |
| | | unit = text.minute |
| | | break |
| | | default: |
| | | num = seconds |
| | | unit = text.second |
| | | break |
| | | } |
| | | |
| | | if (locale === 'en') { |
| | | if (num === 1) { |
| | | num = 'a' |
| | | } else { |
| | | unit += 's' |
| | | } |
| | | } |
| | | |
| | | return text.template.replace(/{\s*num\s*}/g, num + '').replace(/{\s*unit\s*}/g, unit).replace(/{\s*suffix\s*}/g, |
| | | suffix) |
| | | } |
| | | // yyyy-MM-dd hh:mm:ss.SSS 所有支持的类型
|
| | | function pad(str, length = 2) {
|
| | | str += ''
|
| | | while (str.length < length) {
|
| | | str = '0' + str
|
| | | }
|
| | | return str.slice(-length)
|
| | | }
|
| | |
|
| | | const parser = {
|
| | | yyyy: (dateObj) => {
|
| | | return pad(dateObj.year, 4)
|
| | | },
|
| | | yy: (dateObj) => {
|
| | | return pad(dateObj.year)
|
| | | },
|
| | | MM: (dateObj) => {
|
| | | return pad(dateObj.month)
|
| | | },
|
| | | M: (dateObj) => {
|
| | | return dateObj.month
|
| | | },
|
| | | dd: (dateObj) => {
|
| | | return pad(dateObj.day)
|
| | | },
|
| | | d: (dateObj) => {
|
| | | return dateObj.day
|
| | | },
|
| | | hh: (dateObj) => {
|
| | | return pad(dateObj.hour)
|
| | | },
|
| | | h: (dateObj) => {
|
| | | return dateObj.hour
|
| | | },
|
| | | mm: (dateObj) => {
|
| | | return pad(dateObj.minute)
|
| | | },
|
| | | m: (dateObj) => {
|
| | | return dateObj.minute
|
| | | },
|
| | | ss: (dateObj) => {
|
| | | return pad(dateObj.second)
|
| | | },
|
| | | s: (dateObj) => {
|
| | | return dateObj.second
|
| | | },
|
| | | SSS: (dateObj) => {
|
| | | return pad(dateObj.millisecond, 3)
|
| | | },
|
| | | S: (dateObj) => {
|
| | | return dateObj.millisecond
|
| | | },
|
| | | }
|
| | |
|
| | | // 这都n年了iOS依然不认识2020-12-12,需要转换为2020/12/12
|
| | | function getDate(time) {
|
| | | if (time instanceof Date) {
|
| | | return time
|
| | | }
|
| | | switch (typeof time) {
|
| | | case 'string':
|
| | | {
|
| | | // 2020-12-12T12:12:12.000Z、2020-12-12T12:12:12.000
|
| | | if (time.indexOf('T') > -1) {
|
| | | return new Date(time)
|
| | | }
|
| | | return new Date(time.replace(/-/g, '/'))
|
| | | }
|
| | | default:
|
| | | return new Date(time)
|
| | | }
|
| | | }
|
| | |
|
| | | export function formatDate(date, format = 'yyyy/MM/dd hh:mm:ss') {
|
| | | if (!date && date !== 0) {
|
| | | return ''
|
| | | }
|
| | | date = getDate(date)
|
| | | const dateObj = {
|
| | | year: date.getFullYear(),
|
| | | month: date.getMonth() + 1,
|
| | | day: date.getDate(),
|
| | | hour: date.getHours(),
|
| | | minute: date.getMinutes(),
|
| | | second: date.getSeconds(),
|
| | | millisecond: date.getMilliseconds()
|
| | | }
|
| | | const tokenRegExp = /yyyy|yy|MM|M|dd|d|hh|h|mm|m|ss|s|SSS|SS|S/
|
| | | let flag = true
|
| | | let result = format
|
| | | while (flag) {
|
| | | flag = false
|
| | | result = result.replace(tokenRegExp, function(matched) {
|
| | | flag = true
|
| | | return parser[matched](dateObj)
|
| | | })
|
| | | }
|
| | | return result
|
| | | }
|
| | |
|
| | | export function friendlyDate(time, {
|
| | | locale = 'zh',
|
| | | threshold = [60000, 3600000],
|
| | | format = 'yyyy/MM/dd hh:mm:ss'
|
| | | }) {
|
| | | if (time === '-') {
|
| | | return time
|
| | | }
|
| | | if (!time && time !== 0) {
|
| | | return ''
|
| | | }
|
| | | const localeText = {
|
| | | zh: {
|
| | | year: '年',
|
| | | month: '月',
|
| | | day: '天',
|
| | | hour: '小时',
|
| | | minute: '分钟',
|
| | | second: '秒',
|
| | | ago: '前',
|
| | | later: '后',
|
| | | justNow: '刚刚',
|
| | | soon: '马上',
|
| | | template: '{num}{unit}{suffix}'
|
| | | },
|
| | | en: {
|
| | | year: 'year',
|
| | | month: 'month',
|
| | | day: 'day',
|
| | | hour: 'hour',
|
| | | minute: 'minute',
|
| | | second: 'second',
|
| | | ago: 'ago',
|
| | | later: 'later',
|
| | | justNow: 'just now',
|
| | | soon: 'soon',
|
| | | template: '{num} {unit} {suffix}'
|
| | | }
|
| | | }
|
| | | const text = localeText[locale] || localeText.zh
|
| | | let date = getDate(time)
|
| | | let ms = date.getTime() - Date.now()
|
| | | let absMs = Math.abs(ms)
|
| | | if (absMs < threshold[0]) {
|
| | | return ms < 0 ? text.justNow : text.soon
|
| | | }
|
| | | if (absMs >= threshold[1]) {
|
| | | return formatDate(date, format)
|
| | | }
|
| | | let num
|
| | | let unit
|
| | | let suffix = text.later
|
| | | if (ms < 0) {
|
| | | suffix = text.ago
|
| | | ms = -ms
|
| | | }
|
| | | const seconds = Math.floor((ms) / 1000)
|
| | | const minutes = Math.floor(seconds / 60)
|
| | | const hours = Math.floor(minutes / 60)
|
| | | const days = Math.floor(hours / 24)
|
| | | const months = Math.floor(days / 30)
|
| | | const years = Math.floor(months / 12)
|
| | | switch (true) {
|
| | | case years > 0:
|
| | | num = years
|
| | | unit = text.year
|
| | | break
|
| | | case months > 0:
|
| | | num = months
|
| | | unit = text.month
|
| | | break
|
| | | case days > 0:
|
| | | num = days
|
| | | unit = text.day
|
| | | break
|
| | | case hours > 0:
|
| | | num = hours
|
| | | unit = text.hour
|
| | | break
|
| | | case minutes > 0:
|
| | | num = minutes
|
| | | unit = text.minute
|
| | | break
|
| | | default:
|
| | | num = seconds
|
| | | unit = text.second
|
| | | break
|
| | | }
|
| | |
|
| | | if (locale === 'en') {
|
| | | if (num === 1) {
|
| | | num = 'a'
|
| | | } else {
|
| | | unit += 's'
|
| | | }
|
| | | }
|
| | |
|
| | | return text.template.replace(/{\s*num\s*}/g, num + '').replace(/{\s*unit\s*}/g, unit).replace(/{\s*suffix\s*}/g,
|
| | | suffix)
|
| | | }
|