Skip to content

Instantly share code, notes, and snippets.

@kneath
Created January 13, 2009 10:45
Show Gist options
  • Save kneath/46398 to your computer and use it in GitHub Desktop.
Save kneath/46398 to your computer and use it in GitHub Desktop.
/**
* Format any UTC timestamp on the page to the users local timezone.
*/
var DateFormat = {
autoParse: function(){
$$('span.timestamp').each(function(span) {
var utc = Date.parseUTC(span.getAttribute('utc'));
var rel = span.getAttribute('format');
span.set('html', rel == 'words' ? utc.timeAgoInWords() : utc.strftime(rel))
});
}
}
var Locale = new Hash({
monthNames: (typeof Date.CultureInfo == 'undefined' ? 'January February March April May June July August September October November December'.split(' ') : Date.CultureInfo.monthNames),
dayNames: (typeof Date.CultureInfo == 'undefined' ? 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday'.split(' ') : Date.CultureInfo.dayNames)
});
String.prototype.pad = function(l, s, t){
s = s || " ";
return (l -= this.length) > 0 ? (s = new Array(Math.ceil(l / s.length) + 1).join(s)).substr(0, t = !t ? l : t == 1 ? 0 : Math.ceil(l / 2)) + this + s.substr(0, l - t) : this;
};
$extend(Date.prototype, {
/**
* Given a formatted string, replace the necessary items and return.
* Example: Time.now().strftime("%B %d, %Y") => February 11, 2008
* @param {String} format The formatted string used to format the results
*/
strftime: function(format) {
var day = this.getDay(), month = this.getMonth();
var hours = this.getHours(), minutes = this.getMinutes();
function pad(num) { return num.toString().pad(2, '0');};
return format.replace(/\%([aAbBcdeHImMpSwyY])/g, "{$1}").substitute({
'a': Locale.get('dayNames')[day].substr(0, 3),
'A': Locale.get('dayNames')[day],
'b': Locale.get('monthNames')[month].substr(0, 3),
'B': Locale.get('monthNames')[month],
'c': this.toString(),
'd': pad(this.getDate()),
'H': pad(hours),
'I': (hours % 12 == 0) ? 12 : pad(hours % 12),
'm': pad(month + 1),
'e': month + 1,
'M': pad(minutes),
'p': hours >= 12 ? 'PM' : 'AM',
'S': pad(this.getSeconds()),
'w': day,
'y': pad(this.getFullYear() % 100),
'Y': this.getFullYear().toString()
});
},
timeAgoInWords: function() {
var relative_to = (arguments.length > 0) ? arguments[1] : new Date();
return Date.distanceOfTimeInWords(this, relative_to, arguments[2]);
}
});
$extend(Date, {
/**
* Common formats passed to strftime
*/
strftimeFormats: {
time: "%I:%M %p",
day: "%B %d",
short: '%b %d',
dayName: "%A"
},
/**
* Get an array back with hours, minutes and seconds from now to a future date.
* @param {Date} to The future time used to get equate the difference
* @return {Array} [hours, minutes, seconds]
*/
differenceFromNow: function(to) {
var seconds = Math.ceil((new Date().getTime() - to.getTime()) / 1000);
var hours = Math.floor(seconds / 3600).toPaddedString(2);
seconds = Math.floor(seconds % 3600);
var minutes = Math.floor(seconds / 60).toPaddedString(2);
seconds = (seconds % 60).toPaddedString(2);
return [hours, minutes, seconds];
},
/**
* Parse a string date and return a UTC date
* @param {String} value Formatted date string
* @return Date
*/
parseUTC: function(value) {
var localDate = new Date(value);
var utcSeconds = Date.UTC(localDate.getFullYear(), localDate.getMonth(), localDate.getDate(), localDate.getHours(), localDate.getMinutes(), localDate.getSeconds())
return new Date(utcSeconds);
},
/**
* Return the distance of time in words between two Dates
* Example: '5 days ago', 'about an hour ago'
* @param {Date} fromTime The start date to use in the calculation
* @param {Date} toTime The end date to use in the calculation
* @param {Boolean} Include the time in the output
*/
distanceOfTimeInWords: function(fromTime, toTime, includeTime) {
var delta = parseInt((toTime.getTime() - fromTime.getTime()) / 1000);
if(delta < 60) {
return 'less than a minute ago';
} else if(delta < 120) {
return 'about a minute ago';
} else if(delta < (45*60)) {
return (parseInt(delta / 60)).toString() + ' minutes ago';
} else if(delta < (120*60)) {
return 'about an hour ago';
} else if(delta < (24*60*60)) {
return 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago';
} else if(delta < (48*60*60)) {
return '1 day ago';
} else {
var days = (parseInt(delta / 86400)).toString();
if(days > 5) {
var fmt = '%B %d'
if(toTime.getYear() != fromTime.getYear()) { fmt += ', %Y' }
if(includeTime) fmt += ' %I:%M %p'
return fromTime.strftime(fmt);
} else {
return days + " days ago"
}
}
}
});
// Time helpers by MARTIN STRÖM
Object.extend(Number.prototype, {
seconds: function() {
return this * 1000;
},
minutes: function() {
return this * (60).seconds();
},
hours: function() {
return this * (60).minutes();
},
days: function() {
return this * (24).hours();
},
weeks: function(args) {
return this * (7).days();
},
fortnights: function() {
return this * (2).weeks();
},
months: function() {
return this * (30).days();
},
years: function() {
return parseInt(this * (365.25).days())
},
since: function(time) {
time = time || new Date();
if (time instanceof Date) time = time.getTime();
return this + time;
},
ago: function(time) {
time = time || new Date();
if (time instanceof Date) time = time.getTime();
return time - this;
},
toDate: function() {
var date = new Date();
date.setTime(this);
return date;
}
});
Object.extend(Number.prototype, {
second: Number.prototype.seconds,
minute: Number.prototype.minutes,
hour: Number.prototype.hours,
day: Number.prototype.days,
week: Number.prototype.weeks,
fortnight: Number.prototype.fortnights,
month: Number.prototype.months,
year: Number.prototype.years,
from_now: Number.prototype.since,
fromNow: Number.prototype.since,
until: Number.prototype.ago
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment