Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Another dateOnly option implementation, plus a minor ISO8601 parsing improvement #48

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
12 changes: 12 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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
<abbr class="timeago" title="2010-10-20 09:20:17" data-tz-utc></abbr>
```

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))
Expand Down
91 changes: 70 additions & 21 deletions jquery.timeago.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,24 @@
* 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
*
* 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) {
if (timestamp instanceof Date) {
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));
}
Expand All @@ -29,6 +31,7 @@
settings: {
refreshMillis: 60000,
allowFuture: false,
dateOnly: false, // https://github.com/cameron314/jquery-timeago/
strings: {
prefixAgo: null,
prefixFromNow: null,
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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() {
Expand All @@ -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;
}
Expand All @@ -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
Expand Down