UNPKG

twix

Version:

Twix.js allows you to work with date ranges

1,225 lines (934 loc) 63.2 kB
test = (moment, Twix) -> moment.locale 'en' assertEqual = (a, b) -> throw new Error("Found #{b}, expected #{a}") unless a == b assertTwixEqual = (a, b) -> throw new Error("Found #{b.toString()}, expected #{a.toString()}") unless a.equals b assertMomentEqual = (a, b) -> throw new Error("Found #{b.format()}, expected #{a.format()}") unless a.valueOf() == b.valueOf() assertArrayEqual = (a, b) -> throw new Error("Found #{b}, expected #{a}") unless a.length is b.length and a.every (elem, i) -> elem is b[i] thisYear = (partial, time) -> fullDate = "#{moment().year()}-#{partial}" fullDate += "T#{time}" if time moment fullDate nextYear = (partial, time) -> thisYear(partial, time).add(1, 'year') yesterday = -> moment().subtract(1, 'day').startOf 'day' tomorrow = -> moment().add(1, 'day').startOf 'day' thatDay = (start, end) -> if start moment("1982-05-25T#{start}").twix "1982-05-25T#{end}" else moment('1982-05-25').twix '1982-05-25', true describe 'plugin', -> describe 'static constructor', -> it 'is the same as instantiating via the contructor', -> assertEqual 'function', typeof moment.twix assertTwixEqual new Twix('1982-05-25', '1983-05-25', true), moment.twix('1982-05-25', '1983-05-25', true) it 'uses the parse format for both dates', -> assertTwixEqual new Twix(moment('2012-05-25'), moment('2013-05-25'), false), moment.twix('05/25/2012', '05/25/2013', 'MM/DD/YYYY') describe 'create from a member', -> it 'is a function', -> assertEqual 'function', typeof(moment().twix) it 'is the same as instantiating via the contructor', -> assertTwixEqual new Twix('1982-05-25', '1983-05-25', false), moment('1982-05-25').twix('1983-05-25') it 'accepts an allDay argument', -> t = moment('1982-05-25').twix('1983-05-25', true) assertEqual t.allDay, true it 'uses the parse format', -> assertTwixEqual new Twix(moment('2012-05-25'), moment('2013-05-25'), false), moment('2012-05-25').twix('05/25/2013', 'MM/DD/YYYY') it 'uses a parseStrict object argument', -> t = moment('1981-05-25').twix('A05/25/1982', 'MM/DD/YYYY', parseStrict: true) assertEqual t.end().isValid(), false t = moment('1981-05-25').twix('05/25/1982', 'MM/DD/YYYY', parseStrict: true) assertEqual t.end().isValid(), true it 'uses an allDay option argument', -> t = moment('1981-05-25').twix('05/25/1982', 'MM/DD/YYYY', allDay: true) assertEqual t.allDay, true t = moment('1981-05-25').twix('1982-05-25', allDay: true) assertEqual t.allDay, true describe 'moment.forDuration()', -> it 'constructs a twix', -> from = thisYear('05-25') to = thisYear('05-26') duration = moment.duration(to.diff from) twix = from.forDuration duration assertTwixEqual new Twix(from, to), twix it 'constructs an all-day twix', -> from = thisYear('05-25') to = thisYear('05-26') duration = moment.duration(to.diff from) twix = from.forDuration duration, true assertTwixEqual new Twix(from, to, true), twix describe 'duration.afterMoment()', -> it 'contructs a twix', -> d = moment.duration(2, 'days') twix = d.afterMoment thisYear('05-25') assertTwixEqual new Twix(thisYear('05-25'), thisYear('05-27')), twix it 'can use text', -> d = moment.duration(2, 'days') twix = d.afterMoment '1982-05-25' assertTwixEqual new Twix('1982-05-25', '1982-05-27'), twix it 'contructs an all-day twix', -> d = moment.duration(2, 'days') twix = d.afterMoment thisYear('05-25'), true assertTwixEqual new Twix(thisYear('05-25'), thisYear('05-27'), true), twix describe 'duration.beforeMoment()', -> it 'contructs a twix', -> d = moment.duration(2, 'days') twix = d.beforeMoment thisYear('05-25') assertTwixEqual new Twix(thisYear('05-23'), thisYear('05-25')), twix it 'can use text', -> d = moment.duration(2, 'days') twix = d.beforeMoment '1982-05-25' assertTwixEqual new Twix('1982-05-23', '1982-05-25'), twix it 'contructs an all-day twix', -> d = moment.duration(2, 'days') twix = d.beforeMoment thisYear('05-25'), true assertTwixEqual new Twix(thisYear('05-23'), thisYear('05-25'), true), twix describe 'start()', -> it 'returns the start of the range', -> assertMomentEqual moment('1982-05-25'), moment('1982-05-25').twix('1983-10-14').start() it 'returns the start of the start day for all day ranges', -> assertMomentEqual moment('1982-05-25'), moment('1982-05-25T04:45:45').twix('1983-10-14', true).start() it 'returns start time for for non-all-day ranges', -> assertMomentEqual moment('1982-05-25T04:45:45'), moment('1982-05-25T04:45:45').twix('1983-10-14T01:01:01').start() describe 'end()', -> it 'returns the end of the range', -> assertMomentEqual moment('1983-10-14'), moment('1982-05-25').twix('1983-10-14').end() it 'returns the start of the end day for all day ranges', -> assertMomentEqual moment('1983-10-14'), moment('1982-05-25').twix('1983-10-14T09:30:23', true).end() it 'returns end time for for non-all-day ranges', -> assertMomentEqual moment('1983-10-14T01:01:01'), moment('1982-05-25T04:45:45').twix('1983-10-14T01:01:01').end() describe 'isSame()', -> describe 'year', -> it "returns true if they're the same year", -> assertEqual true, moment('1982-05-25').twix('1982-10-14').isSame 'year' it "returns false if they're different years", -> assertEqual false, moment('1982-05-25').twix('1983-10-14').isSame 'year' describe 'day', -> it "returns true if they're the same day", -> assertEqual true, moment('1982-05-25T05:30').twix('1982-05-25T19:30').isSame 'day' it "returns false if they're different days day", -> assertEqual false, moment('1982-05-25T05:30').twix('1982-05-26T19:30').isSame 'day' it "returns true they're in different UTC days but the same local days", -> assertEqual true, moment('1982-05-25T05:30').twix('1982-05-25T23:30').isSame 'day' describe 'length()', -> describe 'no arguments', -> it 'returns milliseconds', -> mom = moment() assertEqual 60 * 1000, mom.twix(mom.clone().add(1, 'minute')).length() describe 'floating point', -> it 'returns a decimal', -> range = moment('1982-05-25T00:00').twix('1982-05-25T06:30') assertEqual 6.5, range.length('hours', true) describe 'days', -> it 'returns 1 for yesterday - today', -> assertEqual 1, yesterday().twix(moment()).length('days') it 'returns 1 for a one-day all-day range', -> assertEqual 1, moment().twix(moment(), true).length('days') it 'returns 2 for a two-day all-day range', -> assertEqual 2, yesterday().twix(moment(), true).length('days') describe 'other', -> it 'returns the right number for a years', -> assertEqual 16, moment('1996-02-17').twix('2012-08-14').length('years') it 'returns the right number for a months', -> assertEqual 197, moment('1996-02-17').twix('2012-08-14').length('months') describe 'count()', -> describe 'days', -> it 'returns 1 inside a day', -> start = thisYear '05-25', '03:00' end = thisYear '05-25', '14:00' range = moment(start).twix end assertEqual 1, range.count('days') it 'returns 2 if the range crosses midnight', -> start = thisYear '05-25', '16:00' end = thisYear '05-26', '03:00' range = moment(start).twix end assertEqual 2, range.count('days') it 'works fine for all-day ranges', -> start = thisYear '05-25' end = thisYear '05-26' range = moment(start).twix end, true assertEqual 2, range.count('days') describe 'years', -> it 'returns 1 inside a year', -> start = thisYear '05-25' end = thisYear '05-26' assertEqual 1, moment(start).twix(end).count('year') it 'returns 2 if the range crosses Jan 1', -> start = thisYear '05-25' end = nextYear '05-26' assertEqual 2, moment(start).twix(end).count('year') describe 'countInner()', -> describe 'days', -> it 'defaults to milliseconds', -> start = thisYear '05-25', '13:00' end = thisYear '05-25', '13:01' range = moment(start).twix end assertEqual 60000, range.countInner() it 'returns 0 inside a day', -> start = thisYear '05-25', '03:00' end = thisYear '05-25', '14:00' range = moment(start).twix end assertEqual 0, range.countInner('days') it 'returns 0 if the range crosses midnight but is still < 24 hours', -> start = thisYear '05-25', '16:00' end = thisYear '05-26', '03:00' range = moment(start).twix end assertEqual 0, range.countInner('days') it "returns 0 if the range is > 24 hours but still doesn't cover a full day", -> start = thisYear '05-25', '16:00' end = thisYear '05-26', '17:00' range = moment(start).twix end assertEqual 0, range.countInner('days') it 'returns 1 if the range includes one full day', -> start = thisYear '05-24', '16:00' end = thisYear '05-26', '17:00' range = moment(start).twix end assertEqual 1, range.countInner('days') it 'returns 1 if the range includes one full day barely', -> start = thisYear '05-24' end = thisYear '05-25' range = moment(start).twix end assertEqual 1, range.countInner('days') it 'returns 2 if the range includes two full days', -> start = thisYear '05-23', '16:00' end = thisYear '05-26', '17:00' range = moment(start).twix end assertEqual 2, range.countInner('days') it 'returns 1 for a one-day all-day range', -> start = thisYear '05-25' end = thisYear '05-25' range = moment(start).twix end, true assertEqual 1, range.countInner('days') it 'returns 2 for a two-day all-day range', -> start = thisYear '05-25' end = thisYear '05-26' range = moment(start).twix end, true assertEqual 2, range.countInner('days') it "doesn't muck with the twix object", -> start = thisYear '05-25' end = thisYear '05-26' range = moment(start).twix end range.countInner('years') assertMomentEqual thisYear('05-25'), range.start() assertMomentEqual thisYear('05-26'), range.end() describe 'iterate()', -> describe 'duration', -> assertSameMinute = (first, second) -> assertEqual true, first.isSame(second, 'minute') it 'provides 4 periods of 20 minutes (as duration) if the range is 1 hour', -> start = thisYear '05-25', '03:00' end = thisYear '05-25', '04:00' duration = moment.duration 20, 'minutes' iter = start.twix(end).iterate(duration) results = while iter.hasNext() iter.next() assertSameMinute start.clone().add(20, 'minutes'), results[1] assertEqual(4, results.length) it 'provides 5 periods of 2 hours, 30 minutes and 20 seconds if the range is 10 hours and 2 minutes', -> start = thisYear '05-25', '03:00' end = thisYear '05-25', '13:01:20' duration = moment.duration hours: 2, minutes: 30, seconds: 20 iter = start.twix(end).iterate(duration) results = while iter.hasNext() iter.next() assertSameMinute start.clone().add(30, 'minutes').add(2, 'hours').add(20, 'seconds'), results[1] assertEqual(5, results.length) describe 'minutes', -> assertSameMinute = (first, second) -> assertEqual true, first.isSame(second, 'minute') it 'provides 4 periods of 20 minutes if the range is 1 hour', -> start = thisYear '05-25', '03:00' end = thisYear '05-25', '04:00' iter = start.twix(end).iterate(20, 'minutes', 0) results = while iter.hasNext() iter.next() assertSameMinute start.clone().add(20, 'minutes'), results[1] assertEqual(4, results.length) describe 'days', -> assertSameDay = (first, second) -> assertEqual true, first.isSame(second, 'day') it 'provides 1 day if the range includes 1 day', -> start = thisYear '05-25', '03:00' end = thisYear '05-25', '14:00' iter = start.twix(end).iterate('days') assertSameDay thisYear('05-25'), iter.next() assertEqual null, iter.next() it 'provides 2 days if the range crosses midnight', -> start = thisYear '05-25', '16:00' end = thisYear '05-26', '03:00' iter = start.twix(end).iterate('days') assertSameDay start, iter.next() assertSameDay end, iter.next() assertEqual null, iter.next() it 'provides 366 days if the range is a year', -> start = moment('2014-05-25T16:00') end = moment('2014-05-25T03:00').add 1, 'year' iter = start.twix(end).iterate 'days' results = while iter.hasNext() iter.next() assertEqual(366, results.length) it 'provides 1 day for an all-day range', -> start = thisYear '05-25' end = thisYear '05-25' iter = start.twix(end, true).iterate 'days' assertSameDay thisYear('05-25'), iter.next() assertEqual null, iter.next() it "doesn't generate extra days when there's a min time", -> start = thisYear '05-25', '16:00' end = thisYear '05-26', '03:00' iter = start.twix(end).iterate 'days', 4 assertSameDay thisYear('05-25'), iter.next() assertEqual null, iter.next() it "provides 1 day for all-day ranges when there's a min time", -> start = thisYear '05-25' end = thisYear '05-25' iter = start.twix(end, true).iterate 'days', 4 assertEqual true, iter.hasNext() assertSameDay start, iter.next() assertEqual false, iter.hasNext() assertEqual null, iter.next() describe 'months', -> assertSameDay = (first, second) -> assertEqual true, first.isSame(second, 'day') it 'provides 3 months for an all-day range with three months in it', -> start = moment('2014-10-01') end = moment('2014-12-01') dateRange = start.twix(end, true) iter = dateRange.iterate('M') assertEqual true, iter.hasNext() assertSameDay start, iter.next() assertEqual true, iter.hasNext() assertSameDay moment('2014-11-01'), iter.next() assertEqual true, iter.hasNext() assertSameDay end, iter.next() describe 'years', -> assertSameYear = (first, second) -> assertEqual true, first.isSame(second, 'year') it 'provides 1 year if the range happens inside a year', -> start = thisYear '05-25' end = thisYear '05-25' iter = start.twix(end).iterate('years') assertSameYear start, iter.next() assertEqual null, iter.next() it 'provides 2 years if the range crosses Jan 1', -> start = thisYear '05-25' end = nextYear '05-26' iter = start.twix(end).iterate('years') assertSameYear start, iter.next() assertSameYear end, iter.next() assertEqual null, iter.next() #is this good behavior? it "doesn't generate extra years when there's a min time", -> start = thisYear '05-25', '16:00' end = nextYear '01-01', '03:00' range = moment(start).twix end iter = range.iterate 'years', 4 assertSameYear thisYear('05-25'), iter.next() assertEqual null, iter.next() describe 'iterateInner()', -> describe 'duration', -> assertSameMinute = (first, second) -> assertEqual true, first.isSame(second, 'minute') it 'provides 3 periods of 20 minutes (as duration) if the range is 1 hour', -> start = thisYear '05-25', '03:00' end = thisYear '05-25', '04:00' duration = moment.duration 20, 'minutes' iter = start.twix(end).iterateInner(duration) results = while iter.hasNext() iter.next() assertSameMinute start.clone().add(20, 'minutes'), results[1] assertEqual(3, results.length) it 'provides 4 periods of 2 hours, 30 minutes and 20 seconds if the range is 10 hours and 1 minute 20 seconds', -> start = thisYear '05-25', '03:00' end = thisYear '05-25', '13:01:20' duration = moment.duration hours: 2, minutes: 30, seconds: 20 iter = start.twix(end).iterateInner(duration) results = while iter.hasNext() iter.next() assertSameMinute start.clone().add(30, 'minutes').add(2, 'hours').add(20, 'seconds'), results[1] assertEqual(4, results.length) describe 'minutes', -> assertSameMinute = (first, second) -> assertEqual true, first.isSame(second, 'minute') it 'provides 3 periods of 20 minutes if the range is 1 hour', -> start = thisYear '05-25', '03:00' end = thisYear '05-25', '04:00' iter = start.twix(end).iterateInner('minutes', 20) results = while iter.hasNext() iter.next() assertSameMinute start.clone().add(20, 'minutes'), results[1] assertEqual(3, results.length) it 'provides 24 periods of 60 minutes if the range is 24 hours', -> start = thisYear '05-25', '03:00' end = thisYear '05-26', '03:00' iter = start.twix(end).iterateInner('minutes', 60) results = while iter.hasNext() iter.next() assertEqual(24, results.length) describe 'hours', -> assertSameHour = (first, second) -> assertEqual true, first.isSame(second, 'hour') it 'provides 3 periods of 2 hours if the range is 7 hours', -> start = thisYear '05-25', '03:00' end = thisYear '05-25', '10:00' iter = start.twix(end).iterateInner(2, 'hours') results = while iter.hasNext() iter.next() assertSameHour start.clone().add(2, 'hours'), results[1] assertEqual(3, results.length) describe 'days', -> assertSameDay = (first, second) -> assertEqual true, first.isSame(second, 'day') it 'is empty if the range starts and ends the same day', -> start = thisYear '05-25', '03:00' end = thisYear '05-25', '14:00' iter = start.twix(end).iterateInner('days') assertEqual false, iter.hasNext() assertEqual null, iter.next() it "is empty if the range doesn't contain a whole day", -> start = thisYear '05-25', '16:00' end = thisYear '05-26', '17:00' iter = start.twix(end).iterateInner('days') assertEqual false, iter.hasNext() assertEqual null, iter.next() it 'provides 1 day if the range contains 1 full day', -> start = thisYear '05-24', '16:00' end = thisYear '05-26', '03:00' iter = start.twix(end).iterateInner('days') assertSameDay thisYear('05-25'), iter.next() assertEqual null, iter.next() it 'provides 1 day for an all-day range', -> start = thisYear '05-25' end = thisYear '05-25' iter = start.twix(end, true).iterateInner 'days' assertSameDay thisYear('05-25'), iter.next() assertEqual null, iter.next() it 'provides 2 days for a two-day all-day range', -> start = thisYear '05-25' end = thisYear '05-26' iter = start.twix(end, true).iterateInner 'days' assertEqual true, iter.hasNext() assertSameDay thisYear('05-25'), iter.next() assertEqual true, iter.hasNext() assertSameDay thisYear('05-26'), iter.next() assertEqual null, iter.next() describe 'humanizeLength()', -> describe 'all-day ranges', -> it 'formats single-day correctly', -> assertEqual('all day', new Twix('1982-05-25', '1982-05-25', true).humanizeLength()) it 'formats multiday correctly', -> assertEqual('3 days', new Twix('1982-05-25', '1982-05-27', true).humanizeLength()) describe 'non-all-day ranges', -> it 'formats single-day correctly', -> assertEqual('4 hours', thatDay('12:00', '16:00').humanizeLength()) it 'formats multiday correctly', -> assertEqual('2 days', new Twix('1982-05-25', '1982-05-27').humanizeLength()) describe 'isEmpty()', -> it 'returns true for empty ranges', -> assertEqual(true, thatDay('12:00', '12:00').isEmpty()) it 'returns false for non-empty ranges', -> assertEqual(false, thatDay('12:00', '13:00').isEmpty()) it "returns false for 'empty' all-day ranges", -> assertEqual(false, moment('1982-05-25').twix('1982-05-25', true).isEmpty()) describe 'asDuration()', -> it 'returns a duration object', -> duration = yesterday().twix(tomorrow()).asDuration() assertEqual true, moment.isDuration(duration) assertEqual 2, duration.days() describe 'isPast()', -> describe 'all-day ranges', -> it 'returns true for days in the past', -> assertEqual true, yesterday().twix(yesterday(), true).isPast() it 'returns false for today', -> today = moment().startOf 'day' assertEqual false, today.twix(today, true).isPast() it 'returns false for days in the future', -> assertEqual false, tomorrow().twix(tomorrow(), true).isPast() describe 'non-all-day ranges', -> it 'returns true for the past', -> past = moment().subtract 3, 'hours' nearerPast = moment().subtract 2, 'hours' assertEqual true, past.twix(nearerPast).isPast() it 'returns false for the future', -> future = moment().add 2, 'hours' furtherFuture = moment().add 3, 'hours' assertEqual false, future.twix(furtherFuture).isPast() describe 'isFuture()', -> describe 'all-day ranges', -> it 'returns false for days in the past', -> assertEqual false, yesterday().twix(yesterday(), true).isFuture() it 'returns false for today', -> today = moment().startOf 'day' assertEqual false, today.twix(today, true).isFuture() it 'returns true for days in the future', -> assertEqual true, tomorrow().twix(tomorrow(), true).isFuture() describe 'non-all-day ranges', -> it 'returns false for the past', -> past = moment().subtract 3, 'hours' nearerPast = moment().subtract 3, 'hours' assertEqual false, past.twix(nearerPast).isFuture() it 'returns true for the future', -> future = moment().add 2, 'hours' furtherFuture = moment().add 3, 'hours' assertEqual true, future.twix(furtherFuture).isFuture() describe 'isCurrent()', -> describe 'all-day ranges', -> it 'returns false for days in the past', -> assertEqual false, yesterday().twix(yesterday(), true).isCurrent() it 'returns true for today', -> today = moment().startOf 'day' assertEqual true, today.twix(today, true).isCurrent() it 'returns false for days in the future', -> assertEqual false, tomorrow().twix(tomorrow(), true).isCurrent() describe 'non-all-day ranges', -> it 'returns false for the past', -> past = moment().subtract 3, 'hours' nearerPast = moment().subtract 2, 'hours' assertEqual false, past.twix(nearerPast).isCurrent() it 'returns false for the future', -> future = moment().add 2, 'hours' furtherFuture = moment().add 3, 'hours' assertEqual false, future.twix(furtherFuture).isCurrent() describe 'contains()', -> describe 'non-all-day', -> start = thisYear '05-25', '06:00' end = thisYear '05-25', '07:00' range = start.twix end it 'returns true for moments inside the range', -> assertEqual true, range.contains(thisYear '05-25', '06:30') it 'returns true for moments at the beginning of the range', -> assertEqual true, range.contains(start) it 'returns true for moments at the end of the range', -> assertEqual true, range.contains(end) it 'returns false for moments before the range', -> assertEqual false, range.contains(thisYear '05-25', '05:30') it 'returns false for moments after the range', -> assertEqual false, range.contains(thisYear '05-25', '08:30') describe 'all-day', -> start = thisYear '05-25' range = start.twix start, true it 'returns true for moments inside the range', -> assertEqual true, range.contains(thisYear '05-25', '06:30') it 'returns true for moments at the beginning of the range', -> assertEqual true, range.contains(start) it 'returns true for moments at the end of the range', -> assertEqual true, range.contains(start.clone().endOf 'day') it 'returns false for moments before the range', -> assertEqual false, range.contains(thisYear '05-24') it 'returns false for moments after the end of the range', -> assertEqual false, range.contains(thisYear '05-26', '00:00:00') it 'returns false for moments after the range', -> assertEqual false, range.contains(thisYear '05-26', '00:00:01') describe 'overlaps()', -> assertOverlap = (first, second) -> assertOverlapness(true)(first, second) assertNoOverlap = (first, second) -> assertOverlapness(false)(first, second) assertOverlapness = (shouldOverlap) -> (first, second) -> assertEqual shouldOverlap, first.overlaps(second) assertEqual shouldOverlap, second.overlaps(first) someTime = thatDay '05:30', '08:30' someDays = new Twix('1982-05-24', '1982-05-25', true) describe 'non-all-day ranges', -> it 'returns false for a later range', -> assertNoOverlap someTime, thatDay '09:30', '11:30' it 'returns false for an earlier range', -> assertNoOverlap someTime, thatDay '03:30', '04:30' it 'returns true for a partially later range', -> assertOverlap someTime, thatDay '08:00', '11:30' it 'returns true for a partially earlier range', -> assertOverlap someTime, thatDay '04:30', '06:30' it 'returns true for an engulfed range', -> assertOverlap someTime, thatDay '06:30', '07:30' it 'returns true for an engulfing range', -> assertOverlap someTime, thatDay '04:30', '09:30' it 'returns false for a range that starts immediately afterwards', -> assertNoOverlap someTime, thatDay '08:30', '09:30' it 'returns false for a range that ends immediately before', -> assertNoOverlap someTime, thatDay '04:30', '05:30' describe 'one all-day range', -> it 'returns true for a partially later range', -> assertOverlap thatDay(), new Twix('1982-05-25 20:00', '1982-05-26 05:00') it 'returns true for a partially earlier range', -> assertOverlap thatDay(), new Twix('1982-05-24 20:00', '1982-05-25 07:00') it 'returns true for an engulfed range', -> assertOverlap thatDay(), someTime it 'returns true for an engulfing range', -> assertOverlap thatDay(), new Twix('1982-05-24 20:00', '1982-05-26 05:00') it 'returns true for a range which starts on the same day', -> assertOverlap thatDay(), new Twix('1982-05-25', '1982-05-27') it 'returns true for a range which ends on the same day', -> assertOverlap thatDay(), new Twix('1982-05-23', '1982-05-25', true) describe 'two all-day ranges', -> it 'returns false for a later range', -> assertNoOverlap someDays, new Twix('1982-05-26', '1982-05-27', true) it 'returns false for an earlier range', -> assertNoOverlap someDays, new Twix('1982-05-22', '1982-05-23', true) it 'returns true for a partially later range', -> assertOverlap someDays, new Twix('1982-05-24', '1982-05-26', true) it 'returns true for a partially earlier range', -> assertOverlap someDays, new Twix('1982-05-22', '1982-05-24', true) it 'returns true for an engulfed range', -> assertOverlap someDays, new Twix('1982-05-25', '1982-05-25', true) it 'returns true for an engulfing range', -> assertOverlap someDays, new Twix('1982-05-22', '1982-05-28', true) describe 'engulfs()', -> assertEngulfing = (first, second) -> assertEqual true, first.engulfs(second) assertNotEngulfing = (first, second) -> assertEqual false, first.engulfs(second) someTime = thatDay '05:30', '08:30' someDays = new Twix('1982-05-24', '1982-05-25', true) describe 'non-all-day ranges', -> it 'returns false for a later range', -> assertNotEngulfing someTime, thatDay '09:30', '11:30' it 'returns false for an earlier range', -> assertNotEngulfing someTime, thatDay '03:30', '04:30' it 'returns false for a partially later range', -> assertNotEngulfing someTime, thatDay '08:00', '11:30' it 'returns false for a partially earlier range', -> assertNotEngulfing someTime, thatDay '04:30', '06:30' it 'returns true for an engulfed range', -> assertEngulfing someTime, thatDay '06:30', '07:30' it 'returns false for an engulfing range', -> assertNotEngulfing someTime, thatDay '04:30', '09:30' describe 'one all-day range', -> it 'returns true for a partially later range', -> assertNotEngulfing thatDay(), new Twix('1982-05-25 20:00', '1982-05-26 05:00') it 'returns true for a partially earlier range', -> assertNotEngulfing thatDay(), new Twix('1982-05-24', '20:00', '1982-05-25 07:00') it 'returns true for an engulfed range', -> assertEngulfing thatDay(), someTime it 'returns true for an engulfing range', -> assertNotEngulfing thatDay(), new Twix('1982-05-24 20:00', '1982-05-26 05:00') describe 'two all-day ranges', -> it 'returns false for a later range', -> assertNotEngulfing someDays, new Twix('1982-05-26', '1982-05-27', true) it 'returns false for an earlier range', -> assertNotEngulfing someDays, new Twix('1982-05-22', '1982-05-23', true) it 'returns true for a partially later range', -> assertNotEngulfing someDays, new Twix('1982-05-24', '1982-05-26', true) it 'returns true for a partially earlier range', -> assertNotEngulfing someDays, new Twix('1982-05-22', '1982-05-24', true) it 'returns true for an engulfed range', -> assertEngulfing someDays, new Twix('1982-05-25', '1982-05-25', true) it 'returns true for an engulfing range', -> assertNotEngulfing someDays, new Twix('1982-05-22', '1982-05-28', true) describe 'union()', -> someTime = thatDay '05:30', '08:30' someDays = new Twix('1982-05-24', '1982-05-25', true) describe 'non-all-day ranges', -> it 'spans a later time', -> assertTwixEqual thatDay('05:30', '11:30'), someTime.union(thatDay '09:30', '11:30') it 'spans an earlier time', -> assertTwixEqual thatDay('03:30', '08:30'), someTime.union(thatDay '03:30', '04:30') it 'spans a partially later range', -> assertTwixEqual thatDay('05:30', '11:30'), someTime.union(thatDay '08:00', '11:30') it 'spans a partially earlier range', -> assertTwixEqual thatDay('04:30', '08:30'), someTime.union(thatDay '04:30', '06:30') it "isn't affected by engulfed ranges", -> assertTwixEqual someTime, someTime.union(thatDay '06:30', '07:30') it 'becomes an engulfing range', -> assertTwixEqual thatDay('04:30', '09:30'), someTime.union(thatDay '04:30', '09:30') it 'spans adjacent ranges', -> assertTwixEqual thatDay('05:30', '09:30'), someTime.union(thatDay '08:30', '09:30') describe 'one all-day range', -> it 'spans a later time', -> assertTwixEqual new Twix('1982-05-24 00:00', '1982-05-26 07:00'), someDays.union(new Twix('1982-05-24 20:00', '1982-05-26 07:00')) it 'spans an earlier time', -> assertTwixEqual new Twix('1982-05-23 08:00', moment('1982-05-26')), someDays.union(new Twix('1982-05-23 08:00', '1982-05-25 07:00')) #i'm tempted to just say this is wrong...shouldn't it get to stay an all-day range? it "isn't affected by engulfing ranges", -> assertTwixEqual new Twix('1982-05-24 00:00', moment('1982-05-26')), someDays.union(someTime) it 'becomes an engulfing range', -> assertTwixEqual new Twix('1982-05-23 20:00', '1982-05-26 08:30'), someDays.union(new Twix('1982-05-23 20:00', '1982-05-26 08:30')) describe 'two all-day ranges', -> it 'spans a later time', -> assertTwixEqual new Twix('1982-05-24', '1982-05-28', true), someDays.union(new Twix('1982-05-27', '1982-05-28', true)) it 'spans an earlier time', -> assertTwixEqual new Twix('1982-05-21', '1982-05-25', true), someDays.union(new Twix('1982-05-21', '1982-05-22', true)) it 'spans a partially later time', -> assertTwixEqual new Twix('1982-05-24', '1982-05-26', true), someDays.union(new Twix('1982-05-25', '1982-05-26', true)) it 'spans a partially earlier time', -> assertTwixEqual new Twix('1982-05-23', '1982-05-25', true), someDays.union(new Twix('1982-05-23', '1982-05-25', true)) it "isn't affected by engulfing ranges", -> assertTwixEqual someDays, someDays.union(thatDay()) it 'becomes an engulfing range', -> assertTwixEqual someDays, thatDay().union(someDays) describe 'intersection()', -> someTime = thatDay '05:30', '08:30' someDays = new Twix('1982-05-24', '1982-05-25', true) describe 'non-all-day ranges', -> it 'does not intersect with a later time', -> intersection = someTime.intersection(thatDay '09:30', '11:30') assertTwixEqual thatDay('09:30', '08:30'), intersection assertEqual false, intersection.isValid() it 'does not intersect with an earlier time', -> intersection = someTime.intersection(thatDay '03:30', '04:30') assertTwixEqual thatDay('05:30', '04:30'), intersection assertEqual false, intersection.isValid() it 'intersects with a partially later range', -> assertTwixEqual thatDay('08:00', '08:30'), someTime.intersection(thatDay '08:00', '11:30') it 'intersects with a partially earlier range', -> assertTwixEqual thatDay('05:30', '06:30'), someTime.intersection(thatDay '04:30', '06:30') it 'intersects with an engulfed range', -> assertTwixEqual thatDay('06:30', '07:30'), someTime.intersection(thatDay '06:30', '07:30') it 'intersects with an engulfing range', -> assertTwixEqual thatDay('05:30', '08:30'), someTime.intersection(thatDay '04:30', '09:30') it 'does not intersect an adjacent range (later)', -> assertEqual 0, someTime.intersection(thatDay '08:30', '09:30').length() it 'does not intersect an adjacent range (earlier)', -> assertEqual 0, someTime.intersection(thatDay '04:30', '05:30').length() it 'returns self for an identical range', -> assertTwixEqual someTime, someTime.intersection(someTime) it 'returns self for a time that starts at the same time but ends later', -> assertTwixEqual someTime, someTime.intersection(thatDay('05:30', '09:30')) describe 'one all-day range', -> it 'intersects with a later time', -> assertTwixEqual new Twix('1982-05-24 20:00', '1982-05-26'), someDays.intersection(new Twix('1982-05-24 20:00', '1982-05-26 07:00')) it 'intersects with an earlier time', -> assertTwixEqual new Twix('1982-05-24 00:00', '1982-05-25 07:00'), someDays.intersection(new Twix('1982-05-23 08:00', '1982-05-25 07:00')) it 'intersects with an engulfed range', -> assertTwixEqual new Twix('1982-05-25 05:30', '1982-05-25 08:30'), someDays.intersection(someTime) it 'intersects with an engulfing range', -> assertTwixEqual new Twix('1982-05-24 00:00', '1982-05-26'), someDays.intersection(new Twix('1982-05-23 20:00', '1982-05-26 08:30')) describe 'two all-day ranges', -> it 'does not intersect with a later time', -> intersection = someDays.intersection(new Twix('1982-05-27', '1982-05-28', true)) assertTwixEqual new Twix('1982-05-27', '1982-05-25', true), intersection assertEqual false, intersection.isValid() it 'does not intersect with an earlier time', -> intersection = someDays.intersection(new Twix('1982-05-21', '1982-05-22', true)) assertTwixEqual new Twix('1982-05-24', '1982-05-22', true), intersection assertEqual false, intersection.isValid() it 'intersects with a partially later time', -> assertTwixEqual new Twix('1982-05-25', '1982-05-25', true), someDays.intersection(new Twix('1982-05-25', '1982-05-26', true)) it 'intersects with a partially earlier time', -> assertTwixEqual new Twix('1982-05-24', '1982-05-25', true), someDays.intersection(new Twix('1982-05-23', '1982-05-25', true)) it 'intersects with an engulfed range', -> assertTwixEqual thatDay(), someDays.intersection(thatDay()) it 'intersects with an engulfing range', -> assertTwixEqual thatDay(), thatDay().intersection(someDays) describe 'xor()', -> someTime = thatDay '05:30', '08:30' someDays = new Twix('1982-05-24', '1982-05-25', true) describe 'non-all-day ranges', -> it 'returns non-overlapping ranges as-is (later)', -> later = thatDay '09:30', '11:30' orred = someTime.xor later assertEqual 2, orred.length assertTwixEqual someTime, orred[0] assertTwixEqual later, orred[1] it 'returns non-overlapping ranges as-is (earlier)', -> later = thatDay '09:30', '11:30' orred = later.xor someTime assertEqual 2, orred.length assertTwixEqual someTime, orred[0] assertTwixEqual later, orred[1] it 'returns the outside parts of a partially overlapping range (later)', -> orred = someTime.xor(thatDay '08:00', '11:30') assertEqual 2, orred.length assertTwixEqual thatDay('05:30', '08:00'), orred[0] assertTwixEqual thatDay('08:30', '11:30'), orred[1] it 'returns the outside parts of a partially overlapping range (earlier)', -> orred = thatDay('08:00', '11:30').xor(someTime) assertEqual 2, orred.length assertTwixEqual thatDay('05:30', '08:00'), orred[0] assertTwixEqual thatDay('08:30', '11:30'), orred[1] it 'returns the outside parts when engulfing a range', -> orred = someTime.xor(thatDay '06:30', '07:30') assertEqual 2, orred.length assertTwixEqual thatDay('05:30', '06:30'), orred[0] assertTwixEqual thatDay('07:30', '08:30'), orred[1] it 'returns the outside parts of an engulfing range', -> orred = thatDay('06:30', '07:30').xor(someTime) assertEqual 2, orred.length assertTwixEqual thatDay('05:30', '06:30'), orred[0] assertTwixEqual thatDay('07:30', '08:30'), orred[1] it 'returns one contiguous range for two adajacent ranges', -> orred = thatDay('08:30', '10:30').xor(someTime) assertEqual 1, orred.length assertTwixEqual thatDay('05:30', '10:30'), orred[0] describe 'one all-day range', -> it 'uses the full day in the xor', -> xored = someDays.xor(new Twix('1982-05-25T16:00', '1982-05-26T02:00')) assertEqual 2, xored.length assertTwixEqual new Twix('1982-05-24T00:00', '1982-05-25T16:00'), xored[0] assertTwixEqual new Twix('1982-05-26T00:00', '1982-05-26T02:00'), xored[1] describe 'two all-day ranges', -> it 'returns an all-day range', -> xored = someDays.xor(new Twix('1982-05-25', '1982-05-27', true)) assertEqual 2, xored.length assertTwixEqual new Twix('1982-05-24', '1982-05-24', true), xored[0] assertTwixEqual new Twix('1982-05-26', '1982-05-27', true), xored[1] describe 'multiple ranges', -> it 'returns the xor of three ranges', -> tween = thatDay '10:00', '13:00' early = thatDay '08:00', '11:00' later = thatDay '12:00', '14:00' xored = tween.xor(early, later) assertEqual 3, xored.length assertTwixEqual thatDay('08:00', '10:00'), xored[0] assertTwixEqual thatDay('11:00', '12:00'), xored[1] assertTwixEqual thatDay('13:00', '14:00'), xored[2] describe 'difference()', -> someTime = thatDay '05:30', '08:30' someDays = new Twix('1982-05-24', '1982-05-25', true) describe 'non-all-day ranges', -> it 'returns self for non-overlapping ranges (later)', -> later = thatDay '09:30', '11:30' exed = someTime.difference later assertEqual 1, exed.length assertTwixEqual someTime, exed[0] it 'returns self for non-overlapping ranges (earlier)', -> later = thatDay '09:30', '11:30' exed = later.difference someTime assertEqual 1, exed.length assertTwixEqual later, exed[0] it 'returns the non-overlapping part of a partially overlapping range (later)', -> exed = someTime.difference(thatDay '08:00', '11:30') assertEqual 1, exed.length assertTwixEqual thatDay('05:30', '08:00'), exed[0] it 'returns the outside parts of a partially overlapping range (earlier)', -> exed = thatDay('08:00', '11:30').difference(someTime) assertEqual 1, exed.length assertTwixEqual thatDay('08:30', '11:30'), exed[0] it 'returns the outside parts when engulfing a range', -> exed = someTime.difference(thatDay '06:30', '07:30') assertEqual 2, exed.length assertTwixEqual thatDay('05:30', '06:30'), exed[0] assertTwixEqual thatDay('07:30', '08:30'), exed[1] it 'returns empty for an engulfing range', -> exed = thatDay('06:30', '07:30').difference(someTime) assertEqual 0, exed.length it 'returns self for an adjacent range', -> exed = someTime.difference(thatDay('08:30', '10:30')) assertEqual 1, exed.length assertTwixEqual someTime, exed[0] it 'returns self for an adjacent range (inverse)', -> other = thatDay('08:30', '10:30') exed = other.difference(someTime) assertEqual 1, exed.length assertTwixEqual other, exed[0] describe 'one all-day range', -> it 'uses the full day', -> exed = someDays.difference(new Twix('1982-05-25T16:00', '1982-05-26T02:00')) assertEqual 1, exed.length assertTwixEqual new Twix('1982-05-24T00:00', '1982-05-25T16:00'), exed[0] describe 'two all-day ranges', -> it 'returns an all-day range', -> exed = someDays.difference(new Twix('1982-05-25', '1982-05-27', true)) assertEqual 1, exed.length assertTwixEqual new Twix('1982-05-24', '1982-05-24', true), exed[0] it "doesn't mutate its inputs", -> first = new Twix('1982-05-24', '1982-05-25', true) second = new Twix('1982-05-25', '1982-05-27', true) firstStart = first.start() firstEnd = first._displayEnd.clone() secondStart = second.start() secondEnd = second._displayEnd.clone() first.difference(second) assertMomentEqual firstStart, first.start() assertMomentEqual firstEnd, first._displayEnd assertMomentEqual secondStart, second.start() assertMomentEqual secondEnd, second._displayEnd describe 'multiple ranges', -> it 'returns the difference of three ranges', -> tween = thatDay '10:00', '13:00' early = thatDay '08:00', '11:00' later = thatDay '12:00', '14:00' exed = tween.difference(early, later) assertEqual 1, exed.length assertTwixEqual thatDay('11:00', '12:00'), exed[0] describe 'split()', -> describe 'using a duration', -> assertHours = (splits) -> assertEqual 3, splits.length assertTwixEqual thatDay('05:01', '06:01'), splits[0] assertTwixEqual thatDay('06:01', '07:01'), splits[1] assertTwixEqual thatDay('07:01', '07:30'), splits[2] it 'accepts a duration directly', -> splits = thatDay('05:01', '07:30').split(moment.duration(1, 'hour')) assertHours splits it 'accepts number, unit as args', -> splits = thatDay('05:01', '07:30').split(1, 'h') assertHours splits it 'accepts an object', -> splits = thatDay('05:01', '07:30').split(moment.duration({'h': 1})) assertHours splits it 'returns the original if the duration is empty', -> range = thatDay '05:01', '07:30' splits = range.split(moment.duration({'h': 0})) assertEqual 1, splits.length assertTwixEqual range, splits[0] it 'splits up all-day ranges into hours across the whole day', -> splits = moment('1982-05-25').twix('1982-05-26', allDay: true).split(moment.duration(1, 'hour')) assertEqual 48, splits.length assertTwixEqual thatDay('00:00', '01:00'), splits[0] assertTwixEqual moment.twix('1982-05-26T23:00', '1982-05-27T00:00'), splits[47] describe 'using times', -> it 'accepts a single time', -> splits = thatDay('05:00', '06:00').split('1982-05-25T05:30') assertEqual 2, splits.length assertTwixEqual thatDay('05:00', '05:30'), splits[0] assertTwixEqual thatDay('05:30', '06:00'), splits[1] it 'accepts multiple times', -> splits = thatDay('05:00', '06:00').split('1982-05-25T05:30', '1982-05-25T05:45') assertEqual 3, splits.length assertTwixEqual thatDay('05:00', '05:30'), splits[0] assertTwixEqual thatDay('05:30', '05:45'), splits[1] assertTwixEqual thatDay('05:45', '06:00'), splits[2] it 'accepts a list of times', -> splits = thatDay('05:00', '06:00').split(['1982-05-25T05:30', '1982-05-25T05:45']) assertEqual 3, splits.length assertTwixEqual thatDay('05:00', '05:30'), splits[0] assertTwixEqual thatDay('05:30', '05:45'), splits[1] assertTwixEqual thatDay('05:45', '06:00'), splits[2] it 'returns the original if there are no args', -> range = thatDay '05:01', '07:30' splits = range.split() assertEqual 1, splits.length assertTwixEqual range, splits[0] it 'returns the original if the arg is an empty list', -> range = thatDay '05:01', '07:30' splits = range.split([]) assertEqual 1, splits.length assertTwixEqual range, splits[0] it 'excludes bad times', -> splits = thatDay('05:00', '06:00').split('1982-05-23', '1982-05-25T05:30', moment.invalid()) assertEqual 2, splits.length assertTwixEqual thatDay('05:00', '05:30'), splits[0] assertTwixEqual thatDay('05:30', '06:00'), splits[1] it "returns the original if they're all bad times", -> range = thatDay '05:01', '07:30' splits = range.split(moment.invalid()) assertEqual 1, splits.length assertTwixEqual range, splits[0] it 'splits at all provided times', -> splits = moment.twix('2016-11-16T16:00:00', '2016-11-17T00:00:00').split('2016-11-16T18:00:00', '2016-11-17T00:00:00') assertEqual 2, splits.length assertTwixEqual moment.twix('2016-11-16T16:00:00', '2016-11-16T18:00:00'), splits[0] assertTwixEqual moment.twix('2016-11-16T18:00:00', '2016-11-17T00:00:00'), splits[1] describe 'divide()', -> it 'should split a 4 hour period into 4 contiguous 1-hour parts', -> range = thatDay '05:00', '09:00' splits = range.divide(4) assertEqual 4, splits.length assertTwixEqual thatDay('06:00', '07:00'), splits[1] it 'should split a 1m30s into 3 30-second parts', -> range = thatDay '05:00:00', '05:01:30' splits = range.divide(3) assertEqual 3, splits.length assertTwixEqual thatDay('05:01:00', '05:01:30'), splits[2] it 'always gives you the right number of parts', -> range = thatDay '05:00:00', '05:01:30' splits = range.divide(17) assertEqual 17, splits.length describe 'isValid()', -> it 'should return false when the start time is invalid', -> assertEqual false, new Twix('1980-13-45', '1982-05-26').isValid() it 'should return false when the end time is invalid', -> assertEqual false, new Twix('1982-05-25', '1985-13-45').isValid() it 'should validate an interval with an earlier start', -> assertEqual true, new Twix('1982-05-24', '1982-05-26').isValid() assertEqual true, new Twix('1982-05-24', '1982-05-26', true).isValid() assertEqual true, new Twix('1982-05-24 20:00', '1982-05-26 07:00').isValid() assertEqual true, new Twix('1982-05-24 20:00', '1982-05-26 07:00', true).isValid() it 'should validate an interval without range', -> assertEqual true, new Twix('1982-05-24', '1982-05-24').isValid() assertEqual true, new Twix('1982-05-24', '1982-05-24', true).isValid() assertEqual true, new Twix('1982-05-24 20:00', '1982-05-24 20:00').isValid() assertEqual true, new Twix('1982-05-24 20:00', '1982-05-24 20:00', true).isValid() it 'should not validate an interval with a later start', -> assertEqual false, new Twix('1982-05-26', '1982-05-24').isValid() assertEqual false, new Twix('1982-05-26', '1982-05-24', true).isValid() assertEqual false, new Twix('1982-05-26 07:00', '1982-05-24 20:00').isVal