From ee56583373ce0fd336d08d93379540ac6513284b Mon Sep 17 00:00:00 2001 From: Cameron Date: Thu, 29 Dec 2011 01:36:30 -0500 Subject: [PATCH 1/7] Made parsing account for timezone offsets that have no minute component (which is valid under ISO8601) --- jquery.timeago.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jquery.timeago.js b/jquery.timeago.js index 24ac69c7..06e2d7d7 100644 --- a/jquery.timeago.js +++ b/jquery.timeago.js @@ -64,7 +64,8 @@ var hours = minutes / 60; var days = hours / 24; var years = days / 365; - + + function substitute(stringOrFunction, number) { var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction; var value = ($l.numbers && $l.numbers[number]) || number; @@ -90,6 +91,7 @@ s = s.replace(/\.\d\d\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); }, From 9a2657fe2b9b41bb1affa84b6a484df8d7b50e21 Mon Sep 17 00:00:00 2001 From: Cameron Date: Sat, 31 Dec 2011 00:10:03 -0500 Subject: [PATCH 2/7] Added dateOnly option (which uses today/tomorrow/yesterday and is midnight-aware) --- jquery.timeago.js | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/jquery.timeago.js b/jquery.timeago.js index 06e2d7d7..3401af5c 100644 --- a/jquery.timeago.js +++ b/jquery.timeago.js @@ -29,6 +29,7 @@ settings: { refreshMillis: 60000, allowFuture: false, + dateOnly: false, strings: { prefixAgo: null, prefixFromNow: null, @@ -45,10 +46,13 @@ months: "%d months", year: "about a year", years: "%d years", + today: "today", + tomorrow: "tomorrow", + yesterday: "yesterday", numbers: [] } }, - inWords: function(distanceMillis) { + inWords: function(distanceMillis, originalDate) { var $l = this.settings.strings; var prefix = $l.prefixAgo; var suffix = $l.suffixAgo; @@ -64,8 +68,33 @@ var hours = minutes / 60; var days = hours / 24; var years = days / 365; - - + + if (this.settings.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; var value = ($l.numbers && $l.numbers[number]) || number; @@ -91,7 +120,7 @@ s = s.replace(/\.\d\d\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)$/,"$1:00"); // -04 -> -04:00 s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 return new Date(s); }, @@ -135,7 +164,7 @@ } function inWords(date) { - return $t.inWords(distance(date)); + return $t.inWords(distance(date), date); } function distance(date) { From 31e74f7af21758d8467b0d707120c7ad8ff1cec2 Mon Sep 17 00:00:00 2001 From: prasad83 Date: Fri, 3 Aug 2012 19:22:12 +0530 Subject: [PATCH 3/7] Enabled autodetecting date-only requirement Having timeago display datediff and timediff was required on page. To provide this ability, the format of display is determined by the initial value. The option to show dateOnly can also be controlled through timeago.settings --- jquery.timeago.js | 58 +++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/jquery.timeago.js b/jquery.timeago.js index 3401af5c..7c54118b 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,7 +31,7 @@ settings: { refreshMillis: 60000, allowFuture: false, - dateOnly: false, + dateOnly: false, // https://github.com/cameron314/jquery-timeago/ strings: { prefixAgo: null, prefixFromNow: null, @@ -46,13 +48,15 @@ months: "%d months", year: "about a year", years: "%d years", + wordSeparator: " ", + numbers: [], + today: "today", tomorrow: "tomorrow", - yesterday: "yesterday", - numbers: [] + yesterday: "yesterday" } }, - inWords: function(distanceMillis, originalDate) { + inWords: function(distanceMillis, originalDate, dateOnly) { var $l = this.settings.strings; var prefix = $l.prefixAgo; var suffix = $l.suffixAgo; @@ -68,8 +72,8 @@ var hours = minutes / 60; var days = hours / 24; var years = days / 365; - - if (this.settings.dateOnly) { + + 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(), @@ -93,7 +97,6 @@ hours = 48; days = Math.abs(daysDifference); } - function substitute(stringOrFunction, number) { var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction; @@ -106,29 +109,31 @@ 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) { - // 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"); + var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title"); return $t.parse(iso8601); + }, + isTime: function(elem) { + // jQuery's `is()` doesn't play well with HTML5 in IE + return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time"); } }); @@ -146,7 +151,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; } @@ -156,15 +161,18 @@ 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), date); + function inWords(date, dateOnly) { + return $t.inWords(distance(date), date, dateOnly); } function distance(date) { From bc2b2dcf8d5b3e2371239551f59a565e2fe141b1 Mon Sep 17 00:00:00 2001 From: cameron314 Date: Mon, 20 Aug 2012 00:18:52 -0400 Subject: [PATCH 4/7] Re-applied clobbered change after merge: Made parsing account for timezone offsets that have no minute component (which is valid under ISO8601) --- jquery.timeago.js | 1 + 1 file changed, 1 insertion(+) diff --git a/jquery.timeago.js b/jquery.timeago.js index 7c54118b..207db2d0 100644 --- a/jquery.timeago.js +++ b/jquery.timeago.js @@ -124,6 +124,7 @@ 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); }, From e48153d3f49e9f58cde7685d007decbc67cb7616 Mon Sep 17 00:00:00 2001 From: prasad83 Date: Thu, 20 Sep 2012 23:26:08 +0530 Subject: [PATCH 5/7] Enabled timezone conversion support (utc2local). data-tz-change="utc2local" attribute on element will covert the specified time to Localtime. This is a stop-gap implementation, it can be further improved. --- jquery.timeago.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/jquery.timeago.js b/jquery.timeago.js index 7c54118b..3702a98e 100644 --- a/jquery.timeago.js +++ b/jquery.timeago.js @@ -127,9 +127,15 @@ s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 return new Date(s); }, + parseUTCToLocal: function(iso8601) { + var utc = $t.parse(iso8601); + utc.setTime(utc.getTime() - utc.getTimezoneOffset()*60*1000); + return utc; + }, datetime: function(elem) { var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title"); - return $t.parse(iso8601); + var tzchange = $(elem).data('tz-change'); + return (tzchange == "utc2local")? $t.parseUTCToLocal(iso8601) : $t.parse(iso8601); }, isTime: function(elem) { // jQuery's `is()` doesn't play well with HTML5 in IE From b7c9b48af29807bcc338229c9a5dd00e3aaa2ced Mon Sep 17 00:00:00 2001 From: prasad83 Date: Tue, 25 Sep 2012 16:44:17 +0530 Subject: [PATCH 6/7] Configure Timeago to work in UTCMode. Enabled timeago computation reference UTC value (instead of Local timezone), Control using the attribute "data-tz-utc" on DOM element. XDate (https://github.com/arshaw/xdate) library is required at runtime. --- jquery.timeago.js | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/jquery.timeago.js b/jquery.timeago.js index 3702a98e..4f438fa1 100644 --- a/jquery.timeago.js +++ b/jquery.timeago.js @@ -127,20 +127,22 @@ s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 return new Date(s); }, - parseUTCToLocal: function(iso8601) { - var utc = $t.parse(iso8601); - utc.setTime(utc.getTime() - utc.getTimezoneOffset()*60*1000); - return utc; - }, datetime: function(elem) { var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title"); - var tzchange = $(elem).data('tz-change'); - return (tzchange == "utc2local")? $t.parseUTCToLocal(iso8601) : $t.parse(iso8601); + 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 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() { @@ -182,7 +184,8 @@ } 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 From a61721a3ebcc89a3e90bc84eb7e551c6cb654928 Mon Sep 17 00:00:00 2001 From: prasad83 Date: Mon, 8 Oct 2012 13:21:11 +0530 Subject: [PATCH 7/7] Updated enhancement of UTC-to-Localtime support. Updated enhancement of UTC-to-Localtime support in README.markdown --- README.markdown | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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))