Skip to content

Instantly share code, notes, and snippets.

@Atinux
Created March 5, 2021 15:29
Show Gist options
  • Save Atinux/32fbbca210df1f3fd8580ce8addc2403 to your computer and use it in GitHub Desktop.
Save Atinux/32fbbca210df1f3fd8580ce8addc2403 to your computer and use it in GitHub Desktop.
<template>
<time :datetime="date" :title="date">{{ timeago }}</time>
</template>
<script>
const units = [
{ max: 2760000, value: 60000, name: 'minute', short: 'm', past: 'a minute ago', future: 'in a minute' },
{ max: 72000000, value: 3600000, name: 'hour', short: 'h', past: 'an hour ago', future: 'in an hour' },
{ max: 518400000, value: 86400000, name: 'day', short: 'd', past: 'yesterday', future: 'tomorrow' },
{ max: 2419200000, value: 604800000, name: 'week', short: 'w', past: 'last week', future: 'in a week' },
{ max: 28512000000, value: 2592000000, name: 'month', short: 'mo', past: 'last month', future: 'in a month' },
{ max: Infinity, value: 31536000000, name: 'year', short: 'y', past: 'last year', future: 'in a year' }
]
export default {
props: {
datetime: {
type: [Date, String, Number],
required: true
},
autoUpdate: {
type: [Number, Boolean],
default: 60
},
short: {
type: Boolean,
default: true
},
max: {
type: String,
default: null,
validator (value) {
return [null, 'minute', 'hour', 'day', 'week', 'month', 'year'].includes(value)
}
}
},
data () {
return {
timeago: this.getTimeago()
}
},
computed: {
date () {
return new Intl.DateTimeFormat(navigator.language, {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
timeZoneName: 'short'
}).format(new Date(this.datetime))
}
},
watch: {
datetime () {
this.timeago = this.getTimeago()
},
short () {
this.timeago = this.getTimeago()
},
max () {
this.timeago = this.getTimeago()
},
autoUpdate (newValue) {
this.stopUpdater()
if (newValue) {
this.startUpdater()
}
}
},
mounted () {
this.startUpdater()
},
activated () {
this.startUpdater()
},
deactivated () {
this.stopUpdater()
},
beforeDestroy () {
this.stopUpdater()
},
methods: {
getTimeago () {
const diff = Date.now() - new Date(this.datetime).getTime()
// less than a minute
if (Math.abs(diff) < 60000) {
return 'just now'
}
for (const unit of units) {
if (Math.abs(diff) < unit.max || (this.max && unit.name === this.max)) {
return this.format(diff, unit)
}
}
},
format (diff, unit) {
const val = Math.round(Math.abs(diff) / unit.value)
if (diff < 0) {
return val <= 1 ? unit.future : `in ${val}${this.short ? unit.short : ` ${unit.name}s`}`
}
return val <= 1 ? this.short ? `1${unit.short} ago` : unit.past : `${val}${this.short ? unit.short : ` ${unit.name}s`} ago`
},
startUpdater () {
if (this.autoUpdate) {
const interval = (this.autoUpdate === true ? 60 : this.autoUpdate) * 1000
this._updater = setInterval(() => {
this.timeago = this.getTimeago()
}, interval)
}
},
stopUpdater () {
if (this._updater) {
clearInterval(this.updater)
this.updater = null
}
}
}
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment