Commits

Stephen McKamey committed 6f8831f

fixing ceiling bug; improving readability

Comments (0)

Files changed (3)

 /**
- * @fileoverview countdown.js v2.2.1
+ * @fileoverview countdown.js v2.2.2
  * 
  * Copyright (c)2006-2011 Stephen M. McKamey
  * Licensed under the MIT License (http://bitbucket.org/mckamey/countdown.js/LICENSE.txt)
 
 	/**
 	 * @private
+	 * @param {number} x number
+	 * @return {number}
+	 */
+	var ceil = Math.ceil;
+
+	/**
+	 * @private
+	 * @param {number} x number
+	 * @return {number}
+	 */
+	var floor = Math.floor;
+
+	/**
+	 * @private
+	 * @param {number} x number
+	 * @return {number}
+	 */
+	var round = Math.round;
+
+	/**
+	 * @private
 	 * @param {Date} ref reference date
 	 * @param {number} shift number of months to shift
 	 * @return {number} number of days shifted
 		ref.setUTCMonth( ref.getUTCMonth() + shift );
 
 		// this is the trickiest since months vary in length
-		// Math.round(x) => ~~(0.5+x)
-		return ~~(0.5 + (ref.getTime() - prevTime) / MILLISECONDS_PER_DAY);
+		return round( (ref.getTime() - prevTime) / MILLISECONDS_PER_DAY );
 	}
 
 	/**
 	 * @param {Timespan} ts
 	 */
 	function ripple(ts) {
-		// https://github.com/jed/140bytes/wiki/Byte-saving-techniques
-		// Math.ceil(x) => ~~(1 + x)
-		// Math.floor(x) => ~~(x)
-		// Math.round(x) => ~~(0.5 + x)
-
 		var x;
 
 		if (ts.milliseconds < 0) {
 			// ripple seconds down to milliseconds
-			x = ~~(1 -ts.milliseconds / MILLISECONDS_PER_SECOND);
+			x = ceil(-ts.milliseconds / MILLISECONDS_PER_SECOND);
 			ts.seconds -= x;
 			ts.milliseconds += x * MILLISECONDS_PER_SECOND;
 
 		} else if (ts.milliseconds >= MILLISECONDS_PER_SECOND) {
 			// ripple milliseconds up to seconds
-			ts.seconds += ~~(ts.milliseconds / MILLISECONDS_PER_SECOND);
+			ts.seconds += floor(ts.milliseconds / MILLISECONDS_PER_SECOND);
 			ts.milliseconds %= MILLISECONDS_PER_SECOND;
 		}
 
 		if (ts.seconds < 0) {
 			// ripple minutes down to seconds
-			x = ~~(1 -ts.seconds / SECONDS_PER_MINUTE);
+			x = ceil(-ts.seconds / SECONDS_PER_MINUTE);
 			ts.minutes -= x;
 			ts.seconds += x * SECONDS_PER_MINUTE;
 
 		} else if (ts.seconds >= SECONDS_PER_MINUTE) {
 			// ripple seconds up to minutes
-			ts.minutes += ~~(ts.seconds / SECONDS_PER_MINUTE);
+			ts.minutes += floor(ts.seconds / SECONDS_PER_MINUTE);
 			ts.seconds %= SECONDS_PER_MINUTE;
 		}
 
 		if (ts.minutes < 0) {
 			// ripple hours down to minutes
-			x = ~~(1 - ts.minutes / MINUTES_PER_HOUR);
+			x = ceil(-ts.minutes / MINUTES_PER_HOUR);
 			ts.hours -= x;
 			ts.minutes += x * MINUTES_PER_HOUR;
 
 		} else if (ts.minutes >= MINUTES_PER_HOUR) {
 			// ripple minutes up to hours
-			ts.hours += ~~(ts.minutes / MINUTES_PER_HOUR);
+			ts.hours += floor(ts.minutes / MINUTES_PER_HOUR);
 			ts.minutes %= MINUTES_PER_HOUR;
 		}
 
 		if (ts.hours < 0) {
 			// ripple days down to hours
-			x = ~~(1 -ts.hours / HOURS_PER_DAY);
+			x = ceil(-ts.hours / HOURS_PER_DAY);
 			ts.days -= x;
 			ts.hours += x * HOURS_PER_DAY;
 
 		} else if (ts.hours >= HOURS_PER_DAY) {
 			// ripple hours up to days
-			ts.days += ~~(ts.hours / HOURS_PER_DAY);
+			ts.days += floor(ts.hours / HOURS_PER_DAY);
 			ts.hours %= HOURS_PER_DAY;
 		}
 
 		if (ts.days < 0) {
 			// ripple months down to days
-			x = ~~(1 -ts.days / MIN_DAYS_PER_MONTH);
+			x = ceil(-ts.days / MIN_DAYS_PER_MONTH);
 			ts.months -= x;
 			ts.days += borrowMonths(ts.refMonth, x);
 		}
 
 		if (ts.days >= DAYS_PER_WEEK) {
 			// ripple days up to weeks
-			ts.weeks += ~~(ts.days / DAYS_PER_WEEK);
+			ts.weeks += floor(ts.days / DAYS_PER_WEEK);
 			ts.days %= DAYS_PER_WEEK;
 		}
 
 		if (ts.months < 0) {
 			// ripple years down to months
-			x = ~~(1 -ts.months / MONTHS_PER_YEAR);
+			x = ceil(-ts.months / MONTHS_PER_YEAR);
 			ts.years -= x;
 			ts.months += x * MONTHS_PER_YEAR;
 
 		} else if (ts.months >= MONTHS_PER_YEAR) {
 			// ripple months up to years
-			ts.years += ~~(ts.months / MONTHS_PER_YEAR);
+			ts.years += floor(ts.months / MONTHS_PER_YEAR);
 			ts.months %= MONTHS_PER_YEAR;
 		}
 
 
 		if (ts.years >= YEARS_PER_DECADE) {
 			// ripple years up to decades
-			ts.decades += ~~(ts.years / YEARS_PER_DECADE);
+			ts.decades += floor(ts.years / YEARS_PER_DECADE);
 			ts.years %= YEARS_PER_DECADE;
 
 			if (ts.decades >= DECADES_PER_CENTURY) {
 				// ripple decades up to centuries
-				ts.centuries += ~~(ts.decades / DECADES_PER_CENTURY);
+				ts.centuries += floor(ts.decades / DECADES_PER_CENTURY);
 				ts.decades %= DECADES_PER_CENTURY;
 
 				if (ts.centuries >= CENTURIES_PER_MILLENNIUM) {
 					// ripple centuries up to millennia
-					ts.millennia += ~~(ts.centuries / CENTURIES_PER_MILLENNIUM);
+					ts.millennia += floor(ts.centuries / CENTURIES_PER_MILLENNIUM);
 					ts.centuries %= CENTURIES_PER_MILLENNIUM;
 				}
 			}
 
 			if (ts.days >= DAYS_PER_WEEK) {
 				// ripple day overflow back up to weeks
-				ts.weeks += ~~(ts.days / DAYS_PER_WEEK);
+				ts.weeks += floor(ts.days / DAYS_PER_WEEK);
 				ts.days %= DAYS_PER_WEEK;
 			}
 		}
 			callback = start;
 			start = null;
 
-		} else if (start !== null && isFinite(start)) {
-			start = new Date(start);
+		} else if (!(start instanceof Date)) {
+			start = (start !== null && isFinite(start)) ? new Date(start) : null;
 		}
 
 		// ensure end date
 			callback = end;
 			end = null;
 
