diff --git a/examples/basic/index.js b/examples/basic/index.js index 2af9d3c..642d68e 100644 --- a/examples/basic/index.js +++ b/examples/basic/index.js @@ -61,6 +61,8 @@ window.Perf = require('react-addons-perf'); -
{convertDate(value, 'YYYY/MM/DD')}
+
{convertDate(value, showFormat)}
- - - + {dateFormat.map((format, index) => ( + + ))}
typeof val === 'undefined'; +/** + * 根据格式获取时间滑动的类别 + * @param {String} format 格式 + * @return {string} 类别名称 + */ +const getTimeType = format => { + const typeMap = { + Y: 'Year', + M: 'Month', + D: 'Date', + h: 'Hour', + m: 'Minute', + s: 'Second', + }; + + for (const key in typeMap) { + if (typeMap.hasOwnProperty(key)) { + if (~format.indexOf(key)) { + return typeMap[key] + } + } + } + + throw new Error('时间格式必须包含 Y, M, D, h, m 或 s字母'); +} + + /** * Class Date组件类 * @extends Component @@ -31,6 +58,8 @@ class DatePickerItem extends Component { marginTop: (this.currentIndex - MIDDLE_INDEX) * DATE_HEIGHT, }; + // 设置时间选择器单元的类别 + this.typeName = getTimeType(props.format); this.renderDatepickerItem = this.renderDatepickerItem.bind(this); this.handleContentTouch = this.handleContentTouch.bind(this); this.handleContentMouseDown = this.handleContentMouseDown.bind(this); @@ -84,7 +113,7 @@ class DatePickerItem extends Component { } _iniDates(date) { - const { typeName } = this.props; + const typeName = this.typeName; const dates = Array(...Array(DATE_LENGTH)) .map((value, index) => TimeUtil[`next${typeName}`](date, index - MIDDLE_INDEX)); @@ -92,7 +121,7 @@ class DatePickerItem extends Component { } _updateDates(direction) { - const { typeName } = this.props; + const typeName = this.typeName; const { dates } = this.state; if (direction === 1) { this.currentIndex ++; @@ -305,7 +334,6 @@ DatePickerItem.propTypes = { min: PropTypes.object, max: PropTypes.object, format: PropTypes.string, - typeName: PropTypes.string, onSelect: PropTypes.func, }; diff --git a/lib/index.js b/lib/index.js index 91afd9e..0c1bc5f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -56,6 +56,7 @@ ModalDatePicker.defaultProps = { min: new Date(1970, 0, 1), max: new Date(2050, 0, 1), dateFormat: ['YYYY', 'M', 'D'], + showFormat: 'YYYY/MM/DD', confirmText: '完成', cancelText: '取消', onSelect: () => {}, diff --git a/lib/time.js b/lib/time.js index a50480d..2254cb8 100644 --- a/lib/time.js +++ b/lib/time.js @@ -2,7 +2,6 @@ * @module time工具 */ - function throwIfInvalidDate(date) { if (Object.prototype.toString.call(date, null) !== '[object Date]') { throw new Error('参数类型不对'); @@ -28,15 +27,16 @@ export function convertDate(date, format) { 's+': date.getSeconds(), }; if (/(Y+)/.test(format)) { - str = str.replace(RegExp.$1, - (date.getFullYear().toString()).substr(4 - RegExp.$1.length)); + str = str.replace(RegExp.$1, date.getFullYear().toString().substr(4 - RegExp.$1.length)); } - for (const k in o) { // eslint-disable-line + for (const k in o) { + // eslint-disable-line if (new RegExp(`(${k})`).test(format)) { - str = str.replace(RegExp.$1, - (RegExp.$1.length === 1) ? - o[k] : (`00${o[k]}`.substr((o[k].toString()).length))); + str = str.replace( + RegExp.$1, + RegExp.$1.length === 1 ? o[k] : `00${o[k]}`.substr(o[k].toString().length), + ); } } @@ -50,7 +50,14 @@ export function convertDate(date, format) { */ export function nextYear(now, index = 0) { throwIfInvalidDate(now); - const date = new Date(now.getFullYear() + index, now.getMonth(), now.getDate()); + const date = new Date( + now.getFullYear() + index, + now.getMonth(), + now.getDate(), + now.getHours(), + now.getMinutes(), + now.getSeconds(), + ); return date; } @@ -59,12 +66,37 @@ export function nextMonth(now, index = 0) { const year = now.getFullYear(); const month = now.getMonth() + index; const dayOfMonth = Math.min(now.getDate(), daysInMonth(year, month)); - const date = new Date(year, month, dayOfMonth); + const date = new Date( + year, + month, + dayOfMonth, + now.getHours(), + now.getMinutes(), + now.getSeconds(), + ); return date; } export function nextDate(now, index = 0) { throwIfInvalidDate(now); - const date = new Date(now.getFullYear(), now.getMonth(), now.getDate() + index); + const date = new Date(now.getTime() + index * 24 * 60 * 60 * 1000); + return date; +} + +export function nextHour(now, index = 0) { + throwIfInvalidDate(now); + const date = new Date(now.getTime() + index * 60 * 60 * 1000); + return date; +} + +export function nextMinute(now, index = 0) { + throwIfInvalidDate(now); + const date = new Date(now.getTime() + index * 60 * 1000); + return date; +} + +export function nextSecond(now, index = 0) { + throwIfInvalidDate(now); + const date = new Date(now.getTime() + index * 1000); return date; } diff --git a/test/functional/DatePickerItem_spec.js b/test/functional/DatePickerItem_spec.js index 24101ae..1eda189 100644 --- a/test/functional/DatePickerItem_spec.js +++ b/test/functional/DatePickerItem_spec.js @@ -11,7 +11,6 @@ const DEFAULT_PROPS = { value: new Date(2010, 3, 7), min: new Date(2010, 2, 6), max: new Date(2010, 4, 8), - format: 'M', onSelect: () => {}, } @@ -20,7 +19,7 @@ describe('DatePickerItem.js', () => { it('should call componentWillMount and initialize dates of state', () => { const spyFunction = sinon.spy(DatePickerItem.prototype, 'componentWillMount'); const datePicker = mount( - + ); const dates = datePicker.state('dates'); sinon.assert.calledOnce(spyFunction); @@ -35,7 +34,7 @@ describe('DatePickerItem.js', () => { it('componentWillReceiveProps', () => { const spyFunction = sinon.spy(DatePickerItem.prototype, 'componentWillReceiveProps'); const datePicker = mount( - + ); datePicker.setProps({ date: new Date(2010, 3, 10) }); const dates = datePicker.state('dates'); @@ -51,7 +50,7 @@ describe('DatePickerItem.js', () => { it('shouldComponentUpdate', () => { const spyFunction = sinon.spy(DatePickerItem.prototype, 'shouldComponentUpdate'); const datePicker = mount( - + ); datePicker.setProps({ value: new Date(2010, 3, 10) }); @@ -65,7 +64,7 @@ describe('DatePickerItem.js', () => { it('should call handleContent three times after touching', () => { const spyFunction = sinon.spy(DatePickerItem.prototype, 'handleContentTouch'); const datePicker = mount( - + ); const touchstartEvent = { @@ -93,7 +92,7 @@ describe('DatePickerItem.js', () => { it('should analyzing the right direction', () => { const spyFunction = sinon.spy(DatePickerItem.prototype, '_moveToNext'); const datePicker = mount( - + ); const touchstartEvent = { targetTouches: [{ pageY: 0 }], @@ -110,7 +109,7 @@ describe('DatePickerItem.js', () => { expect(spyFunction.getCall(0).args[0]).to.equal(-1); const datePicker2 = mount( - + ); const touchstartEvent2 = { targetTouches: [{ pageY: 0 }], @@ -132,7 +131,7 @@ describe('DatePickerItem.js', () => { it('should update dates of state, When the sliding more than 20', () => { const spyFunction = sinon.spy(DatePickerItem.prototype, '_updateDates'); const datePicker = mount( - + ); const touchstartEvent = { targetTouches: [{ pageY: 0 }], @@ -161,7 +160,7 @@ describe('DatePickerItem.js', () => { const spyFunction = sinon.spy(DatePickerItem.prototype, '_moveTo'); const datePicker = mount( - + ); const touchstartEvent = { diff --git a/test/functional/DatePicker_spec.js b/test/functional/DatePicker_spec.js index 4c82ea8..dd1cfd1 100644 --- a/test/functional/DatePicker_spec.js +++ b/test/functional/DatePicker_spec.js @@ -265,3 +265,55 @@ describe('DatePicker.js', () => { }) }); }); + +describe('渲染正确的DatepicketItem子组件', () => { + let props; + let mountedDatepicker; + + const datePicker = () => { + if (!mountedDatepicker) { + mountedDatepicker = mount( + + ); + } + + return mountedDatepicker; + } + + beforeEach(() => { + props = { + value: new Date(2016, 8, 16), + }; + mountedDatepicker = undefined; + }); + + it('当dateFormat等于[YYYY, MM, DD]', () => { + props.dateFormat = ['YYYY', 'MM', 'DD']; + const datePickerItems = datePicker().find(DatePickerItem); + expect(datePickerItems.length).to.equals(3); + expect(datePickerItems.at(0).props().format).to.equals('YYYY'); + expect(datePickerItems.at(1).props().format).to.equals('MM'); + expect(datePickerItems.at(2).props().format).to.equals('DD'); + }); + + it('当dateFormat等于[YYYY, MM, DD, hh, mm, ss]', () => { + props.dateFormat = ['YYYY', 'MM', 'DD', 'hh', 'mm', 'ss']; + const datePickerItems = datePicker().find(DatePickerItem); + expect(datePickerItems.length).to.equals(6); + expect(datePickerItems.at(0).props().format).to.equals('YYYY'); + expect(datePickerItems.at(1).props().format).to.equals('MM'); + expect(datePickerItems.at(2).props().format).to.equals('DD'); + expect(datePickerItems.at(3).props().format).to.equals('hh'); + expect(datePickerItems.at(4).props().format).to.equals('mm'); + expect(datePickerItems.at(5).props().format).to.equals('ss'); + }); + + it('当dateFormat等于[hh, mm, ss]', () => { + props.dateFormat = ['hh', 'mm', 'ss']; + const datePickerItems = datePicker().find(DatePickerItem); + expect(datePickerItems.length).to.equals(3); + expect(datePickerItems.at(0).props().format).to.equals('hh'); + expect(datePickerItems.at(1).props().format).to.equals('mm'); + expect(datePickerItems.at(2).props().format).to.equals('ss'); + }); +}); diff --git a/test/functional/time_spec.js b/test/functional/time_spec.js index daa50a6..e92b3bf 100644 --- a/test/functional/time_spec.js +++ b/test/functional/time_spec.js @@ -1,6 +1,6 @@ import { expect } from 'chai'; -import { nextYear, nextMonth, nextDate, getTime } from '../../lib/time.js'; +import { nextYear, nextMonth, nextDate,nextHour, nextMinute, getTime } from '../../lib/time.js'; describe('time.js', () => { @@ -39,7 +39,7 @@ describe('time.js', () => { it("should return last month, when 'index = -1'", function() { const date = new Date(2010, 1, 28); - const expectDate = new Date(2010, 0, 28); + const expectDate = new Date(2009, 12, 28); expect(nextMonth(date, -1).getTime()).to.equal(expectDate.getTime()); }); @@ -82,4 +82,56 @@ describe('time.js', () => { expect(nextDate(date, 1).getTime()).to.equal(expectDate.getTime()); }); }); + + describe('nextHour', () => { + it('should return correct parameter', function () { + expect(() => nextHour(undefined, -1)).to.throw('参数类型不对'); + expect(() => nextHour(4345345)).to.throw('参数类型不对'); + }); + + it("should return last hour, when 'index = -1'", function() { + const date = new Date(2010, 2, 6, 11, 30, 1); + const expectDate = new Date(2010, 2, 6, 10, 30, 1); + expect(nextHour(date, -1).getTime()).to.equal(expectDate.getTime()); + }); + + it("should return this hour, when 'index = 0'", function() { + const date = new Date(2010, 2, 6, 11, 30, 1); + const expectDate = new Date(2010, 2, 6, 11, 30, 1); + expect(nextHour(date, 0).getTime()).to.equal(expectDate.getTime()); + expect(nextHour(date).getTime()).to.equal(expectDate.getTime()); + }); + + it("should return next hour, when 'index = 1'", function() { + const date = new Date(2010, 2, 6, 11, 30, 1); + const expectDate = new Date(2010, 2, 6, 12, 30, 1); + expect(nextHour(date, 1).getTime()).to.equal(expectDate.getTime()); + }); + }); + + describe('nextMinute', () => { + it('should return correct parameter', function () { + expect(() => nextMinute(undefined, -1)).to.throw('参数类型不对'); + expect(() => nextMinute(4345345)).to.throw('参数类型不对'); + }); + + it("should return last minute, when 'index = -1'", function() { + const date = new Date(2010, 2, 7, 11, 30, 1); + const expectDate = new Date(2010, 2, 7, 11, 29, 1); + expect(nextMinute(date, -1).getTime()).to.equal(expectDate.getTime()); + }); + + it("should return this minute, when 'index = 0'", function() { + const date = new Date(2010, 2, 7, 11, 30, 1); + const expectDate = new Date(2010, 2, 7, 11, 30, 1); + expect(nextMinute(date, 0).getTime()).to.equal(expectDate.getTime()); + expect(nextMinute(date).getTime()).to.equal(expectDate.getTime()); + }); + + it("should return next date, when 'index = 1'", function() { + const date = new Date(2010, 2, 7, 11, 30, 1); + const expectDate = new Date(2010, 2, 7, 11, 31, 1); + expect(nextMinute(date, 1).getTime()).to.equal(expectDate.getTime()); + }); + }); })