diff --git a/src/util/strftime.js b/src/util/strftime.js index 051102269..7a097e78d 100644 --- a/src/util/strftime.js +++ b/src/util/strftime.js @@ -24,20 +24,6 @@ var _date = { return [31, feb, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; }, - getTimezone: function(d) { - return d.toString().replace( - /^.*? ([A-Z]{3}) [0-9]{4}.*$/, "$1" - ).replace( - /^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3" - ); - }, - - getGMTOffset: function(d) { - return (d.getTimezoneOffset() > 0 ? "-" : "+") + - _number.pad(Math.floor(d.getTimezoneOffset() / 60), 2) + - _number.pad(d.getTimezoneOffset() % 60, 2); - }, - getDayOfYear: function(d) { var num = 0; for (var i = 0; i < d.getMonth(); ++i) { @@ -62,27 +48,12 @@ var _date = { return !!((year & 3) === 0 && (year % 100 || (year % 400 === 0 && year))); }, - getFirstDayOfMonth: function(d) { - var day = (d.getDay() - (d.getDate() - 1)) % 7; - return (day < 0) ? (day + 7) : day; - }, - - getLastDayOfMonth: function(d) { - var day = (d.getDay() + (_date.daysInMonth(d)[d.getMonth()] - d.getDate())) % 7; - return (day < 0) ? (day + 7) : day; - }, - getSuffix: function(d) { var str = d.getDate().toString(); var index = parseInt(str.slice(-1)); return suffixes[index] || suffixes['default']; }, - applyOffset: function(date, offset_seconds) { - date.setTime(date.valueOf() - offset_seconds * 1000); - return date; - }, - century: function(d) { return parseInt(d.getFullYear().toString().substring(0, 2), 10); } @@ -191,12 +162,9 @@ var format_codes = { Y: function(d) { return d.getFullYear(); }, - // TODO: guessing the pad function won't work with negative numbers? - // TODO: getTimezoneOffset returns a positive number for GMT-7. Verify my - // assumption that it will return negative for GMT+x z: function(d) { var tz = d.getTimezoneOffset() / 60 * 100; - return (tz > 0 ? '-' : '+') + _number.pad(tz, 4); + return (tz > 0 ? '-' : '+') + _number.pad(Math.abs(tz), 4); }, "%": function() { return '%'; @@ -206,19 +174,6 @@ format_codes.h = format_codes.b; format_codes.N = format_codes.L; var strftime = function(d, format) { - // I used to use string split with a regex and a capturing block here, - // which I thought was really clever, but apparently this exact feature is - // fucked in IE. In every other browser (and languages), the captured - // blocks are present in the output. E.g. - // var pairs = "hello%athere".split(/(%.)/); - // => ['hello', '%a', 'there'] - // IE however, just treats it the same as if no capturing block is present - // => ['hello', 'there'] - // An alternate implementation of split is available here - // http://blog.stevenlevithan.com/archives/cross-browser-split - // Because that's a large amount of code for this one specific use case, - // I've just decided to loop through a regex instead. - var output = ''; var remaining = format; diff --git a/test/util/strftime.js b/test/util/strftime.js index 8653bf0df..912e284b9 100644 --- a/test/util/strftime.js +++ b/test/util/strftime.js @@ -4,18 +4,112 @@ const expect = chai.expect; var t = require('../../src/util/strftime.js'); describe('util/strftime', function() { - var now = new Date('2016-10-24T00:15:23+08:00'); - it('should format week by %U', function() { - expect(t(now, '%U')).to.equal('43'); + var now; + before(function() { + mockUTC(); + now = new Date('2016-01-04T13:15:23'); + then = new Date('2016-01-03T03:05:03'); }); - it('should format locale date string', function() { - var date = now.toLocaleDateString('en-US'); - expect(t(now, '%m/%d/%Y')).to.equal(date); + after(function() { + restoreUTC(); }); - it('should format locale date string', function() { - var time = now.toLocaleTimeString('en-US', { - hour12: false - }); - expect(t(now, '%H:%M:%S')).to.equal(time); + + it('should format UTC datetime', function() { + expect(t(now, '%Y-%m-%dT%H:%M:%S')).to.equal('2016-01-04T13:15:23'); + }); + it('should format %A as Monday', function() { + expect(t(now, '%A')).to.equal('Monday'); + }); + it('should format %B as month name', function() { + expect(t(now, '%B')).to.equal('January'); + }); + it('should format %C as century', function() { + expect(t(now, '%C')).to.equal('20'); + }); + it('should format %c as local string', function() { + expect(t(now, '%c')).to.equal(now.toLocaleString()); + }); + it('should format %e as space padded date', function() { + expect(t(now, '%e')).to.equal(' 4'); + }); + it('should format %I as 0 padded hour12', function() { + expect(t(now, '%I')).to.equal('01'); + }); + it('should format %j as day of year', function() { + expect(t(now, '%j')).to.equal('004'); + }); + it('should format %k as space padded hour', function() { + expect(t(then, '%k')).to.equal(' 3'); + }); + it('should format %l as space padded hour12', function() { + expect(t(now, '%l')).to.equal(' 1'); + }); + it('should format %L as 0 padded millisecond', function() { + expect(t(then, '%L')).to.equal('000'); + }); + it('should format %p as upper cased am/pm', function() { + expect(t(now, '%p')).to.equal('PM'); + expect(t(then, '%p')).to.equal('AM'); + }); + it('should format %P as lower cased am/pm', function() { + expect(t(now, '%P')).to.equal('pm'); + expect(t(then, '%P')).to.equal('am'); + }); + it('should format %q as date suffix', function(){ + expect(t(now, '%q')).to.equal('th'); + expect(t(then, '%q')).to.equal('rd'); + }); + it('should format %s as UNIX seconds', function(){ + expect(t(now, '%s')).to.be.match(/\d+/); + }); + it('should format %u as day of week(1-7)', function(){ + expect(t(now, '%u')).to.be.equal('1'); + expect(t(then, '%u')).to.be.equal('7'); + }); + it('should format %U as week of year, starts with 0', function() { + expect(t(now, '%U')).to.equal('01'); + }); + it('should format %w as day of month(0-7)', function(){ + expect(t(now, '%w')).to.be.equal('1'); + expect(t(then, '%w')).to.be.equal('0'); + }); + it('should format %W as week of year, starts with 1', function(){ + expect(t(now, '%W')).to.be.equal('01'); + }); + it('should format %x as local date string', function() { + expect(t(now, '%x')).to.equal(now.toLocaleDateString()); + }); + it('should format %X as local time string', function() { + expect(t(now, '%X')).to.equal(now.toLocaleTimeString()); + }); + it('should format %y as 2-digit year', function() { + expect(t(now, '%y')).to.equal('16'); + }); + it('should format %z as time zone', function() { + expect(t(now, '%z')).to.equal('+0800'); + }); + it('should escape %% as %', function() { + expect(t(now, '%%')).to.equal('%'); }); }); + + +function mockUTC() { + var p = Date.prototype; + + p._getHours = p.getHours; + p.getHours = p.getUTCHours; + + p._getDays = p.getDays; + p.getDays = p.getUTCDays; + + p._getTimezoneOffset = p._getTimezoneOffset; + p.getTimezoneOffset = () => -480; +} + +function restoreUTC() { + var p = Date.prototype; + p.getHours = p._getHours; + p.getDays = p._getDays; + p.getTimezoneOffset = p._getTimezoneOffset; +}