From c8219f62389fe93c653b8f0474bc358743d2395b Mon Sep 17 00:00:00 2001 From: Adam Shaw Date: Sun, 2 Feb 2014 21:51:53 -0800 Subject: [PATCH] parse ISO8601 date strings without date-of-month as first-of-month --- src/moment-ext.js | 39 +++++++++++++++++++++++---------- tests/automated/moment-ambig.js | 18 +++++++++++++++ 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/moment-ext.js b/src/moment-ext.js index c3dc2ad..110dd5a 100644 --- a/src/moment-ext.js +++ b/src/moment-ext.js @@ -1,6 +1,6 @@ -var ambigTimeRegex = /^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))$/; -var ambigZoneRegex = /^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?)?$/; +var ambigDateOfMonthRegex = /^\s*\d{4}-\d\d$/; +var ambigTimeOrZoneRegex = /^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?)?$/; // Creating @@ -28,13 +28,30 @@ fc.moment.parseZone = function() { // when parseZone==true, if can't figure it out, fall back to parseUTC function makeMoment(args, parseUTC, parseZone) { - var isSingleString = args.length == 1 && typeof args[0] === 'string'; - var isAmbigTime = isSingleString && ambigTimeRegex.test(args[0]); // an ISO8601 string without a time part - var isAmbigZone = isAmbigTime || // ambiguously-zoned moments are always ambiguously-timed too - $.isArray(args[0]) || // we consider y/m/d/h/m/s arrays to be lacking a zone - isSingleString && ambigZoneRegex.test(args[0]); // an ISO8601 string without a zone part + var input = args[0]; + var isSingleString = args.length == 1 && typeof input === 'string'; + var isAmbigTime = false; + var isAmbigZone = false; + var ambigMatch; var mom; + if (isSingleString) { + if (ambigDateOfMonthRegex.test(input)) { + // accept strings like '2014-05', but convert to the first of the month + input += '-01'; + isAmbigTime = true; + isAmbigZone = true; + } + else if ((ambigMatch = ambigTimeOrZoneRegex.exec(input))) { + isAmbigTime = !ambigMatch[5]; // no time part? + isAmbigZone = true; + } + } + else if ($.isArray(input)) { + // arrays have no timezone information, so assume ambiguous zone + isAmbigZone = true; + } + if (parseUTC || parseZone || isAmbigTime) { mom = moment.utc.apply(moment, args); } @@ -42,8 +59,8 @@ function makeMoment(args, parseUTC, parseZone) { mom = moment.apply(null, args); } - if (moment.isMoment(args[0])) { - transferAmbigs(args[0], mom); + if (moment.isMoment(input)) { + transferAmbigs(input, mom); } if (isAmbigTime) { @@ -56,9 +73,9 @@ function makeMoment(args, parseUTC, parseZone) { mom._ambigZone = true; } else if (isSingleString) { - mom.zone(args[0]); // if fails, will set it to 0, which it already was + mom.zone(input); // if fails, will set it to 0, which it already was } - else if (isNativeDate(args[0]) || args[0] === undefined) { + else if (isNativeDate(input) || input === undefined) { // native Date object? // specified with no arguments? // then consider the moment to be local diff --git a/tests/automated/moment-ambig.js b/tests/automated/moment-ambig.js index 8336993..00f05f8 100644 --- a/tests/automated/moment-ambig.js +++ b/tests/automated/moment-ambig.js @@ -43,6 +43,12 @@ describe('$.fullCalendar.moment', function() { expect(mom.hasTime()).toBe(false); }); + it('assumes first-of-month and ambiguous time when no date-of-month', function() { + var mom = $.fullCalendar.moment('2014-06'); + expect(mom.format()).toBe('2014-06-01'); + expect(mom.hasTime()).toBe(false); + }); + }); it('is local when given no arguments', function() { @@ -88,6 +94,12 @@ describe('$.fullCalendar.moment.utc', function() { expect(mom.hasTime()).toBe(false); }); + it('assumes first-of-month and ambiguous time when no date-of-month', function() { + var mom = $.fullCalendar.moment.utc('2014-06'); + expect(mom.format()).toBe('2014-06-01'); + expect(mom.hasTime()).toBe(false); + }); + }); it('is UTC when given no arguments', function() { @@ -131,6 +143,12 @@ describe('$.fullCalendar.moment.parseZone', function() { expect(mom.hasTime()).toBe(false); }); + it('assumes first-of-month and ambiguous time when no date-of-month', function() { + var mom = $.fullCalendar.moment.parseZone('2014-06'); + expect(mom.format()).toBe('2014-06-01'); + expect(mom.hasTime()).toBe(false); + }); + }); it('is local when given no arguments', function() {