]> git.ipfire.org Git - thirdparty/moment.git/commitdiff
Added to npm. Removed dependancy on underscore. Now, underscore.date can be used...
authorTim Wood <washwithcare@gmail.com>
Mon, 2 May 2011 17:53:27 +0000 (10:53 -0700)
committerTim Wood <washwithcare@gmail.com>
Mon, 2 May 2011 17:53:27 +0000 (10:53 -0700)
13 files changed:
build.js [new file with mode: 0755]
lib/underscore.date.js [deleted file]
lib/underscore.date.min.js [deleted file]
package.json [new file with mode: 0755]
test/customize.html
test/customizeDate.js
test/customizePartial.html
test/customizePartial.js
test/date.js
test/speed.js
test/test.html
underscore.date.js [new file with mode: 0644]
underscore.date.min.js [new file with mode: 0644]

diff --git a/build.js b/build.js
new file mode 100755 (executable)
index 0000000..672bdb6
--- /dev/null
+++ b/build.js
@@ -0,0 +1,19 @@
+var fs     = require('fs'),
+    uglify = require('uglify-js');
+
+function makeFile(filename, contents) {
+    fs.writeFileSync(filename, contents);
+    console.log(filename + " saved");
+}
+
+(function() {
+    var output = fs.readFileSync('./underscore.date.js', 'utf8'), 
+        ast, 
+        ugly;
+    ast  = uglify.parser.parse(output);
+    ast  = uglify.uglify.ast_mangle(ast);
+    ast  = uglify.uglify.ast_squeeze(ast);
+    ugly = uglify.uglify.gen_code(ast);
+        
+    makeFile('./underscore.date.min.js', ugly);
+})();
diff --git a/lib/underscore.date.js b/lib/underscore.date.js
deleted file mode 100644 (file)
index 8e8ef82..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-// Underscore.date
-//
-// (c) 2011 Tim Wood
-// Underscore.date is freely distributable under the terms of the MIT license.
-//
-// Version 0.3.2
-
-/*global _:false */
-
-
-(function(Date, _, undefined){
-    // function to return first three characters for minification of wordsMonthsShort + 
-    // wordsWeekdaysShort arrays.
-    function firstThreeLetters(input){
-        return input.slice(0, 3);
-    }
-    // assign variables here so they can be overwritten for i18n or customization
-    var self = this, _d,
-        wordsMonths = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
-        wordsMonthsShort = _.map(wordsMonths, firstThreeLetters),
-        wordsWeekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
-        wordsWeekdaysShort = _.map(wordsWeekdays, firstThreeLetters),
-        wordsTimeAgo = {
-            future: "in %s",
-            past: "%s ago",
-            s: "seconds",
-            m: "a minute",
-            mm: "%d minutes",
-            h: "an hour",
-            hh: "%d hours",
-            d: "a day",
-            dd: "%d days",
-            M: "a month",
-            MM: "%d months",
-            y: "a year",
-            yy: "%d years"
-        },
-        createOrdinal = function(number) {
-            var b = number % 10;
-            return (~~ (number % 100 / 10) === 1) ? 'th' : 
-                (b === 1) ? 'st' : 
-                (b === 2) ? 'nd' : 
-                (b === 3) ? 'rd' : 'th';
-        };
-    
-    // left zero fill a number
-    // see http://jsperf.com/left-zero-filling for performance comparison
-    function leftZeroFill(number, targetLength) {
-        var output = number + '';
-        while (output.length < targetLength) {
-            output = '0' + output;
-        }
-        return output;
-    }
-    
-    // helper function for _.addTime and _.subtractTime
-    function dateAddRemove(_this, input, adding){
-        var self = _this.date,
-            ms = (input.ms || 0) +
-            (input.s  || 0) * 1e3 + // 1000
-            (input.m  || 0) * 6e4 + // 1000 * 60
-            (input.h  || 0) * 36e5 + // 1000 * 60 * 60
-            (input.d  || 0) * 864e5 + // 1000 * 60 * 60 * 24
-            (input.w  || 0) * 6048e5, // 1000 * 60 * 60 * 24 * 7
-            M = (input.M || 0) + 
-            (input.y || 0) * 12,
-            currentDate;
-        if (ms) {
-            self.setMilliseconds(self.getMilliseconds() + ms * adding);
-        }
-        if (M) {
-            currentDate = self.getDate();
-            self.setDate(1);
-            self.setMonth(self.getMonth() + M * adding);
-            self.setDate(Math.min(new Date(self.getFullYear(), self.getMonth() + 1, 0).getDate(), currentDate)); 
-        }
-        return _this;
-    }
-    
-    // convert an array to a date.
-    // the array should mirror the parameters below
-    // note: all values past the year are optional and will default to the lowest possible value.
-    // [year, month, day , hour, minute, second, millisecond]
-    function dateFromArray(input) {
-        return new Date(input[0], input[1] || 0, input[2] || 1, input[3] || 0, input[4] || 0, input[5] || 0, input[6] || 0);
-    }
-    
-    // convert any input to a date
-    //
-    // undefined = _.now()
-    // date = date
-    // array = new Date(array)
-    // number = new Date(number)
-    // string = new Date(string)
-    function makeInputDate(input){
-        return input === undefined ? new Date() :
-            input instanceof _Date ? input.date :
-            _.isDate(input) ? input : 
-            _.isArray(input) && input.length > 2 ? dateFromArray(input) :
-            new Date(input);
-    }
-    
-    // convert any input to milliseconds
-    //
-    // undefined = _.now()
-    // number = number
-    // date = date.gettime()
-    // array = new Date(array).getTime()
-    // string = new Date(string).getTime()
-    function makeInputMilliseconds(input){
-        return isNaN(input) ? makeInputDate(input).getTime() : input;
-    }
-    
-    // helper function for _.relativeTime
-    function substituteTimeAgo(string, number) {
-        return wordsTimeAgo[string].replace(/%d/i, number || 1);
-    }
-    
-    // _Date prototype object
-    function _Date(input) {
-        this.date = makeInputDate(input);
-        return this;
-    }
-    
-    var _DateProto = _Date.prototype;
-    
-    _DateProto.format = function(inputString) {
-        // shortcuts to this and getting time functions
-        // done to save bytes in minification
-        var date = this.date,
-            currentMonth = date.getMonth(),
-            currentDate = date.getDate(),
-            currentYear = date.getFullYear(),
-            currentDay = date.getDay(),
-            currentHours = date.getHours(),
-            currentMinutes = date.getMinutes(),
-            currentSeconds = date.getSeconds(),
-            currentString = date.toString(),
-            charactersToReplace = /(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|dddd?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|zz?)/g,
-            nonuppercaseLetters = /[^A-Z]/g;
-        // check if the character is a format
-        // return formatted string or non string.
-        //
-        // uses switch/case instead of an object of named functions (like http://phpjs.org/functions/date:380) 
-        // for minification and performance
-        // see http://jsperf.com/object-of-functions-vs-switch for performance comparison
-        function replaceFunction(input) {
-            // create a couple variables to be used later inside one of the cases.
-            var a, b;
-            switch (input) {
-                // MONTH
-                case 'M' : 
-                    return currentMonth + 1;
-                case 'Mo' : 
-                    return (currentMonth + 1) + createOrdinal(currentMonth + 1);
-                case 'MM' :
-                    return leftZeroFill(currentMonth + 1, 2);
-                case 'MMM' : 
-                    return wordsMonthsShort[currentMonth];
-                case 'MMMM' : 
-                    return wordsMonths[currentMonth];
-                // DAY OF MONTH
-                case 'D' : 
-                    return currentDate;
-                case 'Do' : 
-                    return currentDate + createOrdinal(currentDate);
-                case 'DD' : 
-                    return leftZeroFill(currentDate, 2);
-                // DAY OF YEAR
-                case 'DDD' :
-                    a = new Date(currentYear, currentMonth, currentDate);
-                    b = new Date(currentYear, 0, 1);
-                    return ~~ (((a - b) / 864e5) + 1.5);
-                case 'DDDo' : 
-                    a = replaceFunction('DDD');
-                    return a + createOrdinal(a);
-                case 'DDDD' :
-                    return leftZeroFill(replaceFunction('DDD'), 3);
-                // WEEKDAY
-                case 'd' :
-                    return currentDay;
-                case 'do' : 
-                    return currentDay + createOrdinal(currentDay);
-                case 'ddd' : 
-                    return wordsWeekdaysShort[currentDay];
-                case 'dddd' : 
-                    return wordsWeekdays[currentDay];
-                // WEEK OF YEAR
-                case 'w' : 
-                    a = new Date(currentYear, currentMonth, currentDate - currentDay + 5);
-                    b = new Date(a.getFullYear(), 0, 4);
-                    return ~~ ((a - b) / 864e5 / 7 + 1.5);
-                case 'wo' : 
-                    a = replaceFunction('w');
-                    return a + createOrdinal(a);
-                case 'ww' : 
-                    return leftZeroFill(replaceFunction('w'), 2);
-                // YEAR
-                case 'YY' : 
-                    return (currentYear + '').slice(-2);
-                case 'YYYY' : 
-                    return currentYear;
-                // AM / PM
-                case 'a' : 
-                    return currentHours > 11 ? 'pm' : 'am';
-                case 'A' :
-                    return currentHours > 11 ? 'PM' : 'AM';
-                // 24 HOUR 
-                case 'H' : 
-                    return currentHours;
-                case 'HH' : 
-                    return leftZeroFill(currentHours, 2);
-                // 12 HOUR 
-                case 'h' : 
-                    return currentHours % 12 || 12;
-                case 'hh' : 
-                    return leftZeroFill(currentHours % 12 || 12, 2);
-                // MINUTE
-                case 'm' : 
-                    return currentMinutes;
-                case 'mm' : 
-                    return leftZeroFill(currentMinutes, 2);
-                // SECOND
-                case 's' : 
-                    return currentSeconds;
-                case 'ss' : 
-                    return leftZeroFill(currentSeconds, 2);
-                // TIMEZONE
-                case 'z' :
-                    return replaceFunction('zz').replace(nonuppercaseLetters, '');
-                case 'zz' : 
-                    a = currentString.indexOf('(');
-                    if (a > -1) {
-                        return currentString.slice(a + 1, currentString.indexOf(')'));
-                    }
-                    return currentString.slice(currentString.indexOf(':')).replace(nonuppercaseLetters, '');
-                // DEFAULT
-                default :
-                    return input.replace("\\", "");
-            }
-        }
-        return inputString.replace(charactersToReplace, replaceFunction);
-    };
-    
-    _DateProto.add = function(input) {
-        return dateAddRemove(this, input, 1);
-    };
-    
-    _DateProto.subtract = function(input) {
-        return dateAddRemove(this, input, -1);
-    };
-    
-    _DateProto.customize = function(input) {
-        var inputOrdinal = input.ordinal;
-        _.extend(wordsWeekdays, input.weekdays);
-        _.extend(wordsWeekdaysShort, input.weekdaysShort);
-        _.extend(wordsMonths, input.months);
-        _.extend(wordsMonthsShort, input.monthsShort);
-        _.extend(wordsTimeAgo, input.relativeTime);
-        if (inputOrdinal && _.isFunction(inputOrdinal)) {
-            createOrdinal = inputOrdinal;
-        }
-    };
-    
-    function msApart(time, now) {
-        return makeInputMilliseconds(time) - makeInputMilliseconds(now);
-    }
-    
-    function relativeTime(milliseconds) {
-        var seconds = Math.abs(milliseconds) / 1000,
-            minutes = seconds / 60,
-            hours = minutes / 60,
-            days = hours / 24,
-            years = days / 365;
-        return seconds < 45 && substituteTimeAgo('s', ~~ seconds) ||
-            seconds < 90 && substituteTimeAgo('m') ||
-            minutes < 45 && substituteTimeAgo('mm', ~~ minutes) ||
-            minutes < 90 && substituteTimeAgo('h') ||
-            hours < 24 && substituteTimeAgo('hh', ~~ hours) ||
-            hours < 48 && substituteTimeAgo('d') ||
-            days < 25 && substituteTimeAgo('dd', ~~ days) ||
-            days < 45 && substituteTimeAgo('M') ||
-            days < 350 && substituteTimeAgo('MM', ~~ ((days + 15) / 30)) ||
-            years < 2 && substituteTimeAgo('y') ||
-            substituteTimeAgo('yy', ~~ years);
-    }
-    
-    _DateProto.from = function(time, withoutSuffix, asMilliseconds) {
-        var difference = msApart(this.date, time),
-            string = difference < 0 ? wordsTimeAgo.past : wordsTimeAgo.future;
-        return asMilliseconds ? difference : 
-            withoutSuffix ? relativeTime(difference) :
-            string.replace(/%s/i, relativeTime(difference));
-    };
-    
-    _DateProto.fromNow = function(withoutSuffix, asMilliseconds) {
-        return this.from(_.now(), withoutSuffix, asMilliseconds);
-    };
-    
-    _DateProto.isLeapYear = function() {
-        return _.isLeapYear(this.date.getFullYear());
-    };
-    
-    // integrate with underscore.js
-    _.mixin({
-        date : function(input) {
-            return new _Date(input);
-        },
-        now : function(asTimestamp) {
-            return asTimestamp ? new Date().getTime() : _.date();
-        },
-        isLeapYear : function(year) {
-            return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
-        }
-    });
-    
-}(Date, _));
diff --git a/lib/underscore.date.min.js b/lib/underscore.date.min.js
deleted file mode 100644 (file)
index 885e2fe..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// Underscore.date
-//
-// (c) 2011 Tim Wood
-// Underscore.date is freely distributable under the terms of the MIT license.
-//
-// Version 0.3.2
-
-(function(a,b,c){function v(a){var b=Math.abs(a)/1e3,c=b/60,d=c/60,e=d/24,f=e/365;return b<45&&r("s",~~b)||b<90&&r("m")||c<45&&r("mm",~~c)||c<90&&r("h")||d<24&&r("hh",~~d)||d<48&&r("d")||e<25&&r("dd",~~e)||e<45&&r("M")||e<350&&r("MM",~~((e+15)/30))||f<2&&r("y")||r("yy",~~f)}function u(a,b){return q(a)-q(b)}function s(a){this.date=p(a);return this}function r(a,b){return k[a].replace(/%d/i,b||1)}function q(a){return isNaN(a)?p(a).getTime():a}function p(d){return d===c?new a:d instanceof s?d.date:b.isDate(d)?d:b.isArray(d)&&d.length>2?o(d):new a(d)}function o(b){return new a(b[0],b[1]||0,b[2]||1,b[3]||0,b[4]||0,b[5]||0,b[6]||0)}function n(b,c,d){var e=b.date,f=(c.ms||0)+(c.s||0)*1e3+(c.m||0)*6e4+(c.h||0)*36e5+(c.d||0)*864e5+(c.w||0)*6048e5,g=(c.M||0)+(c.y||0)*12,h;f&&e.setMilliseconds(e.getMilliseconds()+f*d),g&&(h=e.getDate(),e.setDate(1),e.setMonth(e.getMonth()+g*d),e.setDate(Math.min((new a(e.getFullYear(),e.getMonth()+1,0)).getDate(),h)));return b}function m(a,b){var c=a+"";while(c.length<b)c="0"+c;return c}function d(a){return a.slice(0,3)}var e=this,f,g=["January","February","March","April","May","June","July","August","September","October","November","December"],h=b.map(g,d),i=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],j=b.map(i,d),k={future:"in %s",past:"%s ago",s:"seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},l=function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"},t=s.prototype;t.format=function(b){function t(b){var c,r;switch(b){case"M":return d+1;case"Mo":return d+1+l(d+1);case"MM":return m(d+1,2);case"MMM":return h[d];case"MMMM":return g[d];case"D":return e;case"Do":return e+l(e);case"DD":return m(e,2);case"DDD":c=new a(f,d,e),r=new a(f,0,1);return~~((c-r)/864e5+1.5);case"DDDo":c=t("DDD");return c+l(c);case"DDDD":return m(t("DDD"),3);case"d":return k;case"do":return k+l(k);case"ddd":return j[k];case"dddd":return i[k];case"w":c=new a(f,d,e-k+5),r=new a(c.getFullYear(),0,4);return~~((c-r)/864e5/7+1.5);case"wo":c=t("w");return c+l(c);case"ww":return m(t("w"),2);case"YY":return(f+"").slice(-2);case"YYYY":return f;case"a":return n>11?"pm":"am";case"A":return n>11?"PM":"AM";case"H":return n;case"HH":return m(n,2);case"h":return n%12||12;case"hh":return m(n%12||12,2);case"m":return o;case"mm":return m(o,2);case"s":return p;case"ss":return m(p,2);case"z":return t("zz").replace(s,"");case"zz":c=q.indexOf("(");if(c>-1)return q.slice(c+1,q.indexOf(")"));return q.slice(q.indexOf(":")).replace(s,"");default:return b.replace("\\","")}}var c=this.date,d=c.getMonth(),e=c.getDate(),f=c.getFullYear(),k=c.getDay(),n=c.getHours(),o=c.getMinutes(),p=c.getSeconds(),q=c.toString(),r=/(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|dddd?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|zz?)/g,s=/[^A-Z]/g;return b.replace(r,t)},t.add=function(a){return n(this,a,1)},t.subtract=function(a){return n(this,a,-1)},t.customize=function(a){var c=a.ordinal;b.extend(i,a.weekdays),b.extend(j,a.weekdaysShort),b.extend(g,a.months),b.extend(h,a.monthsShort),b.extend(k,a.relativeTime),c&&b.isFunction(c)&&(l=c)},t.from=function(a,b,c){var d=u(this.date,a),e=d<0?k.past:k.future;return c?d:b?v(d):e.replace(/%s/i,v(d))},t.fromNow=function(a,c){return this.from(b.now(),a,c)},t.isLeapYear=function(){return b.isLeapYear(this.date.getFullYear())},b.mixin({date:function(a){return new s(a)},now:function(c){return c?(new a).getTime():b.date()},isLeapYear:function(a){return a%4===0&&a%100!==0||a%400===0}})})(Date,_)
diff --git a/package.json b/package.json
new file mode 100755 (executable)
index 0000000..ba5379b
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  "name": "underscore.date",
+  "version": "0.4.0",
+  "description": "Underscore.date is a JavaScript Date utility library built on top of Underscore.js",
+  "homepage": "https://github.com/timrwood/underscore.date",
+  "author": "Tim Wood <washwithcare@gmail.com> (http://timwoodcreates.com/)",
+  "keywords": [
+    "underscore",
+    "date"
+  ],
+  "main": "./underscore.date",
+  "engines": {
+    "node": "*"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/timrwood/underscore.date.git"
+  },
+  "bugs": {
+    "url": "https://github.com/timrwood/underscore.date/issues"
+  },
+  "licenses" : [
+    { "type" : "MIT" }
+  ]
+}
index 5fd882fda0ccc6a15d1983a023ccdf49eaf10488..ff7f2e615d89b5e504fae26ed67d94da01db9539 100644 (file)
@@ -4,7 +4,6 @@
         <title>Underscore.date customization test suite</title>
         <link rel="stylesheet" href="vendor/qunit.css" type="text/css" media="screen" />
         <script type="text/javascript" src="vendor/jquery.js"></script>
