Last active
August 25, 2018 04:41
-
-
Save rhwlo/fbb02ded6c48de68aefa1469405511e0 to your computer and use it in GitHub Desktop.
parse duration strings in JS and format them
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script> | |
const formatDuration = ({hours, minutes, seconds}) => { | |
const finalSeconds = seconds % 60; | |
const finalMinutes = ((minutes || 0) + Math.floor(seconds / 60)) % 60; | |
const finalHours = Math.floor((minutes || 0) / 60 + seconds / 3600) + (hours || 0); | |
const formattedHours = (finalHours && finalHours > 0) ? `${finalHours}h` : ''; | |
const formattedMinutes = (finalMinutes && finalMinutes > 0) ? `${finalMinutes}m` : ''; | |
const formattedSeconds = (finalSeconds && finalSeconds > 0) ? `${finalSeconds}s` : ''; | |
return `${formattedHours}${formattedMinutes}${formattedSeconds}`; | |
}; | |
const totalSeconds = ({hours, minutes, seconds}) => { | |
return (hours || 0) * 3600 + (minutes || 0) * 60 + (seconds || 0); | |
} | |
const HMS_REGEX = /^(?:([0-9]+)h)?(?:([0-9]+)m)?(?:([0-9]+)s)?$/; | |
const COLON_REGEX = /^([0-9]+:)?([0-9]+:)?[0-9]+$/; | |
const parseDurationString = durationString => { | |
if (durationString.match(COLON_REGEX)) { | |
const [seconds, mMinutes, mHours] = durationString.split(":").reverse().map(i => parseInt(i)); | |
return {seconds, minutes: mMinutes || 0, hours: mHours || 0}; | |
} | |
const hmsMatch = durationString.match(HMS_REGEX); | |
if (hmsMatch) { | |
return {hours: parseInt(hmsMatch[1] || '0'), | |
minutes: parseInt(hmsMatch[2] || '0'), | |
seconds: parseInt(hmsMatch[3] || '0')}; | |
} | |
throw new Error(`Couldn't parse duration string "${durationString}"`); | |
}; | |
Vue.component('v-email-field', { | |
props: { | |
'value': {type: String, required: true}, | |
'domain': {type: String, required: true}, | |
}, | |
computed: { | |
suffix: function () { | |
return this.value.includes("@") ? "" : `@${this.domain}` | |
} | |
}, | |
template: "<v-text-field reverse v-model='value' :prefix='suffix'></v-text-field>" | |
}); | |
Vue.component('v-duration-entry', { | |
props: { | |
'value': { | |
type: Number, | |
required: true | |
}, | |
'formatString': { | |
type: String, | |
default: '%h:%m:%s' | |
} | |
}, | |
data() { | |
return { | |
formattedDuration: formatDuration({seconds: this.value}), | |
} | |
}, | |
template: '<v-text-field v-model="formattedDuration" v-on:blur="refreshDuration"></v-text-field>', | |
methods: { | |
refreshDuration () { | |
this.value = parseDurationString(this.formattedDuration); | |
this.formattedDuration = formatDuration(this.value); | |
this.$emit('input', totalSeconds(this.value)); | |
} | |
} | |
}); | |
new Vue({ | |
el: "#app", | |
data() { | |
return { | |
message: "hi", | |
email: "foo", | |
secondsForThing: 300, | |
} | |
} | |
}); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment