Skip to content

Instantly share code, notes, and snippets.

@mholtzhausen
Last active February 14, 2020 08:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mholtzhausen/e3be7035257611b4cf9a9e852c255b8c to your computer and use it in GitHub Desktop.
Save mholtzhausen/e3be7035257611b4cf9a9e852c255b8c to your computer and use it in GitHub Desktop.
Date Formatting
const SECONDS = {
MINUTE: 60,
HOUR: 3600,
DAY: 86400,
WEEK: 604800,
MONTH: 2630016, //30.44 day month average
YEAR: 31557600, //based on 365.25 days per year
}
class DForm {
/**
*
* @param {Date} date
*/
constructor(date) {
if (date instanceof DForm) return date
this.Year = date.getFullYear()
this.Month = date.getMonth() + 1
this.Day = date.getDate()
this.Hour = date.getHours()
this.Minute = date.getMinutes()
this.Second = date.getSeconds()
this.Millisecond = date.getMilliseconds()
this.Weekday = date.getDay()
}
get DayOrd () {
let v = this.Day % 100;
let s = ["th", "st", "nd", "rd"]
return `${this.Day}${s[(v - 20) % 10] || s[v] || s[0]}` //stole this
}
get MonthPad () { return `${this.Month}`.padStart(2, '0') }
get DayPad () { return `${this.Day}`.padStart(2, '0') }
get HourPad () { return `${this.Hour}`.padStart(2, '0') }
get MinutePad () { return `${this.Minute}`.padStart(2, '0') }
get SecondPad () { return `${this.Second}`.padStart(2, '0') }
get Hour12 () { return `${this.Hour > 12 ? this.Hour % 12 : this.Hour}` }
get Hour12Pad () { return this.Hour12.padStart(2, '0') }
get AMPM () { return this.Hour >= 12 ? 'PM' : 'AM' }
get ampm () { return this.AMPM.toLowerCase() }
get MonthLong () { return ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][this.Month - 1] }
get MonthShort () { return ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][this.Month - 1] }
get DayLong () { return ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][this.Weekday] }
get DayShort () { return ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][this.Weekday] }
static parse (anyDate) {
if (!(anyDate instanceof Date)) anyDate = Date.parse(anyDate)
if (!anyDate) anyDate = new Date()
return new DForm(anyDate)
}
format (formatString) {
let formatted = `${formatString}`
let self = this
let matches = formatString.match(/\{([^\}]*)\}/g) || []
matches.forEach(function(attr) {
let prop = `${attr}`.trim().split('').slice(1, attr.length - 1).join('')
if (prop in self) {
formatted = formatted.replace(attr, self[prop])
}
})
return formatted;
}
/**
*
* @param {Object} adjustment The required adjustment config eg {year:1, minute:-5}
*/
adjust (adjustment = {}) {
adjustment = Object.assign({ years: 0, months: 0, days: 0, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 }, adjustment || {})
let d = this.date
d.setFullYear(d.getFullYear() + adjustment.years)
d.setMonth(d.getMonth() + adjustment.months)
d.setDate(d.getDate() + adjustment.days)
d.setHours(d.getHours() + adjustment.hours)
d.setMinutes(d.getMinutes() + adjustment.minutes)
d.setSeconds(d.getSeconds() + adjustment.seconds)
d.setMilliseconds(d.getMilliseconds() + adjustment.milliseconds)
return new DForm(d)
}
get date () {
return new Date(this.Year, this.Month - 1, this.Day, this.Hour, this.Minute, this.Second, this.Millisecond)
}
elapsed (date) {
if (date instanceof DForm) date = date.date
return Math.round((date.getTime() - this.date.getTime()) / 1000)
}
humanElapsed (date, max_seconds = 31557600, alt_format = null) {
let elapsed = this.elapsed(date)
let dir = elapsed < 0 ? ' ago' : ' from now'
elapsed = Math.abs(elapsed)
if (elapsed > max_seconds) return alt_format ? new DForm(date).format(alt_format) : null
let y = Math.floor(elapsed / SECONDS.YEAR)
let M = Math.floor(elapsed % SECONDS.YEAR / SECONDS.MONTH)
let d = Math.floor(elapsed % SECONDS.YEAR % SECONDS.MONTH / SECONDS.DAY)
let h = Math.floor(elapsed % SECONDS.YEAR % SECONDS.MONTH % SECONDS.DAY / SECONDS.DAY)
let m = Math.floor(elapsed % SECONDS.YEAR % SECONDS.MONTH % SECONDS.DAY % SECONDS.DAY / SECONDS.MINUTE)
let s = Math.floor(elapsed % SECONDS.YEAR % SECONDS.MONTH % SECONDS.DAY % SECONDS.DAY % SECONDS.MINUTE)
const dYears = () => [y ? `${y} years` : '', M ? `${M} months` : '', d ? `${d} days` : ''].filter(v => !!v).join(', ') + dir
const dMonths = () => [M ? `${M} months` : '', d ? `${d} days` : ''].filter(v => !!v).join(' and ') + dir
const dDays = () => [d ? `${d} days` : '', h ? `${h} hours` : ''].filter(v => !!v).join(', ') + dir
const dHours = () => [h ? `${h} hours` : '', m ? `${m} minutes` : ''].filter(v => !!v).join(' and ') + dir
const dMinutes = () => (m ? `${m} minutes` : '') + dir
const dSeconds = () => (s ? `${s} seconds` : '') + dir
if (y) return dYears()
if (M) return dMonths()
if (d) return dDays()
if (h) return dHours()
if (m) return dMinutes()
if (s) return dSeconds()
}
}
const DateFormats = {
HumanDate: '{Day} {MonthShort} {Year}',
HumanDateTime: '{Day} {MonthShort} {Year} at {Hour12}:{MinutePad} {ampm}',
HumanDateLong: '{DayLong}, {DayOrd} {MonthLong} {Year}',
HumanDateTimeLong: '{DayLong}, {DayOrd} {MonthLong} {Year} at {HourPad}h{MinutePad}',
ConciseDate: '{Day}-{Month}-{Year}',
ConciseDateTime: '{Day}-{Month}-{Year} {Hour}:{MinutePad}:{SecondPad}',
FormalDate: '{DayPad}/{MonthPad}/{Year}',
FormalDateTime: '{DayPad}/{MonthPad}/{Year} {HourPad}:{MinutePad}:{SecondPad}',
}
const rand = (min, max) => Math.trunc((Math.random() * (max - min + 1)) + min)
/**
* Testing
*/
const date1 = new DForm(new Date())
const date2 = date1.adjust({ days: -130, months: 0 })
const date3 = date1.adjust({ months: rand(0, 2), days: rand(0, 40), hours: rand(0, 15) })
/**************************************************
* DateFormats Test --- START
*************************Toggle with this space->* /
Object.keys(DateFormats).forEach(name => {
console.log(`${name}: `, date1.format(DateFormats[name]))
})
/**************************************************
* DateFormats Test --- END
**************************************************/
console.log('date1: ',date1.format(DateFormats.FormalDateTime))
console.log('date2: ',date2.format(DateFormats.FormalDateTime))
console.log('date3: ',date3.format(DateFormats.FormalDateTime))
console.log()
console.log('date 2 elapsed seconds', date1.elapsed(date2))
console.log('date 2 elapsed', date1.humanElapsed(date2))
console.log('date 2 elapsed with short ttl:', date1.humanElapsed(date2, SECONDS.DAY * 5))
console.log('date 2 elapsed with short ttl and alt format:', date1.humanElapsed(date2, SECONDS.DAY * 5, DateFormats.HumanDateTimeLong))
console.log()
console.log('date 3 elapsed seconds', date1.elapsed(date3))
console.log('date 3 elapsed', date1.humanElapsed(date3, SECONDS.YEAR * 3))
console.log('date 3 elapsed with short ttl:', date1.humanElapsed(date3, SECONDS.DAY * 5))
console.log('date 3 elapsed with short ttl and alt format:', date1.humanElapsed(date3, SECONDS.DAY * 5, DateFormats.HumanDateTimeLong))
/**************************************************
* Export Section --- START
*************************Toggle with this space->* /
module.exports = {
DateFormats,
DForm,
SECONDS
}
/**************************************************
* Export Section --- END
**************************************************/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment