Stephen McKamey avatar Stephen McKamey committed cc518a2

breaking change: further simplifying API to just the one countdown function

Comments (0)

Files changed (8)

 
 ## The API
 
-A simple but flexible API is the goal of *Countdown.js*. There is one global object with only one method and a set of static constants:
+A simple but flexible API is the goal of *Countdown.js*. There is one global function with a set of static constants:
 
-    countdown.timespan(start|callback, end|callback, units);
+    countdown(start|callback, end|callback, units);
 
 The parameters are a starting Date, ending Date and an optional set of units. If units is left off, it defaults to `countdown.DEFAULTS`.
 
 
 This allows a very minimal call to accept the defaults and get the time since/until a single date. For example:
 
-	countdown.timespan( new Date(2000, 0, 1) );
+	countdown( new Date(2000, 0, 1) );
 
 This will toString() something like:
 
 3. a number specifying the number of milliseconds since midnight Jan 1, 1970 UTC (i.e., the "UNIX epoch").
 4. a callback function accepting one timespan argument.
 
-If `start` and `end` are both specified, then repeated calls to `countdown.timespan()` will always return the same result.
+If `start` and `end` are both specified, then repeated calls to `countdown(...)` will always return the same result.
 If one date argument is left `null` while the other is provided, then repeated calls will count up if the provided date is in the past, and it will count down if the provided date is in the future.
 For example,
 
-	var daysSinceLastWorkplaceAccident = countdown.timespan(507314280000, null, countdown.DAYS);
+	var daysSinceLastWorkplaceAccident = countdown(507314280000, null, countdown.DAYS);
 
 If a callback function is supplied, then an interval timer will be started with a frequency based upon the smallest unit (e.g., if `countdown.SECONDS` is the smallest unit, the callback will be invoked once per second). Rather than returning a Timespan object, the timer's ID will be returned to allow canceling by passing into `window.clearInterval(id)`. For example, to show a timer since the page first loaded:
 
 	var timerId =