-        <script type="text/javascript" src="vendor/underscore.js"></script>
         <script type="text/javascript" src="../lib/underscore.date.js"></script>
         <script type="text/javascript" src="vendor/qunit.js"></script>
         <script type="text/javascript" src="customizeDate.js"></script>
index 5cb92c4387db3cf7ef5c620380bd90809b83b8ce..01e1ea73645a63b579049da9184298a461f01b59 100644 (file)
@@ -1,5 +1,7 @@
 $(function() {
 
+    _ = _date;
+
     module("Customize");
     
     _.date().customize({
index 2c2c9361c1f53fbf0ec63c0c8b017b4cc4782119..3f754bfaece613d322a8de6b87c5fca1b2c49de1 100644 (file)
@@ -4,7 +4,6 @@
         <title>Underscore.date customization test suite</title>
         <link rel="stylesheet" href="vendor/qunit.css" type="text/css" media="screen" />
         <script type="text/javascript" src="vendor/jquery.js"></script>
-        <script type="text/javascript" src="vendor/underscore.js"></script>
         <script type="text/javascript" src="../lib/underscore.date.js"></script>
         <script type="text/javascript" src="vendor/qunit.js"></script>
         <script type="text/javascript" src="customizePartial.js"></script>
index 12c3601e96a4e7769f11831950d783234cb6703f..71f61b205dea02ffc98f47c96f651d49668ca127 100644 (file)
@@ -1,18 +1,20 @@
 $(function() {
 
+    _ = _date;
+    
     module("Customize");
     
     _.date().customize({
         months : ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"],
         weekdays : ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"],
         relativeTime : {
-            future: "%s from now",
-            past: "%s ago",
-            s: "moments",
-            M: "a month",
-            MM: "%d months",
-            y: "a year",
-            yy: "%d years"
+            future: "test %s from now",
+            past: "test %s ago",
+            s: "test moments",
+            M: "test a month",
+            MM: "test %d months",
+            y: "test a year",
+            yy: "test %d years"
         },
         ordinal : function(number) {
             return 'o';
@@ -39,22 +41,22 @@ $(function() {
 
     test("_.date().relative()", 11, function() {
         var start = _.date([2007, 1, 28]);
-        equal(start.from(_.date([2007, 1, 28]).add({s:30}), true), "moments");
+        equal(start.from(_.date([2007, 1, 28]).add({s:30}), true), "test moments");
         equal(start.from(_.date([2007, 1, 28]).add({s:60}), true), "a minute");
         equal(start.from(_.date([2007, 1, 28]).add({m:5}), true), "5 minutes");
         equal(start.from(_.date([2007, 1, 28]).add({h:1}), true), "an hour");
         equal(start.from(_.date([2007, 1, 28]).add({h:5}), true), "5 hours");
         equal(start.from(_.date([2007, 1, 28]).add({d:1}), true), "a day");
         equal(start.from(_.date([2007, 1, 28]).add({d:5}), true), "5 days");
-        equal(start.from(_.date([2007, 1, 28]).add({M:1}), true), "a month");
-        equal(start.from(_.date([2007, 1, 28]).add({M:5}), true), "5 months");
-        equal(start.from(_.date([2007, 1, 28]).add({y:1}), true), "a year");
-        equal(start.from(_.date([2007, 1, 28]).add({y:5}), true), "5 years");
+        equal(start.from(_.date([2007, 1, 28]).add({M:1}), true), "test a month");
+        equal(start.from(_.date([2007, 1, 28]).add({M:5}), true), "test 5 months");
+        equal(start.from(_.date([2007, 1, 28]).add({y:1}), true), "test a year");
+        equal(start.from(_.date([2007, 1, 28]).add({y:5}), true), "test 5 years");
     });
     
     test("_.fromNow()", 2, function() {
-        equal(_.date(30000).from(0), "moments from now");
-        equal(_.date(0).from(30000), "moments ago");
+        equal(_.date(30000).from(0), "test test moments from now");
+        equal(_.date(0).from(30000), "test test moments ago");
     });
 
 });
index 3f660fbd94a883a96b4a8b9fc12882dea4871928..479a0a30f91bc5b0d560795ecb511f89ca189819 100644 (file)
@@ -1,13 +1,15 @@
 $(function() {
 
+    _ = _date;
+    
     module("Date");
     
     test("_.date()", 6, function() {
-        ok(_.isDate(_.date([2010, 1, 12]).date), "[2010, 1, 12]");
-        ok(_.isDate(_.date([2010, 1, 12, 1]).date), "[2010, 1, 12, 1]");
-        ok(_.isDate(_.date().date), "undefined");
-        ok(_.isDate(_.date("Aug 9, 1995").date), "Aug 9, 1995");
-        ok(_.isDate(_.date("Mon, 25 Dec 1995 13:30:00 GMT").date), "Mon, 25 Dec 1995 13:30:00 GMT");
+        ok(_.date([2010, 1, 12]).date instanceof Date, "[2010, 1, 12]");
+        ok(_.date([2010, 1, 12, 1]).date instanceof Date, "[2010, 1, 12, 1]");
+        ok(_.date().date instanceof Date, "undefined");
+        ok(_.date("Aug 9, 1995").date instanceof Date, "Aug 9, 1995");
+        ok(_.date("Mon, 25 Dec 1995 13:30:00 GMT").date instanceof Date, "Mon, 25 Dec 1995 13:30:00 GMT");
         deepEqual(_.date(new Date(2010, 1, 14, 15, 25, 50, 125)), _.date([2010, 1, 14, 15, 25, 50, 125]), "constructing with array === constructing with new Date()");
     });
     
@@ -37,9 +39,9 @@ $(function() {
     });
 
     test("_.date().add() + _.date().subtract()", 5, function() {
-        equal(_([2010, 1, 14, 15, 25, 50, 125]).date().add({ms:200,s:10,m:10,h:2,d:3,M:2,y:3}).format("MMMM Do YYYY, h:mm:ss a"), "April 17th 2013, 5:36:00 pm");
-        equal(_([2010, 0, 31]).date().format("MMMM Do YYYY"), "January 31st 2010");
-        equal(_([2010, 0, 31]).date().add({M:1}).format("MMMM Do YYYY"), "February 28th 2010");
+        equal(_.date([2010, 1, 14, 15, 25, 50, 125]).add({ms:200,s:10,m:10,h:2,d:3,M:2,y:3}).format("MMMM Do YYYY, h:mm:ss a"), "April 17th 2013, 5:36:00 pm");
+        equal(_.date([2010, 0, 31]).format("MMMM Do YYYY"), "January 31st 2010");
+        equal(_.date([2010, 0, 31]).add({M:1}).format("MMMM Do YYYY"), "February 28th 2010");
         equal(_.date([2007, 1, 28]).format("MMMM Do YYYY"), "February 28th 2007");
         equal(_.date([2007, 1, 28]).subtract({M:1}).format("MMMM Do YYYY"), "January 28th 2007");
     });
index 671e693f9ed56459ed8c88809dd90adaab687c55..c8cb5604e455d2133390bea78340258f92ffff34 100644 (file)
@@ -1,5 +1,7 @@
 (function() {
 
+    _ = _date;
+    
        var date1 = new Date(2010, 2, 6, 15, 25, 50, 125),
                date2 = new Date(1000),
                rt1 = 1000 * 60 * 60 * 24 * 365 * 5,
index c69879082305f26071018e1d88d9230e4f52ec49..8315a4a406726ef6323d5f9bd58c328f44bc6f8a 100644 (file)
@@ -4,7 +4,6 @@
   <title>Underscore.date test suite</title>
   <link rel="stylesheet" href="vendor/qunit.css" type="text/css" media="screen" />
   <script type="text/javascript" src="vendor/jquery.js"></script>
-  <script type="text/javascript" src="vendor/underscore.js"></script>
   <script type="text/javascript" src="../lib/underscore.date.js"></script>
   <script type="text/javascript" src="vendor/qunit.js"></script>
   <script type="text/javascript" src="vendor/jslitmus.js"></script>
diff --git a/underscore.date.js b/underscore.date.js
new file mode 100644 (file)
index 0000000..64c48a6
--- /dev/null
@@ -0,0 +1,338 @@
+// Underscore.date
+//
+// (c) 2011 Tim Wood
+// Underscore.date is freely distributable under the terms of the MIT license.
+//
+// Version 0.4.0
+
+(function(undefined){
+    // Establish the root object, "window" in the browser, or "global" on the server.
+    var root = this;
+
+    // assign variables here so they can be overwritten for i18n or customization
+    var self = this, _date,
+        wordsMonths = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
+        wordsMonthsShort = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
+        wordsWeekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
+        wordsWeekdaysShort = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
+        wordsTimeAgo = {
+            future: "in %s",
+            past: "%s ago",
+            s: "seconds",
+            m: "a minute",
+            mm: "%d minutes",
+            h: "an hour",
+            hh: "%d hours",
+            d: "a day",
+            dd: "%d days",
+            M: "a month",
+            MM: "%d months",
+            y: "a year",
+            yy: "%d years"
+        },
+        createOrdinal = function(number) {
+            var b = number % 10;
+            return (~~ (number % 100 / 10) === 1) ? 'th' : 
+                (b === 1) ? 'st' : 
+                (b === 2) ? 'nd' : 
+                (b === 3) ? 'rd' : 'th';
+        };
+    
+    // left zero fill a number
+    // see http://jsperf.com/left-zero-filling for performance comparison
+    function leftZeroFill(number, targetLength) {
+        var output = number + '';
+        while (output.length < targetLength) {
+            output = '0' + output;
+        }
+        return output;
+    }
+    
+    // helper function for _.addTime and _.subtractTime
+    function dateAddRemove(_this, input, adding){
+        var self = _this.date,
+            ms = (input.ms || 0) +
+            (input.s  || 0) * 1e3 + // 1000
+            (input.m  || 0) * 6e4 + // 1000 * 60
+            (input.h  || 0) * 36e5 + // 1000 * 60 * 60
+            (input.d  || 0) * 864e5 + // 1000 * 60 * 60 * 24
+            (input.w  || 0) * 6048e5, // 1000 * 60 * 60 * 24 * 7
+            M = (input.M || 0) + 
+            (input.y || 0) * 12,
+            currentDate;
+        if (ms) {
+            self.setMilliseconds(self.getMilliseconds() + ms * adding);
+        }
+        if (M) {
+            currentDate = self.getDate();
+            self.setDate(1);
+            self.setMonth(self.getMonth() + M * adding);
+            self.setDate(Math.min(new Date(self.getFullYear(), self.getMonth() + 1, 0).getDate(), currentDate)); 
+        }
+        return _this;
+    }
+    
+    // convert an array to a date.
+    // the array should mirror the parameters below
+    // note: all values past the year are optional and will default to the lowest possible value.
+    // [year, month, day , hour, minute, second, millisecond]
+    function dateFromArray(input) {
+        return new Date(input[0], input[1] || 0, input[2] || 1, input[3] || 0, input[4] || 0, input[5] || 0, input[6] || 0);
+    }
+    
+    // check if is an array
+    function isArray(input) {
+        return Object.prototype.toString.call(input) === '[object Array]';
+    }
+    
+    // convert any input to a date
+    //
+    // undefined = _.now()
+    // date = date
+    // array = new Date(array)
+    // number = new Date(number)
+    // string = new Date(string)
+    function makeInputDate(input){
+        return input === undefined ? new Date() :
+            input instanceof _Date ? input.date :
+            input instanceof Date ? input : 
+            isArray(input) && input.length > 2 ? dateFromArray(input) :
+            new Date(input);
+    }
+    
+    // convert any input to milliseconds
+    //
+    // undefined = _.now()
+    // number = number
+    // date = date.gettime()
+    // array = new Date(array).getTime()
+    // string = new Date(string).getTime()
+    function makeInputMilliseconds(input){
+        return isNaN(input) ? makeInputDate(input).getTime() : input;
+    }
+    
+    // helper function for _.relativeTime
+    function substituteTimeAgo(string, number) {
+        return wordsTimeAgo[string].replace(/%d/i, number || 1);
+    }
+    
+    function msApart(time, now) {
+        return makeInputMilliseconds(time) - makeInputMilliseconds(now);
+    }
+    
+    function relativeTime(milliseconds) {
+        var seconds = Math.abs(milliseconds) / 1000,
+            minutes = seconds / 60,
+            hours = minutes / 60,
+            days = hours / 24,
+            years = days / 365;
+        return seconds < 45 && substituteTimeAgo('s', ~~ seconds) ||
+            seconds < 90 && substituteTimeAgo('m') ||
+            minutes < 45 && substituteTimeAgo('mm', ~~ minutes) ||
+            minutes < 90 && substituteTimeAgo('h') ||
+            hours < 24 && substituteTimeAgo('hh', ~~ hours) ||
+            hours < 48 && substituteTimeAgo('d') ||
+            days < 25 && substituteTimeAgo('dd', ~~ days) ||
+            days < 45 && substituteTimeAgo('M') ||
+            days < 350 && substituteTimeAgo('MM', ~~ ((days + 15) / 30)) ||
+            years < 2 && substituteTimeAgo('y') ||
+            substituteTimeAgo('yy', ~~ years);
+    }
+    
+    // _Date prototype object
+    function _Date(input) {
+        this.date = makeInputDate(input);
+        return this;
+    }
+    
+    var _DateProto = _Date.prototype = {
+        
+        format : function(inputString) {
+            // shortcuts to this and getting time functions
+            // done to save bytes in minification
+            var date = this.date,
+                currentMonth = date.getMonth(),
+                currentDate = date.getDate(),
+                currentYear = date.getFullYear(),
+                currentDay = date.getDay(),
+                currentHours = date.getHours(),
+                currentMinutes = date.getMinutes(),
+                currentSeconds = date.getSeconds(),
+                currentString = date.toString(),
+                charactersToReplace = /(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|dddd?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|zz?)/g,
+                nonuppercaseLetters = /[^A-Z]/g;
+            // check if the character is a format
+            // return formatted string or non string.
+            //
+            // uses switch/case instead of an object of named functions (like http://phpjs.org/functions/date:380) 
+            // for minification and performance
+            // see http://jsperf.com/object-of-functions-vs-switch for performance comparison
+            function replaceFunction(input) {
+                // create a couple variables to be used later inside one of the cases.
+                var a, b;
+                switch (input) {
+                    // MONTH
+                    case 'M' : 
+                        return currentMonth + 1;
+                    case 'Mo' : 
+                        return (currentMonth + 1) + createOrdinal(currentMonth + 1);
+                    case 'MM' :
+                        return leftZeroFill(currentMonth + 1, 2);
+                    case 'MMM' : 
+                        return wordsMonthsShort[currentMonth];
+                    case 'MMMM' : 
+                        return wordsMonths[currentMonth];
+                    // DAY OF MONTH
+                    case 'D' : 
+                        return currentDate;
+                    case 'Do' : 
+                        return currentDate + createOrdinal(currentDate);
+                    case 'DD' : 
+                        return leftZeroFill(currentDate, 2);
+                    // DAY OF YEAR
+                    case 'DDD' :
+                        a = new Date(currentYear, currentMonth, currentDate);
+                        b = new Date(currentYear, 0, 1);
+                        return ~~ (((a - b) / 864e5) + 1.5);
+                    case 'DDDo' : 
+                        a = replaceFunction('DDD');
+                        return a + createOrdinal(a);
+                    case 'DDDD' :
+                        return leftZeroFill(replaceFunction('DDD'), 3);
+                    // WEEKDAY
+                    case 'd' :
+                        return currentDay;
+                    case 'do' : 
+                        return currentDay + createOrdinal(currentDay);
+                    case 'ddd' : 
+                        return wordsWeekdaysShort[currentDay];
+                    case 'dddd' : 
+                        return wordsWeekdays[currentDay];
+                    // WEEK OF YEAR
+                    case 'w' : 
+                        a = new Date(currentYear, currentMonth, currentDate - currentDay + 5);
+                        b = new Date(a.getFullYear(), 0, 4);
+                        return ~~ ((a - b) / 864e5 / 7 + 1.5);
+                    case 'wo' : 
+                        a = replaceFunction('w');
+                        return a + createOrdinal(a);
+                    case 'ww' : 
+                        return leftZeroFill(replaceFunction('w'), 2);
+                    // YEAR
+                    case 'YY' : 
+                        return (currentYear + '').slice(-2);
+                    case 'YYYY' : 
+                        return currentYear;
+                    // AM / PM
+                    case 'a' : 
+                        return currentHours > 11 ? 'pm' : 'am';
+                    case 'A' :
+                        return currentHours > 11 ? 'PM' : 'AM';
+                    // 24 HOUR 
+                    case 'H' : 
+                        return currentHours;
+                    case 'HH' : 
+                        return leftZeroFill(currentHours, 2);
+                    // 12 HOUR 
+                    case 'h' : 
+                        return currentHours % 12 || 12;
+                    case 'hh' : 
+                        return leftZeroFill(currentHours % 12 || 12, 2);
+                    // MINUTE
+                    case 'm' : 
+                        return currentMinutes;
+                    case 'mm' : 
+                        return leftZeroFill(currentMinutes, 2);
+                    // SECOND
+                    case 's' : 
+                        return currentSeconds;
+                    case 'ss' : 
+                        return leftZeroFill(currentSeconds, 2);
+                    // TIMEZONE
+                    case 'z' :
+                        return replaceFunction('zz').replace(nonuppercaseLetters, '');
+                    case 'zz' : 
+                        a = currentString.indexOf('(');
+                        if (a > -1) {
+                            return currentString.slice(a + 1, currentString.indexOf(')'));
+                        }
+                        return currentString.slice(currentString.indexOf(':')).replace(nonuppercaseLetters, '');
+                    // DEFAULT
+                    default :
+                        return input.replace("\\", "");
+                }
+            }
+            return inputString.replace(charactersToReplace, replaceFunction);
+        },
+        add : function(input) {
+            return dateAddRemove(this, input, 1);
+        },
+        subtract : function(input) {
+            return dateAddRemove(this, input, -1);
+        },
+        customize : function(input) {
+            var inputOrdinal = input.ordinal,
+                inputRelativeTime = input.relativeTime;
+            if (input.weekdays) {
+                wordsWeekdays = input.weekdays;
+            }
+            if (input.weekdaysShort) {
+                wordsWeekdaysShort = input.weekdaysShort;
+            }
+            if (input.months) {
+                wordsMonths = input.months;
+            }
+            if (input.monthsShort) {
+                wordsMonthsShort = input.monthsShort;
+            }
+            if (inputRelativeTime) {
+                for (var key in inputRelativeTime) {
+                    if (inputRelativeTime.hasOwnProperty(key)) {
+                        wordsTimeAgo[key] = inputRelativeTime[key];
+                    }
+                }
+            }
+            if (inputOrdinal && inputOrdinal instanceof Function) {
+                createOrdinal = inputOrdinal;
+            }
+        },
+        from : function(time, withoutSuffix, asMilliseconds) {
+            var difference = msApart(this.date, time),
+                string = difference < 0 ? wordsTimeAgo.past : wordsTimeAgo.future;
+            return asMilliseconds ? difference : 
+                withoutSuffix ? relativeTime(difference) :
+                string.replace(/%s/i, relativeTime(difference));
+        },
+        fromNow : function(withoutSuffix, asMilliseconds) {
+            return this.from(_date.now(), withoutSuffix, asMilliseconds);
+        },
+        isLeapYear : function() {
+            return _date.isLeapYear(this.date.getFullYear());
+        }
+    };
+    
+    _date = {
+        date : function(input) {
+            return new _Date(input);
+        },
+        now : function(asTimestamp) {
+            return asTimestamp ? new Date().getTime() : _date.date();
+        },
+        isLeapYear : function(year) {
+            return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+        }
+    };
+    
+    // CommonJS module is defined
+    if (typeof window === 'undefined' && typeof module !== 'undefined') {
+        // Export module
+        module.exports = _date;
+    // Integrate with Underscore.js
+    } else if (root._ !== undefined) {
+        root._.mixin(_date);
+    // Or define it
+    } else {
+        root._ = _date;
+    }
+    
+}());
diff --git a/underscore.date.min.js b/underscore.date.min.js
new file mode 100644 (file)
index 0000000..4be77a9
--- /dev/null
@@ -0,0 +1 @@
+(function(a){function t(a){this.date=o(a);return this}function s(a){var b=Math.abs(a)/1e3,c=b/60,d=c/60,e=d/24,f=e/365;return b<45&&q("s",~~b)||b<90&&q("m")||c<45&&q("mm",~~c)||c<90&&q("h")||d<24&&q("hh",~~d)||d<48&&q("d")||e<25&&q("dd",~~e)||e<45&&q("M")||e<350&&q("MM",~~((e+15)/30))||f<2&&q("y")||q("yy",~~f)}function r(a,b){return p(a)-p(b)}function q(a,b){return i[a].replace(/%d/i,b||1)}function p(a){return isNaN(a)?o(a).getTime():a}function o(b){return b===a?new Date:b instanceof t?b.date:b instanceof Date?b:n(b)&&b.length>2?m(b):new Date(b)}function n(a){return Object.prototype.toString.call(a)==="[object Array]"}function m(a){return new Date(a[0],a[1]||0,a[2]||1,a[3]||0,a[4]||0,a[5]||0,a[6]||0)}function l(a,b,c){var d=a.date,e=(b.ms||0)+(b.s||0)*1e3+(b.m||0)*6e4+(b.h||0)*36e5+(b.d||0)*864e5+(b.w||0)*6048e5,f=(b.M||0)+(b.y||0)*12,g;e&&d.setMilliseconds(d.getMilliseconds()+e*c),f&&(g=d.getDate(),d.setDate(1),d.setMonth(d.getMonth()+f*c),d.setDate(Math.min((new Date(d.getFullYear(),d.getMonth()+1,0)).getDate(),g)));return a}function k(a,b){var c=a+"";while(c.length<b)c="0"+c;return c}var b=this,c=this,d,e=["January","February","March","April","May","June","July","August","September","October","November","December"],f=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],g=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],h=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],i={future:"in %s",past:"%s ago",s:"seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},j=function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"},u=t.prototype={format:function(a){function s(a){var b,q;switch(a){case"M":return c+1;case"Mo":return c+1+j(c+1);case"MM":return k(c+1,2);case"MMM":return f[c];case"MMMM":return e[c];case"D":return d;case"Do":return d+j(d);case"DD":return k(d,2);case"DDD":b=new Date(i,c,d),q=new Date(i,0,1);return~~((b-q)/864e5+1.5);case"DDDo":b=s("DDD");return b+j(b);case"DDDD":return k(s("DDD"),3);case"d":return l;case"do":return l+j(l);case"ddd":return h[l];case"dddd":return g[l];case"w":b=new Date(i,c,d-l+5),q=new Date(b.getFullYear(),0,4);return~~((b-q)/864e5/7+1.5);case"wo":b=s("w");return b+j(b);case"ww":return k(s("w"),2);case"YY":return(i+"").slice(-2);case"YYYY":return i;case"a":return m>11?"pm":"am";case"A":return m>11?"PM":"AM";case"H":return m;case"HH":return k(m,2);case"h":return m%12||12;case"hh":return k(m%12||12,2);case"m":return n;case"mm":return k(n,2);case"s":return o;case"ss":return k(o,2);case"z":return s("zz").replace(r,"");case"zz":b=p.indexOf("(");if(b>-1)return p.slice(b+1,p.indexOf(")"));return p.slice(p.indexOf(":")).replace(r,"");default:return a.replace("\\","")}}var b=this.date,c=b.getMonth(),d=b.getDate(),i=b.getFullYear(),l=b.getDay(),m=b.getHours(),n=b.getMinutes(),o=b.getSeconds(),p=b.toString(),q=/(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|dddd?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|zz?)/g,r=/[^A-Z]/g;return a.replace(q,s)},add:function(a){return l(this,a,1)},subtract:function(a){return l(this,a,-1)},customize:function(a){var b=a.ordinal,c=a.relativeTime;a.weekdays&&(g=a.weekdays),a.weekdaysShort&&(h=a.weekdaysShort),a.months&&(e=a.months),a.monthsShort&&(f=a.monthsShort);if(c)for(var d in c)c.hasOwnProperty(d)&&(i[d]=c[d]);b&&b instanceof Function&&(j=b)},from:function(a,b,c){var d=r(this.date,a),e=d<0?i.past:i.future;return c?d:b?s(d):e.replace(/%s/i,s(d))},fromNow:function(a,b){return this.from(d.now(),a,b)},isLeapYear:function(){return d.isLeapYear(this.date.getFullYear())}};d={date:function(a){return new t(a)},now:function(a){return a?(new Date).getTime():d.date()},isLeapYear:function(a){return a%4===0&&a%100!==0||a%400===0}},typeof window=="undefined"&&typeof module!="undefined"?module.exports=d:b._!==a?b._.mixin(d):b._=d})()
\ No newline at end of file