-		} else if (end !== null && isFinite(end)) {
-			end = new Date(end);
+		} else if (!(end instanceof Date)) {
+			end = (end !== null && isFinite(end)) ? new Date(end) : null;
 		}
 
-		start = (start instanceof Date) ? start : null;
-		end = (end instanceof Date) ? end : null;
-
 		if (!start && !end) {
 			// used for unit testing
 			return new Timespan();
-var module,countdown=function(j){function k(a,b){var c=a.getTime();a.setUTCMonth(a.getUTCMonth()+b);return~~(0.5+(a.getTime()-c)/864E5)}function g(a,b,c){return a+" "+(a===1?b:c)}function h(){}function l(a,b,c,e){a.start=b;a.end=c;a.units=e;a.value=c.getTime()-b.getTime();if(a.value<0)var d=c,c=b,b=d;a.refMonth=new Date(b.getFullYear(),b.getMonth(),15);try{a.millennia=0;a.centuries=0;a.decades=0;a.years=c.getUTCFullYear()-b.getUTCFullYear();a.months=c.getUTCMonth()-b.getUTCMonth();a.weeks=0;a.days=
-c.getUTCDate()-b.getUTCDate();a.hours=c.getUTCHours()-b.getUTCHours();a.minutes=c.getUTCMinutes()-b.getUTCMinutes();a.seconds=c.getUTCSeconds()-b.getUTCSeconds();a.milliseconds=c.getUTCMilliseconds()-b.getUTCMilliseconds();var f;a.milliseconds<0?(f=~~(1-a.milliseconds/1E3),a.seconds-=f,a.milliseconds+=f*1E3):a.milliseconds>=1E3&&(a.seconds+=~~(a.milliseconds/1E3),a.milliseconds%=1E3);a.seconds<0?(f=~~(1-a.seconds/60),a.minutes-=f,a.seconds+=f*60):a.seconds>=60&&(a.minutes+=~~(a.seconds/60),a.seconds%=
-60);a.minutes<0?(f=~~(1-a.minutes/60),a.hours-=f,a.minutes+=f*60):a.minutes>=60&&(a.hours+=~~(a.minutes/60),a.minutes%=60);a.hours<0?(f=~~(1-a.hours/24),a.days-=f,a.hours+=f*24):a.hours>=24&&(a.days+=~~(a.hours/24),a.hours%=24);a.days<0&&(f=~~(1-a.days/28),a.months-=f,a.days+=k(a.refMonth,f));a.days>=7&&(a.weeks+=~~(a.days/7),a.days%=7);a.months<0?(f=~~(1-a.months/12),a.years-=f,a.months+=f*12):a.months>=12&&(a.years+=~~(a.months/12),a.months%=12);a.years>=10&&(a.decades+=~~(a.years/10),a.years%=
-10,a.decades>=10&&(a.centuries+=~~(a.decades/10),a.decades%=10,a.centuries>=10&&(a.millennia+=~~(a.centuries/10),a.centuries%=10)));e&1024||(a.centuries+=a.millennia*10,delete a.millennia);e&512||(a.decades+=a.centuries*10,delete a.centuries);e&256||(a.years+=a.decades*10,delete a.decades);e&128||(a.months+=a.years*12,delete a.years);!(e&64)&&a.months&&(a.days+=k(a.refMonth,a.months),delete a.months,a.days>=7&&(a.weeks+=~~(a.days/7),a.days%=7));e&32||(a.days+=a.weeks*7,delete a.weeks);e&16||(a.hours+=
-a.days*24,delete a.days);e&8||(a.minutes+=a.hours*60,delete a.hours);e&4||(a.seconds+=a.minutes*60,delete a.minutes);e&2||(a.milliseconds+=a.seconds*1E3,delete a.seconds);e&1||delete a.milliseconds}finally{delete a.refMonth}return a}function d(a,b,c){var e,c=c||222;"function"===typeof a?(e=a,a=null):a!==null&&isFinite(a)&&(a=new Date(a));"function"===typeof b?(e=b,b=null):b!==null&&isFinite(b)&&(b=new Date(b));a=a instanceof Date?a:null;b=b instanceof Date?b:null;if(!a&&!b)return new h;if(!e)return l(new h,
-a||new Date,b||new Date,c);var d;d=c&1?1E3/30:c&2?1E3:c&4?6E4:c&8?36E5:c&16?864E5:6048E5;var f=function(){e(l(new h,a||new Date,b||new Date,c))};f();return setInterval(f,d)}var i;h.prototype.toString=function(a){var b=i(this);b.length>a&&(b=b.slice(0,a));a=b.length;if(!a)return"";a>1&&(b[a-1]="and "+b[a-1]);return b.join(", ")};h.prototype.toHTML=function(a,b){var a=a||"span",c=i(this);c.length>b&&(c=c.slice(0,b));var e=c.length;if(!e)return"";for(var d=0;d<e;d++)c[d]="<"+a+">"+c[d]+"</"+a+">";--e&&
-(c[e]="and "+c[e]);return c.join(", ")};h.prototype.toShort=function(a){var b=i(this),a=a>0?a:1;b.length>a&&(b=b.slice(0,a));a=b.length;if(!a)return"";a>1&&(b[a-1]="and "+b[a-1]);return b.join(", ")};i=function(a){var b=[];a.millennia&&b.push(g(a.millennia,"millennium","millennia"));a.centuries&&b.push(g(a.centuries,"century","centuries"));a.decades&&b.push(g(a.decades,"decade","decades"));a.years&&b.push(g(a.years,"year","years"));a.months&&b.push(g(a.months,"month","months"));a.weeks&&b.push(g(a.weeks,
-"week","weeks"));a.days&&b.push(g(a.days,"day","days"));a.hours&&b.push(g(a.hours,"hour","hours"));a.minutes&&b.push(g(a.minutes,"minute","minutes"));a.seconds&&b.push(g(a.seconds,"second","seconds"));a.milliseconds&&b.push(g(a.milliseconds,"millisecond","milliseconds"));return b};d.MILLISECONDS=1;d.SECONDS=2;d.MINUTES=4;d.HOURS=8;d.DAYS=16;d.WEEKS=32;d.MONTHS=64;d.YEARS=128;d.DECADES=256;d.CENTURIES=512;d.MILLENNIA=1024;d.DEFAULTS=222;d.ALL=2047;if(j&&j.exports)j.exports=d;return d}(module);
+var module,countdown=function(l){function m(a,b){var c=a.getTime();a.setUTCMonth(a.getUTCMonth()+b);return o((a.getTime()-c)/864E5)}function g(a,b,c){return a+" "+(a===1?b:c)}function i(){}function n(a,b,c,e){a.start=b;a.end=c;a.units=e;a.value=c.getTime()-b.getTime();if(a.value<0)var d=c,c=b,b=d;a.refMonth=new Date(b.getFullYear(),b.getMonth(),15);try{a.millennia=0;a.centuries=0;a.decades=0;a.years=c.getUTCFullYear()-b.getUTCFullYear();a.months=c.getUTCMonth()-b.getUTCMonth();a.weeks=0;a.days=c.getUTCDate()-
+b.getUTCDate();a.hours=c.getUTCHours()-b.getUTCHours();a.minutes=c.getUTCMinutes()-b.getUTCMinutes();a.seconds=c.getUTCSeconds()-b.getUTCSeconds();a.milliseconds=c.getUTCMilliseconds()-b.getUTCMilliseconds();var f;a.milliseconds<0?(f=j(-a.milliseconds/1E3),a.seconds-=f,a.milliseconds+=f*1E3):a.milliseconds>=1E3&&(a.seconds+=h(a.milliseconds/1E3),a.milliseconds%=1E3);a.seconds<0?(f=j(-a.seconds/60),a.minutes-=f,a.seconds+=f*60):a.seconds>=60&&(a.minutes+=h(a.seconds/60),a.seconds%=60);a.minutes<0?
+(f=j(-a.minutes/60),a.hours-=f,a.minutes+=f*60):a.minutes>=60&&(a.hours+=h(a.minutes/60),a.minutes%=60);a.hours<0?(f=j(-a.hours/24),a.days-=f,a.hours+=f*24):a.hours>=24&&(a.days+=h(a.hours/24),a.hours%=24);a.days<0&&(f=j(-a.days/28),a.months-=f,a.days+=m(a.refMonth,f));a.days>=7&&(a.weeks+=h(a.days/7),a.days%=7);a.months<0?(f=j(-a.months/12),a.years-=f,a.months+=f*12):a.months>=12&&(a.years+=h(a.months/12),a.months%=12);a.years>=10&&(a.decades+=h(a.years/10),a.years%=10,a.decades>=10&&(a.centuries+=
+h(a.decades/10),a.decades%=10,a.centuries>=10&&(a.millennia+=h(a.centuries/10),a.centuries%=10)));e&1024||(a.centuries+=a.millennia*10,delete a.millennia);e&512||(a.decades+=a.centuries*10,delete a.centuries);e&256||(a.years+=a.decades*10,delete a.decades);e&128||(a.months+=a.years*12,delete a.years);!(e&64)&&a.months&&(a.days+=m(a.refMonth,a.months),delete a.months,a.days>=7&&(a.weeks+=h(a.days/7),a.days%=7));e&32||(a.days+=a.weeks*7,delete a.weeks);e&16||(a.hours+=a.days*24,delete a.days);e&8||
+(a.minutes+=a.hours*60,delete a.hours);e&4||(a.seconds+=a.minutes*60,delete a.minutes);e&2||(a.milliseconds+=a.seconds*1E3,delete a.seconds);e&1||delete a.milliseconds}finally{delete a.refMonth}return a}function d(a,b,c){var e,c=c||222;"function"===typeof a?(e=a,a=null):a instanceof Date||(a=a!==null&&isFinite(a)?new Date(a):null);"function"===typeof b?(e=b,b=null):b instanceof Date||(b=b!==null&&isFinite(b)?new Date(b):null);if(!a&&!b)return new i;if(!e)return n(new i,a||new Date,b||new Date,c);
+var d;d=c&1?1E3/30:c&2?1E3:c&4?6E4:c&8?36E5:c&16?864E5:6048E5;var f=function(){e(n(new i,a||new Date,b||new Date,c))};f();return setInterval(f,d)}var j=Math.ceil,h=Math.floor,o=Math.round,k;i.prototype.toString=function(a){var b=k(this);b.length>a&&(b=b.slice(0,a));a=b.length;if(!a)return"";a>1&&(b[a-1]="and "+b[a-1]);return b.join(", ")};i.prototype.toHTML=function(a,b){var a=a||"span",c=k(this);c.length>b&&(c=c.slice(0,b));var e=c.length;if(!e)return"";for(var d=0;d<e;d++)c[d]="<"+a+">"+c[d]+"</"+
+a+">";--e&&(c[e]="and "+c[e]);return c.join(", ")};i.prototype.toShort=function(a){var b=k(this),a=a>0?a:1;b.length>a&&(b=b.slice(0,a));a=b.length;if(!a)return"";a>1&&(b[a-1]="and "+b[a-1]);return b.join(", ")};k=function(a){var b=[];a.millennia&&b.push(g(a.millennia,"millennium","millennia"));a.centuries&&b.push(g(a.centuries,"century","centuries"));a.decades&&b.push(g(a.decades,"decade","decades"));a.years&&b.push(g(a.years,"year","years"));a.months&&b.push(g(a.months,"month","months"));a.weeks&&
+b.push(g(a.weeks,"week","weeks"));a.days&&b.push(g(a.days,"day","days"));a.hours&&b.push(g(a.hours,"hour","hours"));a.minutes&&b.push(g(a.minutes,"minute","minutes"));a.seconds&&b.push(g(a.seconds,"second","seconds"));a.milliseconds&&b.push(g(a.milliseconds,"millisecond","milliseconds"));return b};d.MILLISECONDS=1;d.SECONDS=2;d.MINUTES=4;d.HOURS=8;d.DAYS=16;d.WEEKS=32;d.MONTHS=64;d.YEARS=128;d.DECADES=256;d.CENTURIES=512;d.MILLENNIA=1024;d.DEFAULTS=222;d.ALL=2047;if(l&&l.exports)l.exports=d;return d}(module);

test/timespanTests.js

 	}
 });
 
+test("Underflow bug", function() {
+
+	var start = new Date(2011, 11, 1);
+	var end = new Date(2011, 11, 31, 23, 59, 59, 999);
+
+	var expected = countdown.clone({
+		start: new Date(2011, 11, 1),
+		end: new Date(2011, 11, 31, 23, 59, 59, 999),
+		units: countdown.ALL,
+		value: end.getTime() - start.getTime(),
+		millennia: 0,
+		centuries: 0,
+		decades: 0,
+		years: 0,
+		months: 0,
+		weeks: 4,
+		days: 2,
+		hours: 23,
+		minutes: 59,
+		seconds: 59,
+		milliseconds: 999
+	});
+
+	var actual = countdown(start, end, countdown.ALL);
+
+	same(actual, expected, "");
+});
+
 }catch(ex){alert(ex);}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.