-	  countdown.timespan(
+	  countdown(
 	    new Date(),
 	    function(ts) {
 	      document.getElementById('pageTimer').innerHTML = ts.toHTML("strong");
 /**
- * @fileoverview countdown.js v2.1.3
+ * @fileoverview countdown.js v2.2.0
  * 
  * Copyright (c)2006-2011 Stephen M. McKamey
  * Licensed under the MIT License (http://bitbucket.org/mckamey/countdown.js/LICENSE.txt)
 var module;
 
 /**
+ * API entry
  * @public
- * @type {Object}
+ * @param {function(Object)|Date|number} start the starting date
+ * @param {function(Object)|Date|number} end the ending date
+ * @param {number} units the units to populate
+ * @return {Object|number}
  */
 var countdown = (
 
 		return MILLISECONDS_PER_SECOND * SECONDS_PER_MINUTE * MINUTES_PER_HOUR * HOURS_PER_DAY * DAYS_PER_WEEK;
 	}
 
-	var countdown = {
-		/**
-		 * @public
-		 * @const
-		 * @type {number}
-		 */
-		MILLISECONDS: MILLISECONDS,
+	/**
+	 * API entry point
+	 * 
+	 * @public
+	 * @param {function(Timespan)|Date|number} start the starting date
+	 * @param {function(Timespan)|Date|number} end the ending date
+	 * @param {number} units the units to populate
+	 * @return {Timespan|number}
+	 */
+	function countdown(start, end, units) {
+		var callback;
 
-		/**
-		 * @public
-		 * @const
-		 * @type {number}
-		 */
-		SECONDS: SECONDS,
+		// ensure some units or use defaults
+		units = units || DEFAULTS;
 
-		/**
-		 * @public
-		 * @const
-		 * @type {number}
-		 */
-		MINUTES: MINUTES,
+		// ensure start date
+		if ('function' === typeof start) {
+			callback = start;
+			start = null;
 
-		/**
-		 * @public
-		 * @const
-		 * @type {number}
-		 */
-		HOURS: HOURS,
+		} else if (start !== null && isFinite(start)) {
+			start = new Date(start);
+		}
 
-		/**
-		 * @public
-		 * @const
-		 * @type {number}
-		 */
-		DAYS: DAYS,
+		// ensure end date
+		if ('function' === typeof end) {
+			callback = end;
+			end = null;
 
-		/**
-		 * @public
-		 * @const
-		 * @type {number}
-		 */
-		WEEKS: WEEKS,
+		} else if (end !== null && isFinite(end)) {
+			end = new Date(end);
+		}
 
-		/**
-		 * @public
-		 * @const
-		 * @type {number}
-		 */
-		MONTHS: MONTHS,
+		start = (start instanceof Date) ? start : null;
+		end = (end instanceof Date) ? end : null;
 
-		/**
-		 * @public
-		 * @const
-		 * @type {number}
-		 */
-		YEARS: YEARS,
+		if (!start && !end) {
+			// used for unit testing
+			return new Timespan();
+		}
 
-		/**
-		 * @public
-		 * @const
-		 * @type {number}
-		 */
-		DECADES: DECADES,
+		if (!callback) {
+			return populate(new Timespan(), /** @type{Date} */(start||new Date()), /** @type{Date} */(end||new Date()), units);
+		}
 
-		/**
-		 * @public
-		 * @const
-		 * @type {number}
-		 */
-		CENTURIES: CENTURIES,
+		// base delay off units
+		var delay = getDelay(units);
+		var fn = function() {
+			callback(
+				populate(new Timespan(), /** @type{Date} */(start||new Date()), /** @type{Date} */(end||new Date()), units)
+			);
+		};
 
-		/**
-		 * @public
-		 * @const
-		 * @type {number}
-		 */
-		MILLENNIA: MILLENNIA,
+		fn();
+		return setInterval(fn, delay);
+	}
 
-		/**
-		 * @public
-		 * @const
-		 * @type {number}
-		 */
-		DEFAULTS: DEFAULTS,
+	/**
+	 * @public
+	 * @const
+	 * @type {number}
+	 */
+	countdown.MILLISECONDS = MILLISECONDS;
 
-		/**
-		 * @public
-		 * @const
-		 * @type {number}
-		 */
-		ALL: MILLENNIA|CENTURIES|DECADES|YEARS|MONTHS|WEEKS|DAYS|HOURS|MINUTES|SECONDS|MILLISECONDS,
+	/**
+	 * @public
+	 * @const
+	 * @type {number}
+	 */
+	countdown.SECONDS = SECONDS;
 
-		/**
-		 * API entry point
-		 * 
-		 * @public
-		 * @param {function(Timespan)|Date|number} start the starting date
-		 * @param {function(Timespan)|Date|number} end the ending date
-		 * @param {number} units the units to populate
-		 * @return {Timespan|number}
-		 */
-		timespan : function(start, end, units) {
-			var callback;
+	/**
+	 * @public
+	 * @const
+	 * @type {number}
+	 */
+	countdown.MINUTES = MINUTES;
 
-			// ensure some units or use defaults
-			units = units || DEFAULTS;
+	/**
+	 * @public
+	 * @const
+	 * @type {number}
+	 */
+	countdown.HOURS = HOURS;
 
-			// ensure start date
-			if ('function' === typeof start) {
-				callback = start;
-				start = null;
+	/**
+	 * @public
+	 * @const
+	 * @type {number}
+	 */
+	countdown.DAYS = DAYS;
 
-			} else if (start !== null && isFinite(start)) {
-				start = new Date(start);
-			}
+	/**
+	 * @public
+	 * @const
+	 * @type {number}
+	 */
+	countdown.WEEKS = WEEKS;
 
-			// ensure end date
-			if ('function' === typeof end) {
-				callback = end;
-				end = null;
+	/**
+	 * @public
+	 * @const
+	 * @type {number}
+	 */
+	countdown.MONTHS = MONTHS;
 
-			} else if (end !== null && isFinite(end)) {
-				end = new Date(end);
-			}
+	/**
+	 * @public
+	 * @const
+	 * @type {number}
+	 */
+	countdown.YEARS = YEARS;
 
-			start = (start instanceof Date) ? start : null;
-			end = (end instanceof Date) ? end : null;
+	/**
+	 * @public
+	 * @const
+	 * @type {number}
+	 */
+	countdown.DECADES = DECADES;
 
-			if (!callback) {
-				return populate(new Timespan(), /** @type{Date} */(start||new Date()), /** @type{Date} */(end||new Date()), units);
-			}
+	/**
+	 * @public
+	 * @const
+	 * @type {number}
+	 */
+	countdown.CENTURIES = CENTURIES;
 
-			// base delay off units
-			var delay = getDelay(units);
-			var fn = function() {
-				callback(
-					populate(new Timespan(), /** @type{Date} */(start||new Date()), /** @type{Date} */(end||new Date()), units)
-				);
-			};
+	/**
+	 * @public
+	 * @const
+	 * @type {number}
+	 */
+	countdown.MILLENNIA = MILLENNIA;
 
-			fn();
-			return setInterval(fn, delay);
-		},
+	/**
+	 * @public
+	 * @const
+	 * @type {number}
+	 */
+	countdown.DEFAULTS = DEFAULTS;
 
-		/**
-		 * For unit testing only.
-		 * 
-		 * @private
-		 * @param {Timespan|Object} map properties to convert to a Timespan
-		 * @return {Timespan}
-		 */
-		clone: function(map) {
-			var ts = new Timespan();
-			for (var key in map) {
-				if (map.hasOwnProperty(key)) {
-					ts[key] = map[key];
-				}
-			}
-			return ts;
-		}
-	};
+	/**
+	 * @public
+	 * @const
+	 * @type {number}
+	 */
+	countdown.ALL = MILLENNIA|CENTURIES|DECADES|YEARS|MONTHS|WEEKS|DAYS|HOURS|MINUTES|SECONDS|MILLISECONDS;
 
 	if (module && module.exports) {
 		module.exports = countdown;
-var module,countdown=function(i){function j(a,b){var c=a.getTime();a.setUTCMonth(a.getUTCMonth()+b);return Math.round((a.getTime()-c)/864E5)}function e(a,b,c){return a+" "+(a===1?b:c)}function g(){}function k(a,b,c,d){a.start=b;a.end=c;a.units=d;a.value=c.getTime()-b.getTime();if(a.value<0)var e=c,c=b,b=e;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;
+var module,countdown=function(j){function k(a,b){var c=a.getTime();a.setUTCMonth(a.getUTCMonth()+b);return Math.round((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=Math.ceil(-a.milliseconds/1E3),a.seconds-=f,a.milliseconds+=f*1E3):a.milliseconds>=1E3&&(a.seconds+=Math.floor(a.milliseconds/1E3),a.milliseconds%=1E3);a.seconds<0?(f=Math.ceil(-a.seconds/60),a.minutes-=f,a.seconds+=f*60):a.seconds>=60&&(a.minutes+=
-Math.floor(a.seconds/60),a.seconds%=60);a.minutes<0?(f=Math.ceil(-a.minutes/60),a.hours-=f,a.minutes+=f*60):a.minutes>=60&&(a.hours+=Math.floor(a.minutes/60),a.minutes%=60);a.hours<0?(f=Math.ceil(-a.hours/24),a.days-=f,a.hours+=f*24):a.hours>=24&&(a.days+=Math.floor(a.hours/24),a.hours%=24);a.days<0&&(f=Math.ceil(-a.days/28),a.months-=f,a.days+=j(a.refMonth,f));a.days>=7&&(a.weeks+=Math.floor(a.days/7),a.days%=7);a.months<0?(f=Math.ceil(-a.months/12),a.years-=f,a.months+=f*12):a.months>=12&&(a.years+=
-Math.floor(a.months/12),a.months%=12);a.years>=10&&(a.decades+=Math.floor(a.years/10),a.years%=10,a.decades>=10&&(a.centuries+=Math.floor(a.decades/10),a.decades%=10,a.centuries>=10&&(a.millennia+=Math.floor(a.centuries/10),a.centuries%=10)));d&1024||(a.centuries+=a.millennia*10,delete a.millennia);d&512||(a.decades+=a.centuries*10,delete a.centuries);d&256||(a.years+=a.decades*10,delete a.decades);d&128||(a.months+=a.years*12,delete a.years);!(d&64)&&a.months&&(a.days+=j(a.refMonth,a.months),delete a.months,
-a.days>=7&&(a.weeks+=Math.floor(a.days/7),a.days%=7));d&32||(a.days+=a.weeks*7,delete a.weeks);d&16||(a.hours+=a.days*24,delete a.days);d&8||(a.minutes+=a.hours*60,delete a.hours);d&4||(a.seconds+=a.minutes*60,delete a.minutes);d&2||(a.milliseconds+=a.seconds*1E3,delete a.seconds);d&1||delete a.milliseconds}finally{delete a.refMonth}return a}var h;g.prototype.toString=function(a){var b=h(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(", ")};
-g.prototype.toHTML=function(a,b){var a=a||"span",c=h(this);c.length>b&&(c=c.slice(0,b));var d=c.length;if(!d)return"";for(var e=0;e<d;e++)c[e]="<"+a+">"+c[e]+"</"+a+">";--d&&(c[d]="and "+c[d]);return c.join(", ")};g.prototype.toShort=function(a){var b=h(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(", ")};h=function(a){var b=[];a.millennia&&b.push(e(a.millennia,"millennium","millennia"));a.centuries&&b.push(e(a.centuries,"century",
-"centuries"));a.decades&&b.push(e(a.decades,"decade","decades"));a.years&&b.push(e(a.years,"year","years"));a.months&&b.push(e(a.months,"month","months"));a.weeks&&b.push(e(a.weeks,"week","weeks"));a.days&&b.push(e(a.days,"day","days"));a.hours&&b.push(e(a.hours,"hour","hours"));a.minutes&&b.push(e(a.minutes,"minute","minutes"));a.seconds&&b.push(e(a.seconds,"second","seconds"));a.milliseconds&&b.push(e(a.milliseconds,"millisecond","milliseconds"));return b};var l={MILLISECONDS:1,SECONDS:2,MINUTES:4,
-HOURS:8,DAYS:16,WEEKS:32,MONTHS:64,YEARS:128,DECADES:256,CENTURIES:512,MILLENNIA:1024,DEFAULTS:222,ALL:2047,timespan:function(a,b,c){var d,c=c||222;"function"===typeof a?(d=a,a=null):a!==null&&isFinite(a)&&(a=new Date(a));"function"===typeof b?(d=b,b=null):b!==null&&isFinite(b)&&(b=new Date(b));a=a instanceof Date?a:null;b=b instanceof Date?b:null;if(!d)return k(new g,a||new Date,b||new Date,c);var e;e=c&1?1E3/30:c&2?1E3:c&4?6E4:c&8?36E5:c&16?864E5:6048E5;var f=function(){d(k(new g,a||new Date,b||
-new Date,c))};f();return setInterval(f,e)},clone:function(a){var b=new g,c;for(c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b}};if(i&&i.exports)i.exports=l;return l}(module);
+Math.floor(a.seconds/60),a.seconds%=60);a.minutes<0?(f=Math.ceil(-a.minutes/60),a.hours-=f,a.minutes+=f*60):a.minutes>=60&&(a.hours+=Math.floor(a.minutes/60),a.minutes%=60);a.hours<0?(f=Math.ceil(-a.hours/24),a.days-=f,a.hours+=f*24):a.hours>=24&&(a.days+=Math.floor(a.hours/24),a.hours%=24);a.days<0&&(f=Math.ceil(-a.days/28),a.months-=f,a.days+=k(a.refMonth,f));a.days>=7&&(a.weeks+=Math.floor(a.days/7),a.days%=7);a.months<0?(f=Math.ceil(-a.months/12),a.years-=f,a.months+=f*12):a.months>=12&&(a.years+=
+Math.floor(a.months/12),a.months%=12);a.years>=10&&(a.decades+=Math.floor(a.years/10),a.years%=10,a.decades>=10&&(a.centuries+=Math.floor(a.decades/10),a.decades%=10,a.centuries>=10&&(a.millennia+=Math.floor(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+=Math.floor(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);
 			fff = Number(byId('milliseconds').value);
 
 		var start = new Date(yyyy, MM, dd, HH, mm, ss, fff),
-			ts = countdown.timespan(start, null, units);
+			ts = countdown(start, null, units);
 
 		byId('counter').innerHTML = ts.toHTML("strong", max) || empty;
 		byId('timespan').innerHTML = JSON.stringify(ts, null, "  ");
 {
 	"name": "countdown",
 	"description": "A simple JavaScript API for producing an accurate, intuitive description of the timespan between two Date instances.",
-	"version": "2.1.3",
+	"version": "2.3.0",
 	"homepage": "http://countdownjs.org",
 	"author": "Stephen McKamey <stephen@mckamey.com>",
 	"repository": {
 
 <h2>The API</h2>
 
-<p>A simple but flexible API is the goal of <em>Countdown.js</em>. There is one global object with only one method and a set of static constants:</p>
+<p>A simple but flexible API is the goal of <em>Countdown.js</em>. There is one global function with a set of static constants:</p>
 
-<pre><code>countdown.timespan(start|callback, end|callback, units);</code></pre>
+<pre><code>countdown(start|callback, end|callback, units);</code></pre>
 
 <p>The parameters are a starting Date, ending Date and an optional set of units. If units is left off, it defaults to <code>countdown.DEFAULTS</code>.</p>
 
 
 <p>This allows a very minimal call to accept the defaults and get the time since/until a single date. For example:</p>
 
-<pre><code>countdown.timespan( new Date(2000, 0, 1) );</code></pre>
+<pre><code>countdown( new Date(2000, 0, 1) );</code></pre>
 
 <p>This will toString() something like:</p>
 
 	<li>a callback function accepting one timespan argument.</li>
 </ol>
 
-<p>If <code>start</code> and <code>end</code> are both specified, then repeated calls to <code>countdown.timespan()</code> will always return the same result.
+<p>If <code>start</code> and <code>end</code> are both specified, then repeated calls to <code>countdown(...)</code> will always return the same result.
 If one date argument is left <code>null</code> while the other is provided, then repeated calls will count up if the provided date is in the past, and it will count down if the provided date is in the future.
 For example,</p>
 
-<pre><code>var daysSinceLastWorkplaceAccident = countdown.timespan(507314280000, null, countdown.DAYS);</code></pre>
+<pre><code>var daysSinceLastWorkplaceAccident = countdown(507314280000, null, countdown.DAYS);</code></pre>
 
 <p>If a callback function is supplied, then an interval timer will be started with a frequency based upon the smallest unit (e.g., if <code>countdown.SECONDS</code> is the smallest unit, the callback will be invoked once per second). Rather than returning a Timespan object, the timer's ID will be returned to allow canceling by passing into <code>window.clearInterval(id)</code>. For example, to show a timer since the page first loaded:</p>
 
 <pre><code>var timerId =
-  countdown.timespan(
+  countdown(
     new Date(),
     function(ts) {
       document.getElementById('pageTimer').innerHTML = ts.toHTML("strong");

test/formatTests.js

 
 test("Zero", function() {
 
-	var input = countdown.timespan(0, 0, countdown.ALL);
+	var input = countdown(0, 0, countdown.ALL);
 
 	var expected = "";
 
 
 test("1 ms", function() {
 
-	var input = countdown.timespan(0, 1, countdown.ALL);
+	var input = countdown(0, 1, countdown.ALL);
 
 	var expected = "1 millisecond";
 
 
 test("2 ms", function() {
 
-	var input = countdown.timespan(0, 2, countdown.ALL);
+	var input = countdown(0, 2, countdown.ALL);
 
 	var expected = "2 milliseconds";
 
 
 test("1 sec, 2 ms", function() {
 
-	var input = countdown.timespan(1000, 2002, countdown.ALL);
+	var input = countdown(1000, 2002, countdown.ALL);
 
 	var expected = "1 second, and 2 milliseconds";
 
 
 test("2 sec, 1 ms", function() {
 
-	var input = countdown.timespan(10000, 12001, countdown.ALL);
+	var input = countdown(10000, 12001, countdown.ALL);
 
 	var expected = "2 seconds, and 1 millisecond";
 
 
 test("1 day, reversed", function() {
 
-	var input = countdown.timespan(24 * 60 * 60 * 1000, 0, countdown.ALL);
+	var input = countdown(24 * 60 * 60 * 1000, 0, countdown.ALL);
 
 	var expected = "1 day";
 
 
 test("15 days", function() {
 
-	var input = countdown.timespan(15 * 24 * 60 * 60 * 1000, 0, countdown.ALL);
+	var input = countdown(15 * 24 * 60 * 60 * 1000, 0, countdown.ALL);
 
 	var expected = "2 weeks, and 1 day";
 
 
 test("32 days", function() {
 
-	var input = countdown.timespan(32 * 24 * 60 * 60 * 1000, 0, countdown.ALL);
+	var input = countdown(32 * 24 * 60 * 60 * 1000, 0, countdown.ALL);
 
 	var expected = "1 month, and 1 day";
 
 
 test("millennium, week", function() {
 
-	var input = countdown.timespan(0, 10 * 100 * 365.25 * 24 * 60 * 60 * 1000, countdown.ALL);
+	var input = countdown(0, 10 * 100 * 365.25 * 24 * 60 * 60 * 1000, countdown.ALL);
 
 	var expected = "1 millennium, and 1 week";
 
 
 test("one of each", function() {
 
-	var input = countdown.timespan(0,
+	var input = countdown(0,
 		(11 * 100) * (365.25 * 24 * 60 * 60 * 1000) + // millennium, century, week, day
 		(365 * 24 * 60 * 60 * 1000) + // year
 		(31 * 24 * 60 * 60 * 1000) + // month
 
 test("millennium, week; 1 max", function() {
 
-	var input = countdown.timespan(0, 10 * 100 * 365.25 * 24 * 60 * 60 * 1000, countdown.ALL);
+	var input = countdown(0, 10 * 100 * 365.25 * 24 * 60 * 60 * 1000, countdown.ALL);
 
 	var expected = "1 millennium";
 
 
 test("one of each; 3 max", function() {
 
-	var input = countdown.timespan(0,
+	var input = countdown(0,
 		(11 * 100) * (365.25 * 24 * 60 * 60 * 1000) + // millennium, century, week, day
 		(365 * 24 * 60 * 60 * 1000) + // year
 		(31 * 24 * 60 * 60 * 1000) + // month
 
 test("one of each; zero max", function() {
 
-	var input = countdown.timespan(0,
+	var input = countdown(0,
 		(11 * 100) * (365.25 * 24 * 60 * 60 * 1000) + // millennium, century, week, day
 		(365 * 24 * 60 * 60 * 1000) + // year
 		(31 * 24 * 60 * 60 * 1000) + // month
 
 test("one of each; -2 max", function() {
 
-	var input = countdown.timespan(0,
+	var input = countdown(0,
 		(11 * 100) * (365.25 * 24 * 60 * 60 * 1000) + // millennium, century, week, day
 		(365 * 24 * 60 * 60 * 1000) + // year
 		(31 * 24 * 60 * 60 * 1000) + // month
 
 test("Zero", function() {
 
-	var input = countdown.timespan(0, 0, countdown.ALL);
+	var input = countdown(0, 0, countdown.ALL);
 
 	var expected = "";
 
 
 test("1 ms", function() {
 
-	var input = countdown.timespan(0, 1, countdown.ALL);
+	var input = countdown(0, 1, countdown.ALL);
 
 	var expected = "<span>1 millisecond</span>";
 
 
 test("2 days, reversed", function() {
 
-	var input = countdown.timespan(2 * 24 * 60 * 60 * 1000, 0, countdown.ALL);
+	var input = countdown(2 * 24 * 60 * 60 * 1000, 0, countdown.ALL);
 
 	var expected = "<span>2 days</span>";
 
 
 test("8 days", function() {
 
-	var input = countdown.timespan(0, 8 * 24 * 60 * 60 * 1000, countdown.ALL);
+	var input = countdown(0, 8 * 24 * 60 * 60 * 1000, countdown.ALL);
 
 	var expected = "<span>1 week</span>, and <span>1 day</span>";
 
 
 test("70 days", function() {
 
-	var input = countdown.timespan(0, 70 * 24 * 60 * 60 * 1000, countdown.ALL);
+	var input = countdown(0, 70 * 24 * 60 * 60 * 1000, countdown.ALL);
 
 	var expected = "<span>2 months</span>, <span>1 week</span>, and <span>4 days</span>";
 
 
 test("366 days, non-leap year", function() {
 
-	var input = countdown.timespan(0, 366 * 24 * 60 * 60 * 1000, countdown.ALL);
+	var input = countdown(0, 366 * 24 * 60 * 60 * 1000, countdown.ALL);
 
 	var expected = "<span>1 year</span>, and <span>1 day</span>";
 
 
 	var start = new Date(2000, 0, 1);
 
-	var input = countdown.timespan(start, start.getTime() + 366 * 24 * 60 * 60 * 1000, countdown.ALL);
+	var input = countdown(start, start.getTime() + 366 * 24 * 60 * 60 * 1000, countdown.ALL);
 
 	var expected = "<span>1 year</span>";
 
 
 test("one of each", function() {
 
-	var input = countdown.timespan(0,
+	var input = countdown(0,
 		(11 * 100) * (365.25 * 24 * 60 * 60 * 1000) + // millennium, century, week, day
 		(365 * 24 * 60 * 60 * 1000) + // year
 		(31 * 24 * 60 * 60 * 1000) + // month

test/timespanTests.js

 try{
 
-module("countdown.timespan(...)");
+/**
+ * Mocks up a Timespan object for unit tests
+ * 
+ * @private
+ * @param {Timespan|Object} map properties to convert to a Timespan
+ * @return {Timespan}
+ */
+countdown.clone = function(map) {
+	var ts = countdown();
+	for (var key in map) {
+		if (map.hasOwnProperty(key)) {
+			ts[key] = map[key];
+		}
+	}
+	return ts;
+};
+
+module("countdown(...)");
 
 test("Zero", function() {
 
 		milliseconds: 0
 	});
 
-	var actual = countdown.timespan(start, end, countdown.ALL);
+	var actual = countdown(start, end, countdown.ALL);
 
 	same(actual, expected, "");
 });
 		milliseconds: 1
 	});
 
-	var actual = countdown.timespan(start, end, countdown.ALL);
+	var actual = countdown(start, end, countdown.ALL);
 
 	same(actual, expected, "");
 });
 		milliseconds: 0
 	});
 
-	var actual = countdown.timespan(start, end, countdown.ALL);
+	var actual = countdown(start, end, countdown.ALL);
 
 	same(actual, expected, "");
 });
 		milliseconds: 0
 	});
 
-	var actual = countdown.timespan(start, end, countdown.ALL);
+	var actual = countdown(start, end, countdown.ALL);
 
 	same(actual, expected, "");
 });
 			expected.end = end;
 			expected.value = end.getTime() - start.getTime();
 	
-			var actual = countdown.timespan(start, end, countdown.ALL);
+			var actual = countdown(start, end, countdown.ALL);
 	
 			same(actual, expected, "");
 		}
 
 	while (start.getTime() < end.getTime()) {
 
-		var actual = countdown.timespan(start, end, units);
+		var actual = countdown(start, end, units);
 		actual = {
 			weeks: actual.weeks,
 			days: actual.days
 
 	while (start.getTime() < end.getTime()) {
 
-		var actual = countdown.timespan(start, end, units);
+		var actual = countdown(start, end, units);
 		actual = {
 			months: actual.months,
 			days: actual.days
 
 	while (start.getTime() < end.getTime()) {
 
-		var actual = countdown.timespan(start, end, units);
+		var actual = countdown(start, end, units);
 		actual = {
 			months: actual.months,
 			weeks: actual.weeks,
 
 	while (end.getTime() < goalTime) {
 
-		var actual = countdown.timespan(start, end, units);
+		var actual = countdown(start, end, units);
 		actual = {
 			months: actual.months,
 			days: actual.days
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.