Skip to content

Instantly share code, notes, and snippets.

@rhwlo
Last active August 25, 2018 04:41
Show Gist options
  • Save rhwlo/fbb02ded6c48de68aefa1469405511e0 to your computer and use it in GitHub Desktop.
Save rhwlo/fbb02ded6c48de68aefa1469405511e0 to your computer and use it in GitHub Desktop.
parse duration strings in JS and format them
<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