diff --git a/strftime.js b/strftime.js index 4cb902d..c3689ed 100644 --- a/strftime.js +++ b/strftime.js @@ -51,37 +51,7 @@ var _locale; var _date; var _timeZone; - var _timestamp; - - function strftime(fmt, d, locale) { - return _strftime(fmt, d, locale); - } - - function strfTimeTZ(fmt, d, locale, timezone) { - var _locale = locale; - var _timezone = timezone; - - if ((typeof locale === 'number' || typeof locale === 'string') && timezone == null) { - _timezone = locale; - _locale = undefined; - } - - return _strftime(fmt, d, _locale, { - timezone: _timezone - }); - } - - function strftimeUTC(fmt, d, locale) { - return _strftime(fmt, d, locale, { - utc: true - }); - } - - function localizedStrftime(locale) { - return function (fmt, d, options) { - return _strftime(fmt, d, locale, options); - }; - } + var _padding; // d, locale, and options are optional, but you can't leave // holes in the argument list. If you pass options you have to pass @@ -103,10 +73,6 @@ } _date = _date || new Date(); - - // Hang on to this Unix timestamp because we might mess with it directly below. - _timestamp = _date.getTime(); - _locale = _locale || DefaultLocale; _locale.formats = _locale.formats || {}; @@ -116,7 +82,7 @@ _date = dateToUTC(_date); } - if (_timeZone) { + /*if (_timeZone) { // ISO 8601 format timezone string, [-+]HHMM // Convert to the number of minutes and it'll be applied to the date below. if (tzType === 'string') { @@ -128,338 +94,171 @@ } _date = new Date(_date.getTime() + (_timeZone * 60000)); - } + }*/ // Most of the specifiers supported by C's strftime, and some from Ruby. // Some other syntax extensions from Ruby are supported: %-, %_, and %0 // to pad with nothing, space, or zero (respectively). - /*var part; - var regExp = /%([-_0]?.)/g;*/ - // while (part = regExp.exec(format)) { - // var padding; - // var _c = part[1]; - // - // if (_c.length === 2) { - // switch (_c[0]) { - // // omit padding - // case '-': - // padding = ''; - // break; - // - // // pad with space - // case '_': - // padding = ' '; - // break; - // - // // pad with zero - // case '0': - // padding = '0'; - // break; - // - // // unrecognized, return the format - // default: - // return part[0]; - // } - // - // _c = _c[1]; - // } - // - // switch (_c) { - // // Examples for new Date(0) in GMT - // - // // 'Thursday' - // case 'A': - // return _locale.days[_d.getDay()]; - // - // // 'Thu' - // case 'a': - // return _locale.shortDays[_d.getDay()]; - // - // // 'January' - // case 'B': - // return _locale.months[_d.getMonth()]; - // - // // 'Jan' - // case 'b': - // return _locale.shortMonths[_d.getMonth()]; - // - // // '19' - // case 'C': - // return pad(Math.floor(_d.getFullYear() / 100), padding); - // - // // '01/01/70' - // case 'D': - // return _strftime(_locale.formats.D || '%m/%d/%y', _d, _locale); - // - // // '01' - // case 'd': - // return pad(_d.getDate(), padding); - // - // // '01' - // case 'e': - // return _d.getDate(); - // - // // '1970-01-01' - // case 'F': - // return _strftime(_locale.formats.F || '%Y-%m-%d', _d, _locale); - // - // // '00' - // case 'H': - // return pad(_d.getHours(), padding); - // - // // 'Jan' - // case 'h': - // return _locale.shortMonths[_d.getMonth()]; - // - // // '12' - // case 'I': - // return pad(hours12(_d), padding); - // - // // '000' - // case 'j': - // var y = new Date(_d.getFullYear(), 0, 1); - // var day = Math.ceil((_d.getTime() - y.getTime()) / (1000 * 60 * 60 * 24)); - // return pad(day, null, 3); - // - // // ' 0' - // case 'k': - // return pad(_d.getHours(), padding == null ? ' ' : padding); - // - // // '000' - // case 'L': - // return pad(Math.floor(timestamp % 1000), null, 3); - // - // // '12' - // case 'l': - // return pad(hours12(_d), padding == null ? ' ' : padding); - // - // // '00' - // case 'M': - // return pad(_d.getMinutes(), padding); - // - // // '01' - // case 'm': - // return pad(_d.getMonth() + 1, padding); - // - // // '\n' - // case 'n': - // return '\n'; - // - // // '1st' - // case 'o': - // return String(_d.getDate()) + ordinal(_d.getDate()); - // - // // 'am' - // case 'P': - // return _d.getHours() < 12 ? _locale.am : _locale.pm; - // - // // 'AM' - // case 'p': - // return _d.getHours() < 12 ? _locale.AM : _locale.PM; - // - // // '00:00' - // case 'R': - // return _strftime(_locale.formats.R || '%H:%M', _d, _locale); - // - // // '12:00:00 AM' - // case 'r': - // return _strftime(_locale.formats.r || '%I:%M:%S %p', _d, _locale); - // - // // '00' - // case 'S': - // return pad(_d.getSeconds(), padding); - // - // // '0' - // case 's': - // return Math.floor(timestamp / 1000); - // - // // '00:00:00' - // case 'T': - // return _strftime(_locale.formats.T || '%H:%M:%S', _d, _locale); - // - // // '\t' - // case 't': - // return '\t'; - // - // // '00' - // case 'U': - // return pad(weekNumber(_d, 'sunday'), padding); - // - // // '4' - // case 'u': - // var day = _d.getDay(); - // return day === 0 ? 7 : day; // 1 - 7, Monday is first day of the week - // - // // '1-Jan-1970' - // case 'v': - // return _strftime(_locale.formats.v || '%e-%b-%Y', _d, _locale); - // - // // '00' - // case 'W': - // return pad(weekNumber(_d, 'monday'), padding); - // - // // '4' - // case 'w': - // return _d.getDay(); // 0 - 6, Sunday is first day of the week - // - // // '1970' - // case 'Y': - // return _d.getFullYear(); - // - // // '70' - // case 'y': - // return String(_d.getFullYear()).slice(-2); - // - // // 'GMT' - // case 'Z': - // if (_options.utc) { - // return 'GMT'; - // } else { - // var tzString = _d.toString().match(/\((\w+)\)/); - // return tzString && tzString[1] || ''; - // } - // - // // '+0000' - // case 'z': - // if (_options.utc) { - // return '+0000'; - // } else { - // var off = typeof tz === 'number' ? tz : -_d.getTimezoneOffset(); - // return (off < 0 ? '-' : '+') + pad(Math.abs(off / 60)) + pad(off % 60); - // } - // - // default: - // return _c; - // } - // } - - return format.replace(/%([-_0]?.)/g, processing); + return format.replace(/%([-_0]?)(.)/g, processing); } - function processing(_, c) { - var padding; - var _c = c; - var day; - - if (_c.length === 2) { - switch (_c[0]) { - // omit padding - case '-': - padding = ''; - break; - - // pad with space - case '_': - padding = ' '; - break; - - // pad with zero - case '0': - padding = '0'; - break; - - // unrecognized, return the format - default: - return _; - } - - _c = _c[1]; - } - - if (_c === 'A') { + var mask = { + 'A': function () { return _locale.days[_date.getDay()]; - } else if (_c === 'a') { + }, + 'a': function () { return _locale.shortDays[_date.getDay()]; - } else if (_c === 'B') { + }, + 'B': function () { return _locale.months[_date.getMonth()]; - } else if (_c === 'b') { + }, + 'b': function () { return _locale.shortMonths[_date.getMonth()]; - } else if (_c === 'C') { - return pad(Math.floor(_date.getFullYear() / 100), padding); - } else if (_c === 'D') { + }, + 'C': function () { + return pad(Math.floor(_date.getFullYear() / 100), _padding); + }, + 'D': function () { return _strftime(_locale.formats.D || '%m/%d/%y', _date, _locale); - } else if (_c === 'd') { - return pad(_date.getDate(), padding); - } else if (_c === 'e') { + }, + 'd': function () { + return pad(_date.getDate(), _padding); + }, + 'e': function () { return _date.getDate(); - } else if (_c === 'F') { + }, + 'F': function () { return _strftime(_locale.formats.F || '%Y-%m-%d', _date, _locale); - } else if (_c === 'H') { - return pad(_date.getHours(), padding); - } else if (_c === 'h') { + }, + 'H': function () { + return pad(_date.getHours(), _padding); + }, + 'h': function () { return _locale.shortMonths[_date.getMonth()]; - } else if (_c === 'I') { - return pad(hours12(_date), padding); - } else if (_c === 'j') { + }, + 'I': function () { + return pad(hours12(_date), _padding); + }, + 'j': function () { var y = new Date(_date.getFullYear(), 0, 1); - day = Math.ceil((_date.getTime() - y.getTime()) / (1000 * 60 * 60 * 24)); + var day = Math.ceil((_date.getTime() - y.getTime()) / (1000 * 60 * 60 * 24)); return pad(day, null, 3); - } else if (_c === 'k') { - return pad(_date.getHours(), padding == null ? ' ' : padding); - } else if (_c === 'L') { - return pad(Math.floor(_timestamp % 1000), null, 3); - } else if (_c === 'l') { - return pad(hours12(_date), padding == null ? ' ' : padding); - } else if (_c === 'M') { - return pad(_date.getMinutes(), padding); - } else if (_c === 'm') { - return pad(_date.getMonth() + 1, padding); - } else if (_c === 'n') { + }, + 'k': function () { + return pad(_date.getHours(), _padding == null ? ' ' : _padding); + }, + 'L': function () { + return pad(Math.floor(_date.getTime() % 1000), null, 3); + }, + 'l': function () { + return pad(hours12(_date), _padding == null ? ' ' : _padding); + }, + 'M': function () { + return pad(_date.getMinutes(), _padding); + }, + 'm': function () { + return pad(_date.getMonth() + 1, _padding); + }, + 'n': function () { return '\n'; - } else if (_c === 'o') { + }, + 'o': function () { return String(_date.getDate()) + ordinal(_date.getDate()); - } else if (_c === 'P') { + }, + 'P': function () { return _date.getHours() < 12 ? _locale.am : _locale.pm; - } else if (_c === 'p') { + }, + 'p': function () { return _date.getHours() < 12 ? _locale.AM : _locale.PM; - } else if (_c === 'R') { + }, + 'R': function () { return _strftime(_locale.formats.R || '%H:%M', _date, _locale); - } else if (_c === 'r') { + }, + 'r': function () { return _strftime(_locale.formats.r || '%I:%M:%S %p', _date, _locale); - } else if (_c === 'S') { - return pad(_date.getSeconds(), padding); - } else if (_c === 's') { - return Math.floor(timestamp / 1000); - } else if (_c === 'T') { + }, + 'S': function () { + return pad(_date.getSeconds(), _padding); + }, + 's': function () { + return Math.floor(_date.getTime() / 1000); + }, + 'T': function () { return _strftime(_locale.formats.T || '%H:%M:%S', _date, _locale); - } else if (_c === 't') { + }, + 't': function () { return '\t'; - } else if (_c === 'U') { - return pad(weekNumber(_date, 'sunday'), padding); - } else if (_c === 'u') { - day = _date.getDay(); + }, + 'U': function () { + return pad(weekNumber(_date, 'sunday'), _padding); + }, + 'u': function () { + var day = _date.getDay(); return day === 0 ? 7 : day; - } else if (_c === 'v') { + }, + 'v': function () { return _strftime(_locale.formats.v || '%e-%b-%Y', _date, _locale); - } else if (_c === 'W') { - return pad(weekNumber(_date, 'monday'), padding); - } else if (_c === 'w') { + }, + 'W': function () { + return pad(weekNumber(_date, 'monday'), _padding); + }, + 'w': function () { return _date.getDay(); - } else if (_c === 'Y') { + }, + 'Y': function () { return _date.getFullYear(); - } else if (_c === 'y') { + }, + 'y': function () { return String(_date.getFullYear()).slice(-2); - } else if (_c === 'Z') { + }, + 'Z': function () { if (_options.utc) { return 'GMT'; } else { var tzString = _date.toString().match(/\((\w+)\)/); return tzString && tzString[1] || ''; } - } else if (_c === 'z') { + }, + 'z': function () { if (_options.utc) { return '+0000'; } else { var off = typeof _timeZone === 'number' ? _timeZone : -_date.getTimezoneOffset(); return (off < 0 ? '-' : '+') + pad(Math.abs(off / 60)) + pad(off % 60); } - } else { - return _c; } + }; + + function processing(_, p, c) { + var _padding; + + if (p) { + switch (p) { + // omit padding + case '-': + _padding = ''; + break; + + // pad with space + case '_': + _padding = ' '; + break; + + // pad with zero + case '0': + _padding = '0'; + break; + + // unrecognized, return the format + default: + return _; + } + } + + return mask[c] ? mask[c]() : c; } - // TODO: Did not inline quacksLikeDate called from _strftime (target requires context change). function quacksLikeDate(x) { var index = RequiredDateMethods.length; @@ -473,7 +272,7 @@ } function dateToUTC(d) { - new Date(d.getTime() + (d.getTimezoneOffset() || 0) * 60000); + return new Date(d.getTime() + (d.getTimezoneOffset() || 0) * 60000); } // Default padding is '0' and default length is 2, both are optional. @@ -544,9 +343,36 @@ return Math.floor((yDay + 7 - wDay) / 7); } + function strftime(fmt, d, locale) { + return _strftime(fmt, d, locale); + } + namespace.strftime = strftime; - namespace.strftimeTZ = strftime.strftimeTZ = strfTimeTZ; - namespace.strftimeUTC = strftime.strftimeUTC = strftimeUTC; - namespace.localizedStrftime = strftime.localizedStrftime = localizedStrftime; + + namespace.strftimeTZ = strftime.strftimeTZ = function strfTimeTZ(fmt, d, locale, timezone) { + var _locale = locale; + var _timezone = timezone; + + if ((typeof locale === 'number' || typeof locale === 'string') && timezone == null) { + _timezone = locale; + _locale = undefined; + } + + return _strftime(fmt, d, _locale, { + timezone: _timezone + }); + }; + + namespace.strftimeUTC = strftime.strftimeUTC = function strftimeUTC(fmt, d, locale) { + return _strftime(fmt, d, locale, { + utc: true + }); + }; + + namespace.localizedStrftime = strftime.localizedStrftime = function localizedStrftime(locale) { + return function (fmt, d, options) { + return _strftime(fmt, d, locale, options); + }; + }; }());