diff --git a/README.markdown b/README.markdown index 85b007a8..ec1933a6 100644 --- a/README.markdown +++ b/README.markdown @@ -41,6 +41,18 @@ As time passes, the timestamps will automatically update. **For different language configurations**: [http://gist.github.com/6251](http://gist.github.com/6251) +# Enhancement: (UTC to Localtime) + +```html + +``` + +2010-10-20 09:20:17 - will be treated as UTC and translated to 2010-10-20 14:50:17 GMT+5:30 (if client-browser is using IST). + +__NOTE: This feature depends on [XDate](http://arshaw.com/xdate/) support at runtime __ + + + ## Author [Ryan McGeary](http://ryan.mcgeary.org) ([@rmm5t](http://twitter.com/rmm5t)) diff --git a/jquery.timeago.js b/jquery.timeago.js index 24ac69c7..26942159 100644 --- a/jquery.timeago.js +++ b/jquery.timeago.js @@ -3,7 +3,7 @@ * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago"). * * @name timeago - * @version 0.10.0 + * @version 0.11.4 * @requires jQuery v1.2.3+ * @author Ryan McGeary * @license MIT License - http://www.opensource.org/licenses/mit-license.php @@ -11,7 +11,7 @@ * For usage and examples, visit: * http://timeago.yarp.com/ * - * Copyright (c) 2008-2011, Ryan McGeary (ryanonjavascript -[at]- mcgeary [*dot*] org) + * Copyright (c) 2008-2012, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org) */ (function($) { $.timeago = function(timestamp) { @@ -19,6 +19,8 @@ return inWords(timestamp); } else if (typeof timestamp === "string") { return inWords($.timeago.parse(timestamp)); + } else if (typeof timestamp === "number") { + return inWords(new Date(timestamp)); } else { return inWords($.timeago.datetime(timestamp)); } @@ -29,6 +31,7 @@ settings: { refreshMillis: 60000, allowFuture: false, + dateOnly: false, // https://github.com/cameron314/jquery-timeago/ strings: { prefixAgo: null, prefixFromNow: null, @@ -45,10 +48,15 @@ months: "%d months", year: "about a year", years: "%d years", - numbers: [] + wordSeparator: " ", + numbers: [], + + today: "today", + tomorrow: "tomorrow", + yesterday: "yesterday" } }, - inWords: function(distanceMillis) { + inWords: function(distanceMillis, originalDate, dateOnly) { var $l = this.settings.strings; var prefix = $l.prefixAgo; var suffix = $l.suffixAgo; @@ -64,6 +72,31 @@ var hours = minutes / 60; var days = hours / 24; var years = days / 365; + + if (this.settings.dateOnly || dateOnly) { + // Day difference code from https://github.com/brianmhunt/jquery-timeago/commit/dfbef678758da942127fc60a10638f12dd2c3ee2#commitcomment-97699 + var dateWithoutTime = new Date( + originalDate.getFullYear(), + originalDate.getMonth(), + originalDate.getDate() + ); + + var daysDifference = Math.floor((new Date() - dateWithoutTime) / (1000 * 60 * 60 * 24)); + + if (Math.abs(daysDifference) <= 1) { + var word = + daysDifference == -1 && $l.tomorrow || + daysDifference == 0 && $l.today || + $l.yesterday; + return $.trim(word); + } + + // Not today, tomorrow, or yesterday; subsequent code will choose words, so make + // sure that correct day difference (knowing about midnight) is used (since it's more + // than one day's difference, hours should be >= 48 even if the actual span is less) + hours = 48; + days = Math.abs(daysDifference); + } function substitute(stringOrFunction, number) { var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction; @@ -76,29 +109,41 @@ minutes < 45 && substitute($l.minutes, Math.round(minutes)) || minutes < 90 && substitute($l.hour, 1) || hours < 24 && substitute($l.hours, Math.round(hours)) || - hours < 48 && substitute($l.day, 1) || - days < 30 && substitute($l.days, Math.floor(days)) || - days < 60 && substitute($l.month, 1) || - days < 365 && substitute($l.months, Math.floor(days / 30)) || - years < 2 && substitute($l.year, 1) || - substitute($l.years, Math.floor(years)); + hours < 42 && substitute($l.day, 1) || + days < 30 && substitute($l.days, Math.round(days)) || + days < 45 && substitute($l.month, 1) || + days < 365 && substitute($l.months, Math.round(days / 30)) || + years < 1.5 && substitute($l.year, 1) || + substitute($l.years, Math.round(years)); - return $.trim([prefix, words, suffix].join(" ")); + var separator = $l.wordSeparator === undefined ? " " : $l.wordSeparator; + return $.trim([prefix, words, suffix].join(separator)); }, parse: function(iso8601) { var s = $.trim(iso8601); - s = s.replace(/\.\d\d\d+/,""); // remove milliseconds + s = s.replace(/\.\d+/,""); // remove milliseconds s = s.replace(/-/,"/").replace(/-/,"/"); s = s.replace(/T/," ").replace(/Z/," UTC"); + s = s.replace(/([\+\-]\d\d)$/,"$1:00"); // -04 -> -04:00 s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 return new Date(s); }, datetime: function(elem) { + var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title"); + return ($(elem).attr('data-tz-utc') != undefined)? $t.XDate(iso8601) : $t.parse(iso8601); + }, + isTime: function(elem) { // jQuery's `is()` doesn't play well with HTML5 in IE - var isTime = $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time"); - var iso8601 = isTime ? $(elem).attr("datetime") : $(elem).attr("title"); - return $t.parse(iso8601); - } + return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time"); + }, + XDate: function(iso8601) { + // XDate (http://arshaw.com/xdate) not found? - fallback on default + if (typeof XDate == 'undefined') { + return (iso8601 == undefined)? new Date() : $t.parse(iso8601); + } else { + return (iso8601 == undefined)? new XDate(true): new XDate(iso8601.replace(/\//,'-'), true); + } + } }); $.fn.timeago = function() { @@ -115,7 +160,7 @@ function refresh() { var data = prepareData(this); if (!isNaN(data.datetime)) { - $(this).text(inWords(data.datetime)); + $(this).text(inWords(data.datetime, $(this).data("timeago-dateonly"))); } return this; } @@ -125,19 +170,23 @@ if (!element.data("timeago")) { element.data("timeago", { datetime: $t.datetime(element) }); var text = $.trim(element.text()); - if (text.length > 0) { + if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) { element.attr("title", text); } + // FIX: Compute dateonly setting per element + var dateonly = (element.attr("title").indexOf(':') == -1); + element.data("timeago-dateonly", dateonly); } return element.data("timeago"); } - function inWords(date) { - return $t.inWords(distance(date)); + function inWords(date, dateOnly) { + return $t.inWords(distance(date), date, dateOnly); } function distance(date) { - return (new Date().getTime() - date.getTime()); + //return (new Date().getTime() - date.getTime()); + return ($t.XDate().getTime() - date.getTime()); } // fix for IE6 suckage