Skip to content

Commit

Permalink
Support 24:00:00.000 to mean next day, at midnight.
Browse files Browse the repository at this point in the history
  • Loading branch information
ichernev committed Nov 17, 2014
1 parent c5b9092 commit 1214808
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 9 deletions.
30 changes: 27 additions & 3 deletions moment.js
Original file line number Diff line number Diff line change
Expand Up @@ -701,7 +701,10 @@
overflow =
m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR :
m._a[HOUR] < 0 || m._a[HOUR] > 24 ||
(m._a[HOUR] === 24 && (m._a[MINUTE] !== 0 ||
m._a[SECOND] !== 0 ||
m._a[MILLISECOND] !== 0)) ? HOUR :
m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
Expand Down Expand Up @@ -1384,12 +1387,25 @@
config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
}

// Check for 24:00:00.000
if (config._a[HOUR] === 24 &&
config._a[MINUTE] === 0 &&
config._a[SECOND] === 0 &&
config._a[MILLISECOND] === 0) {
config._nextDay = true;
config._a[HOUR] = 0;
}

config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
// Apply timezone offset from input. The actual zone can be changed
// with parseZone.
if (config._tzm != null) {
config._d.setUTCMinutes(config._d.getUTCMinutes() + config._tzm);
}

if (config._nextDay) {
config._a[HOUR] = 24;
}
}

function dateFromObject(config) {
Expand Down Expand Up @@ -1744,7 +1760,8 @@

function makeMoment(config) {
var input = config._i,
format = config._f;
format = config._f,
res;

config._locale = config._locale || moment.localeData(config._l);

Expand All @@ -1768,7 +1785,14 @@
makeDateFromInput(config);
}

return new Moment(config);
res = new Moment(config);
if (res._nextDay) {
// Adding is smart enough around DST
res.add(1, 'd');
res._nextDay = undefined;
}

return res;
}

moment = function (input, format, locale, strict) {
Expand Down
8 changes: 8 additions & 0 deletions test/moment/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,14 @@ exports.create = {
test.done();
},

'iso format 24hrs' : function (test) {
test.equal(moment('2014-01-01T24:00:00.000').format('YYYY-MM-DD[T]HH:mm:ss.SSS'),
'2014-01-02T00:00:00.000', 'iso format with 24:00 localtime');
test.equal(moment.utc('2014-01-01T24:00:00.000').format('YYYY-MM-DD[T]HH:mm:ss.SSS'),
'2014-01-02T00:00:00.000', 'iso format with 24:00 utc');
test.done();
},

'string without format - json' : function (test) {
test.expect(5);
test.equal(moment('Date(1325132654000)').valueOf(), 1325132654000, 'Date(1325132654000)');
Expand Down
8 changes: 4 additions & 4 deletions test/moment/is_valid.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ exports.isValid = {
'2010-00-00',
'2010-01-00',
'2010-01-40',
'2010-01-01T24',
'2010-01-01T24:01', // 24:00:00 is actually valid
'2010-01-01T23:60',
'2010-01-01T23:59:60'
], i;
Expand All @@ -127,7 +127,7 @@ exports.isValid = {
'2010-00-00T+00:00',
'2010-01-00T+00:00',
'2010-01-40T+00:00',
'2010-01-40T24+00:00',
'2010-01-40T24:01+00:00',
'2010-01-40T23:60+00:00',
'2010-01-40T23:59:60+00:00',
'2010-01-40T23:59:59.9999+00:00'
Expand Down Expand Up @@ -165,10 +165,10 @@ exports.isValid = {
},

'invalidAt' : function (test) {
test.expect(7);
test.equal(moment([2000, 12]).invalidAt(), 1, 'month 12 is invalid: 0-11');
test.equal(moment([2000, 1, 30]).invalidAt(), 2, '30 is not a valid february day');
test.equal(moment([2000, 1, 29, 24]).invalidAt(), 3, '24 is invalid hour');
test.equal(moment([2000, 1, 29, 25]).invalidAt(), 3, '25 is invalid hour');
test.equal(moment([2000, 1, 29, 24, 01]).invalidAt(), 3, '24:01 is invalid hour');
test.equal(moment([2000, 1, 29, 23, 60]).invalidAt(), 4, '60 is invalid minute');
test.equal(moment([2000, 1, 29, 23, 59, 60]).invalidAt(), 5, '60 is invalid second');
test.equal(moment([2000, 1, 29, 23, 59, 59, 1000]).invalidAt(), 6, '1000 is invalid millisecond');
Expand Down
12 changes: 10 additions & 2 deletions test/moment/parsing_flags.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ exports.parsingFlags = {
test.equal(flags([2010, 1, 1, 8]).overflow, -1, 'hour valid');
test.equal(flags([2010, 1, 1, 0]).overflow, -1, 'hour 0 valid');
test.equal(flags([2010, 1, 1, -1]).overflow, 3, 'hour -1 invalid');
test.equal(flags([2010, 1, 1, 24]).overflow, 3, 'hour 24 invalid');
test.equal(flags([2010, 1, 1, 25, 01]).overflow, 3, 'hour 25 invalid');
test.equal(flags([2010, 1, 1, 24, 01]).overflow, 3, 'hour 24:01 invalid');

//minutes
test.equal(flags([2010, 1, 1, 8, 15]).overflow, -1, 'minute valid');
Expand All @@ -51,6 +52,12 @@ exports.parsingFlags = {
test.equal(flags([2010, 1, 1, 8, 15, 12, -1]).overflow, 6, 'millisecond -1 invalid');
test.equal(flags([2010, 1, 1, 8, 15, 12, 1000]).overflow, 6, 'millisecond 1000 invalid');

// 24 hrs
test.equal(flags([2010, 1, 1, 24, 0, 0, 0]).overflow, -1, '24:00:00.000 is fine');
test.equal(flags([2010, 1, 1, 24, 1, 0, 0]).overflow, 3, '24:01:00.000 is wrong hour');
test.equal(flags([2010, 1, 1, 24, 0, 1, 0]).overflow, 3, '24:00:01.000 is wrong hour');
test.equal(flags([2010, 1, 1, 24, 0, 0, 1]).overflow, 3, '24:00:00.001 is wrong hour');

test.done();
},

Expand All @@ -77,7 +84,8 @@ exports.parsingFlags = {
//hours
test.equal(flags('08', 'HH').overflow, -1, 'hour valid');
test.equal(flags('00', 'HH').overflow, -1, 'hour 0 valid');
test.equal(flags('24', 'HH').overflow, 3, 'hour 24 invalid');
test.equal(flags('25', 'HH').overflow, 3, 'hour 25 invalid');
test.equal(flags('24:01', 'HH:mm').overflow, 3, 'hour 24:01 invalid');

//minutes
test.equal(flags('08:15', 'HH:mm').overflow, -1, 'minute valid');
Expand Down

0 comments on commit 1214808

Please sign in to comment.