├── examples ├── popup.html ├── simple.html ├── time.html ├── utils.tsx ├── react-native │ ├── picker.tsx │ └── popup.tsx ├── time.tsx ├── popup.tsx └── simple.tsx ├── src ├── index.tsx ├── PopupStyles.tsx ├── locale │ ├── en_US.tsx │ ├── id_ID.tsx │ ├── ru_RU.tsx │ ├── sv_SE.tsx │ ├── zh_CN.tsx │ ├── pt_BR.tsx │ └── fa_IR.tsx ├── IDatePickerProps.tsx ├── Popup.tsx └── DatePicker.tsx ├── typings ├── index.d.ts └── custom.d.ts ├── index.android.js ├── tsconfig.json ├── .editorconfig ├── assets └── index.less ├── index.ios.js ├── .gitignore ├── .travis.yml ├── tests ├── DatePicker.spec.js └── __snapshots__ │ └── DatePicker.spec.js.snap ├── HISTORY.md ├── package.json └── README.md /examples/popup.html: -------------------------------------------------------------------------------- 1 | placeholder -------------------------------------------------------------------------------- /examples/simple.html: -------------------------------------------------------------------------------- 1 | placeholder -------------------------------------------------------------------------------- /examples/time.html: -------------------------------------------------------------------------------- 1 | placeholder -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './DatePicker'; 2 | -------------------------------------------------------------------------------- /typings/index.d.ts: -------------------------------------------------------------------------------- 1 | /// -------------------------------------------------------------------------------- /index.android.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./index.ios'); 2 | -------------------------------------------------------------------------------- /src/PopupStyles.tsx: -------------------------------------------------------------------------------- 1 | export { default } from 'rmc-picker/lib/PopupStyles'; 2 | -------------------------------------------------------------------------------- /typings/custom.d.ts: -------------------------------------------------------------------------------- 1 | // declare module "rc-dialog" { 2 | // var Ret: any; 3 | // export default Ret; 4 | // } 5 | 6 | -------------------------------------------------------------------------------- /src/locale/en_US.tsx: -------------------------------------------------------------------------------- 1 | export default { 2 | year: '', 3 | month: '', 4 | day: '', 5 | hour: '', 6 | minute: '', 7 | am: 'AM', 8 | pm: 'PM', 9 | }; 10 | -------------------------------------------------------------------------------- /src/locale/id_ID.tsx: -------------------------------------------------------------------------------- 1 | export default { 2 | year: '', 3 | month: '', 4 | day: '', 5 | hour: '', 6 | minute: '', 7 | am: 'AM', 8 | pm: 'PM', 9 | }; 10 | -------------------------------------------------------------------------------- /src/locale/ru_RU.tsx: -------------------------------------------------------------------------------- 1 | export default { 2 | year: '', 3 | month: '', 4 | day: '', 5 | hour: '', 6 | minute: '', 7 | am: 'AM', 8 | pm: 'PM', 9 | }; 10 | -------------------------------------------------------------------------------- /src/locale/sv_SE.tsx: -------------------------------------------------------------------------------- 1 | export default { 2 | year: '', 3 | month: '', 4 | day: '', 5 | hour: '', 6 | minute: '', 7 | am: 'AM', 8 | pm: 'PM', 9 | }; 10 | -------------------------------------------------------------------------------- /src/locale/zh_CN.tsx: -------------------------------------------------------------------------------- 1 | export default { 2 | year: '年', 3 | month: '月', 4 | day: '日', 5 | hour: '时', 6 | minute: '分', 7 | am: '上午', 8 | pm: '下午', 9 | }; 10 | -------------------------------------------------------------------------------- /src/locale/pt_BR.tsx: -------------------------------------------------------------------------------- 1 | export default { 2 | year: 'Ano', 3 | month: 'Mês', 4 | day: 'Dia', 5 | hour: 'Hora', 6 | minute: 'Minuto', 7 | am: 'AM', 8 | pm: 'PM', 9 | }; 10 | -------------------------------------------------------------------------------- /src/locale/fa_IR.tsx: -------------------------------------------------------------------------------- 1 | export default { 2 | year: 'سال', 3 | month: 'ماه', 4 | day: 'روز', 5 | hour: 'ساعت', 6 | minute: 'دقیقه', 7 | am: 'صبح', 8 | pm: 'بعد از ظهر', 9 | }; 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strictNullChecks": true, 4 | "moduleResolution": "node", 5 | "jsx": "react", 6 | "allowSyntheticDefaultImports":true, 7 | "target": "es6" 8 | } 9 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | # Unix-style newlines with a newline ending every file 5 | [*.{js,css}] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | indent_style = space 9 | indent_size = 2 10 | -------------------------------------------------------------------------------- /assets/index.less: -------------------------------------------------------------------------------- 1 | @MDatePickerPrefixCls: rmc-date-picker; 2 | .@{MDatePickerPrefixCls} { 3 | display: flex; 4 | align-items: center; 5 | padding: 10px 0; 6 | 7 | &-item { 8 | flex: 1; 9 | text-align: center; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /index.ios.js: -------------------------------------------------------------------------------- 1 | // only for react-native examples 2 | 3 | import getList from 'react-native-index-page'; 4 | 5 | getList({ 6 | demos: [ 7 | require('./_ts2js/examples/react-native/picker'), 8 | require('./_ts2js/examples/react-native/popup'), 9 | ], 10 | title: require('./package.json').name, 11 | }); 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.log 3 | .idea/ 4 | .ipr 5 | .iws 6 | *~ 7 | ~* 8 | *.diff 9 | *.patch 10 | *.bak 11 | .DS_Store 12 | Thumbs.db 13 | .project 14 | .*proj 15 | .svn/ 16 | *.swp 17 | *.swo 18 | *.pyc 19 | *.pyo 20 | .build 21 | node_modules 22 | .cache 23 | dist 24 | *.css 25 | build 26 | lib 27 | /coverage 28 | yarn.lock 29 | es/ 30 | ios/ 31 | android/ 32 | _ts2js/ 33 | package-lock.json 34 | .history/ 35 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | sudo: false 4 | 5 | notifications: 6 | email: 7 | - yiminghe@gmail.com 8 | 9 | node_js: 10 | - 6.9.1 11 | 12 | before_install: 13 | - | 14 | if ! git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE '(\.md$)|(^(docs|examples))/' 15 | then 16 | echo "Only docs were updated, stopping build process." 17 | exit 18 | fi 19 | npm install npm@3.x -g 20 | phantomjs --version 21 | script: 22 | - | 23 | if [ "$TEST_TYPE" = test ]; then 24 | npm test && bash <(curl -s https://codecov.io/bash) -cF rn 25 | else 26 | npm run $TEST_TYPE 27 | fi 28 | env: 29 | matrix: 30 | - TEST_TYPE=lint 31 | - TEST_TYPE=test -------------------------------------------------------------------------------- /examples/utils.tsx: -------------------------------------------------------------------------------- 1 | 2 | export const minDate = new Date(2015, 8, 15, 10, 30, 0); 3 | export const maxDate = new Date(2018, 1, 1, 23, 49, 59); 4 | export let now = new Date(); 5 | 6 | export const cn = typeof location !== 'undefined' ? location.search.indexOf('cn') !== -1 : false; 7 | if (cn) { 8 | now = new Date(); 9 | } else { 10 | now = new Date(now.getTime() + now.getTimezoneOffset() * 60000); 11 | } 12 | 13 | export function format(date) { 14 | let mday = date.getDate(); 15 | let month = date.getMonth() + 1; 16 | month = month < 10 ? `0${month}` : month; 17 | mday = mday < 10 ? `0${mday}` : mday; 18 | return `${date.getFullYear()}-${month}-${mday} ${date.getHours()}:${date.getMinutes()}`; 19 | } 20 | -------------------------------------------------------------------------------- /tests/DatePicker.spec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render/*, mount*/ } from 'enzyme'; 3 | import { renderToJson } from 'enzyme-to-json'; 4 | import DatePicker from '../src'; 5 | import { cn, format, minDate, maxDate } from '../examples/utils'; 6 | 7 | describe('DatePicker', () => { 8 | it('renders correctly', () => { 9 | const wrapper = render( 10 | 18 | ); 19 | expect(renderToJson(wrapper)).toMatchSnapshot(); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /src/IDatePickerProps.tsx: -------------------------------------------------------------------------------- 1 | interface IDatePickerProps { 2 | date?: any; 3 | defaultDate?: any; 4 | minDate?: any; 5 | maxDate?: any; 6 | minHour?: number; 7 | maxHour?: number; 8 | minMinute?: number; 9 | maxMinute?: number; 10 | mode?: string; 11 | disabled?: boolean; 12 | locale?: any; 13 | minuteStep?: number; 14 | formatMonth?: (month: number, date?: any) => any; 15 | formatDay?: (day: number, date?: any) => any; 16 | onDateChange?: (date: any) => void; 17 | onValueChange?: (vals: any, index: number) => void; 18 | itemStyle?: any; 19 | style?: any; 20 | /** web only */ 21 | prefixCls?: string; 22 | /** web only */ 23 | onScrollChange?: (date: any, vals: any, index: number) => void; 24 | rootNativeProps?: {}; 25 | pickerPrefixCls?: string; 26 | className?: string; 27 | use12Hours?: boolean; 28 | } 29 | 30 | export default IDatePickerProps; 31 | -------------------------------------------------------------------------------- /src/Popup.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import IDatePickerProps from './IDatePickerProps'; 3 | import PopupPicker from 'rmc-picker/lib/Popup'; 4 | import { IPopupPickerProps } from 'rmc-picker/lib/PopupPickerTypes'; 5 | 6 | export interface IPopupDatePickerProps extends IPopupPickerProps { 7 | datePicker: React.ReactElement; 8 | onChange?: (date?: any) => void; 9 | date?: any; 10 | } 11 | 12 | class PopupDatePicker extends React.Component { 13 | static defaultProps = { 14 | pickerValueProp: 'date', 15 | pickerValueChangeProp: 'onDateChange', 16 | }; 17 | 18 | onOk = (v) => { 19 | const { onChange, onOk } = this.props; 20 | if (onChange) { 21 | onChange(v); 22 | } 23 | if (onOk) { 24 | onOk(v); 25 | } 26 | } 27 | 28 | render() { 29 | return (); 35 | } 36 | } 37 | 38 | export default PopupDatePicker; 39 | -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | # History 2 | 3 | --- 4 | 5 | ## 6.0.10 6 | 7 | - fix calendar recursive when use12Hours 8 | 9 | ## 6.0.9 10 | 11 | - add ru_RU and sv_SE locale 12 | 13 | ## 6.0.7 14 | 15 | - add ru_RU and sv_SE locale 16 | 17 | ## 6.x 18 | 19 | - Remove moment.js and change date type from Moment to Date. 20 | - Add `use12Hours`/`onValueChange` props. 21 | 22 | ## 5.2.0 / 2016-12-17 23 | 24 | - support formatMonth/formatDay 25 | 26 | ## 5.1.0 / 2016-12-01 27 | 28 | - support minuteStep 29 | 30 | ## 5.0.0 / 2016-09-07 31 | 32 | - extract datePicker element from popup 33 | 34 | ## 4.0.0 / 2016-07-28 35 | 36 | - use moment.js 37 | 38 | ## 3.0.0 / 2016-6-15 39 | 40 | - support react-native and typescript 41 | 42 | ## 2.0.0 / 2016-03-21 43 | 44 | - use rc-dialog 45 | 46 | ## 1.7.0 / 2016-01-13 47 | 48 | - change onDateChange -> onPickerChange, onOk -> onChange in Popup 49 | 50 | ## 1.5.0 / 2016-01-11 51 | 52 | - add rmc-date-picker/lib/Popup 53 | 54 | ## 1.3.0 / 2016-01-05 55 | 56 | - support defaultDate prop 57 | 58 | ## 1.0.0 / 2015-12-23 59 | 60 | - init 61 | -------------------------------------------------------------------------------- /examples/react-native/picker.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-console */ 2 | 3 | import DatePicker from '../../src/DatePicker'; 4 | import { View, Text } from 'react-native'; 5 | import * as React from 'react'; 6 | import zhCn from '../../src/locale/zh_CN'; 7 | import enUs from '../../src/locale/en_US'; 8 | import { cn, format, minDate, maxDate, now } from '../utils'; 9 | 10 | export class PickerDemo extends React.Component { 11 | static defaultProps = { 12 | mode: 'datetime', 13 | locale: cn ? zhCn : enUs, 14 | }; 15 | 16 | constructor(props) { 17 | super(props); 18 | this.state = { 19 | date: null, 20 | }; 21 | } 22 | 23 | onDateChange = (date) => { 24 | this.setState({ 25 | date, 26 | }); 27 | } 28 | 29 | render() { 30 | const props = this.props; 31 | const { date } = this.state; 32 | 33 | return ( 34 | date picker 35 | 36 | 37 | {date && format(date) || format(now)} 38 | 39 | 47 | 48 | ); 49 | } 50 | } 51 | 52 | export const Demo = PickerDemo; 53 | export const title = 'picker'; 54 | -------------------------------------------------------------------------------- /examples/time.tsx: -------------------------------------------------------------------------------- 1 | /* eslint no-console:0 */ 2 | 3 | import 'rmc-picker/assets/index.css'; 4 | import 'rmc-date-picker/assets/index.less'; 5 | import DatePicker from '../src/index'; 6 | import * as React from 'react'; 7 | import * as ReactDOM from 'react-dom'; 8 | import zhCn from '../src/locale/zh_CN'; 9 | import enUs from '../src/locale/en_US'; 10 | import { cn, format, minDate, maxDate, now } from './utils'; 11 | 12 | now.setHours(15); 13 | now.setMinutes(39); 14 | 15 | class Demo extends React.Component { 16 | static defaultProps = { 17 | mode: 'time', 18 | locale: cn ? zhCn : enUs, 19 | }; 20 | 21 | constructor(props) { 22 | super(props); 23 | this.state = { 24 | date: null, 25 | }; 26 | } 27 | 28 | onDateChange = (date) => { 29 | this.setState({ 30 | date, 31 | }); 32 | } 33 | 34 | render() { 35 | const props = this.props; 36 | const {date} = this.state; 37 | 38 | return (
39 |

date picker

40 |
41 | {date && format(date) || format(now)} 42 | 51 |
52 |
); 53 | } 54 | } 55 | 56 | ReactDOM.render(, document.getElementById('__react-content')); 57 | -------------------------------------------------------------------------------- /examples/popup.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-console */ 2 | 3 | import 'rmc-picker/assets/index.css'; 4 | import 'rmc-date-picker/assets/index.less'; 5 | import 'rmc-picker/assets/popup.css'; 6 | import * as React from 'react'; 7 | import * as ReactDOM from 'react-dom'; 8 | import PopPicker from '../src/Popup'; 9 | import DatePicker from '../src/DatePicker'; 10 | import zhCn from '../src/locale/zh_CN'; 11 | import enUs from '../src/locale/en_US'; 12 | import { cn, format, minDate, maxDate, now } from './utils'; 13 | 14 | class Demo extends React.Component { 15 | static defaultProps = { 16 | mode: 'datetime', 17 | locale: cn ? zhCn : enUs, 18 | }; 19 | 20 | constructor(props) { 21 | super(props); 22 | this.state = { 23 | date: null, 24 | }; 25 | } 26 | 27 | onChange = (date) => { 28 | console.log('onChange', format(date)); 29 | this.setState({ 30 | date, 31 | }); 32 | } 33 | 34 | onDismiss = () => { 35 | console.log('onDismiss'); 36 | } 37 | 38 | show = () => { 39 | console.log('my click'); 40 | } 41 | 42 | render() { 43 | const props = this.props; 44 | const { date } = this.state; 45 | const datePicker = ( 46 | 54 | ); 55 | return (
56 |

popup date picker

57 |
58 | 67 | 68 | 69 |
70 |
); 71 | } 72 | } 73 | 74 | ReactDOM.render(, document.getElementById('__react-content')); 75 | -------------------------------------------------------------------------------- /examples/simple.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-console */ 2 | 3 | import 'rmc-picker/assets/index.css'; 4 | import 'rmc-date-picker/assets/index.less'; 5 | import DatePicker from '../src/index'; 6 | import * as React from 'react'; 7 | import * as ReactDOM from 'react-dom'; 8 | import zhCn from '../src/locale/zh_CN'; 9 | import enUs from '../src/locale/en_US'; 10 | import { cn, format, minDate, maxDate, now } from './utils'; 11 | 12 | class Demo extends React.Component { 13 | static defaultProps = { 14 | locale: cn ? zhCn : enUs, 15 | }; 16 | 17 | constructor(props) { 18 | super(props); 19 | this.state = { 20 | date: new Date(2017, 2, 31, 15, 1, 1), 21 | mode: 'datetime', 22 | }; 23 | } 24 | 25 | onDateChange = (date) => { 26 | console.log('onChange', format(date)); 27 | this.setState({ 28 | date, 29 | }); 30 | } 31 | 32 | onValueChange = (values, index) => { 33 | console.log('onValueChange', values, index); 34 | } 35 | 36 | onScrollChange = (values, index) => { 37 | console.log('onScrollChange', values, index); 38 | } 39 | 40 | changeMode = (e) => { 41 | this.setState({ 42 | mode: e.target.value, 43 | }); 44 | } 45 | 46 | render() { 47 | const props = this.props; 48 | const { date, mode } = this.state; 49 | 50 | return (
51 |

date picker

52 | 53 | 60 | 61 |
62 | {date && format(date) || format(now)} 63 | 75 |
76 |
); 77 | } 78 | } 79 | 80 | ReactDOM.render(, document.getElementById('__react-content')); 81 | -------------------------------------------------------------------------------- /examples/react-native/popup.tsx: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-console */ 2 | 3 | import { View, Text, StyleSheet, TouchableHighlight} from 'react-native'; 4 | import * as React from 'react'; 5 | import PopPicker from '../../src/Popup'; 6 | import DatePicker from '../../src/DatePicker'; 7 | import PopupStyles from '../../src/PopupStyles'; 8 | import zhCn from '../../src/locale/zh_CN'; 9 | import enUs from '../../src/locale/en_US'; 10 | import { cn, format, minDate, maxDate, now } from '../utils'; 11 | 12 | const styles = StyleSheet.create({ 13 | button: { 14 | borderWidth: 1, 15 | borderColor: 'red', 16 | padding: 5, 17 | width: 300, 18 | }, 19 | }); 20 | 21 | export class PopupDemo extends React.Component { 22 | static defaultProps = { 23 | mode: 'datetime', 24 | locale: cn ? zhCn : enUs, 25 | }; 26 | 27 | constructor(props) { 28 | super(props); 29 | this.state = { 30 | date: null, 31 | }; 32 | } 33 | 34 | onChange = (date) => { 35 | console.log('onChange', format(date)); 36 | this.setState({ 37 | date, 38 | }); 39 | } 40 | 41 | onDismiss = () => { 42 | console.log('onDismiss'); 43 | } 44 | 45 | show = () => { 46 | console.log('my click'); 47 | } 48 | 49 | render() { 50 | const props = this.props; 51 | const {date} = this.state; 52 | const datePicker = ( 53 | 60 | ); 61 | return ( 62 | 63 | popup date picker 64 | 65 | 66 | 74 | 75 | {date && format(date) || 'open'} 76 | 77 | 78 | 79 | ); 80 | } 81 | } 82 | 83 | export const Demo = PopupDemo; 84 | export const title = 'popup'; 85 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rmc-date-picker", 3 | "version": "6.0.10", 4 | "description": "React Mobile DatePicker Component for web and react-native", 5 | "keywords": [ 6 | "react", 7 | "react-component", 8 | "react-mobile-date-picker", 9 | "date-picker" 10 | ], 11 | "homepage": "https://github.com/react-component/m-date-picker", 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/react-component/m-date-picker.git" 15 | }, 16 | "bugs": { 17 | "url": "https://github.com/react-component/m-date-picker/issues" 18 | }, 19 | "files": [ 20 | "lib", 21 | "es", 22 | "assets/*.css" 23 | ], 24 | "license": "MIT", 25 | "main": "./lib/index", 26 | "module": "./es/index", 27 | "config": { 28 | "port": 8007 29 | }, 30 | "scripts": { 31 | "watch-tsc": "rc-tools run watch-tsc", 32 | "compile": "rc-tools run compile --babel-runtime", 33 | "build": "rc-tools run build", 34 | "gh-pages": "rc-tools run gh-pages", 35 | "start": "rc-tools run server --babel-runtime", 36 | "prepublish": "rc-tools run guard", 37 | "prepare": "rc-tools run guard", 38 | "prepublishOnly": "rc-tools run guard", 39 | "pub": "rc-tools run pub --babel-runtime", 40 | "lint": "rc-tools run lint --no-js-lint", 41 | "test": "jest", 42 | "coverage": "jest --coverage", 43 | "rn-start": "node node_modules/react-native/local-cli/cli.js start", 44 | "rn-init": "rc-tools run react-native-init" 45 | }, 46 | "jest": { 47 | "moduleFileExtensions": [ 48 | "tsx", 49 | "js" 50 | ], 51 | "collectCoverageFrom": [ 52 | "src/**/*" 53 | ], 54 | "transform": { 55 | "\\.tsx?$": "./node_modules/rc-tools/scripts/jestPreprocessor.js", 56 | "\\.jsx?$": "./node_modules/rc-tools/scripts/jestPreprocessor.js" 57 | } 58 | }, 59 | "devDependencies": { 60 | "@types/jest": "^19.2.4", 61 | "@types/react": "^15.5.0", 62 | "@types/react-dom": "^15.5.0", 63 | "@types/react-native": "^0.46.9", 64 | "enzyme": "^2.6.0", 65 | "enzyme-to-json": "^1.4.5", 66 | "fastclick": "^1.0.6", 67 | "jest": "^20.0.0", 68 | "pre-commit": "1.x", 69 | "rc-tools": "6.x", 70 | "react": "^15.5.0", 71 | "react-dom": "^15.5.0", 72 | "react-native": "~0.42.0", 73 | "react-native-index-page": "~0.2.0", 74 | "react-test-renderer": "^15.5.0" 75 | }, 76 | "typings": "./lib/index.d.ts", 77 | "pre-commit": [ 78 | "lint" 79 | ], 80 | "dependencies": { 81 | "babel-runtime": "6.x", 82 | "rmc-picker": "~5.0.0" 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rmc-date-picker 2 | --- 3 | 4 | React Mobile DatePicker Component (web and react-native) 5 | 6 | 7 | [![NPM version][npm-image]][npm-url] 8 | ![react-native](https://img.shields.io/badge/react--native-%3E%3D_0.30.0-green.svg) 9 | ![react](https://img.shields.io/badge/react-%3E%3D_15.2.0-green.svg) 10 | [![build status][travis-image]][travis-url] 11 | [![Codecov](https://img.shields.io/codecov/c/github/react-component/m-date-picker.svg?style=flat-square)](https://codecov.io/gh/react-component/m-date-picker) 12 | [![gemnasium deps][gemnasium-image]][gemnasium-url] 13 | [![node version][node-image]][node-url] 14 | [![npm download][download-image]][download-url] 15 | 16 | [npm-image]: http://img.shields.io/npm/v/rmc-date-picker.svg?style=flat-square 17 | [npm-url]: http://npmjs.org/package/rmc-date-picker 18 | [travis-image]: https://img.shields.io/travis/react-component/m-date-picker.svg?style=flat-square 19 | [travis-url]: https://travis-ci.org/react-component/m-date-picker 20 | [gemnasium-image]: http://img.shields.io/gemnasium/react-component/m-date-picker.svg?style=flat-square 21 | [gemnasium-url]: https://gemnasium.com/react-component/m-date-picker 22 | [node-image]: https://img.shields.io/badge/node.js-%3E=_0.10-green.svg?style=flat-square 23 | [node-url]: http://nodejs.org/download/ 24 | [download-image]: https://img.shields.io/npm/dm/rmc-date-picker.svg?style=flat-square 25 | [download-url]: https://npmjs.org/package/rmc-date-picker 26 | 27 | ## Screenshots 28 | 29 | ### web 30 | 31 | 32 | 33 | ### ios 34 | 35 | 36 | 37 | ### android 38 | 39 | 40 | 41 | ## Usage 42 | 43 | see example 44 | 45 | ## Development 46 | 47 | ``` 48 | npm i 49 | npm start 50 | ``` 51 | 52 | ## Example 53 | 54 | http://localhost:8000/examples/ 55 | 56 | online example: http://react-component.github.io/m-date-picker/ 57 | 58 | ## react-native 59 | 60 | ``` 61 | npm run rn-init 62 | npm run watch-tsc 63 | react-native start 64 | react-native run-ios 65 | ``` 66 | 67 | ## install 68 | 69 | [![rmc-date-picker](https://nodei.co/npm/rmc-date-picker.png)](https://npmjs.org/package/rmc-date-picker) 70 | 71 | 72 | ## API 73 | 74 | ### DatePicker props 75 | 76 | | name | description | type | default | 77 | |----------|----------------|----------|--------------| 78 | |className(web) | additional css class of root dom node | String | '' | 79 | |prefixCls(web) | prefix class | String | 'rmc-date-picker' | 80 | |pickerPrefixCls(web) | picker prefix class | String | 'rmc-picker' | 81 | |defaultDate | default selected date. | Date | | 82 | |date | The currently selected date. | Date | | 83 | |mode | The date picker mode. | String | 'date' enum('date', 'time', 'datetime', 'year', 'month') | 84 | |minDate | min date | Date | `new Date(2000, 1, 1, 0, 0, 0)` | 85 | |maxDate | max date | Date | `new Date(2030, 1, 1, 23, 59, 59)` | 86 | |minHour | min Hour `[0, 23]`| Number | `0` | 87 | |maxHour | max Hour `[0, 23]`| Number | `23` | 88 | |minMinute | max Minute `[0, 59]`| Number | `0` | 89 | |maxMinute | max Minute `[0, 59]`| Number| `59` | 90 | |locale | the locale of area | Object | import from 'rmc-date-picker/lib/locale/en_US' | 91 | |use12Hours | 12 hours display mode | Boolean | false | 92 | |minuteStep | The amount of time, in minutes, between each minute item. | Number | 1 | 93 | |onDateChange | Date change handler. | Function(date: Date) | '' | 94 | |onValueChange | fire when picker change | (vals: any, index: number) => void | | 95 | |formatMonth | Customize display value of months | (month:number, current:Date) => React.Node | | 96 | |formatDay | Customize display value of days | (day:number, current:Date) => React.Node | | 97 | 98 | ### rmc-date-picker/lib/Popup props 99 | 100 | | name | description | type | default | 101 | |----------|----------------|----------|--------------| 102 | |className(web) | additional css class of modal node | String | '' | 103 | |style(web) | additional modal style | object | {} | 104 | |popupTransitionName(web) | | String | | 105 | |maskTransitionName(web) | | String | | 106 | |prefixCls(web) | popup's prefix class | String | 'rmc-picker-popup' | 107 | |styles(react-native) | PopupPicker's styles | StyleSheet.create | | 108 | |datePicker | DatePicker element | React DatePicker element | | 109 | |date | The currently selected date. | Date | | 110 | |visible | whether pop picker is visible | Boolean | false | 111 | |onChange | exec on ok | Function(date: Date) | | 112 | |onVisibleChange | called when pop picker visible change | Function | | 113 | |onDismiss | exec on dismiss | function | | 114 | |okText | ok button text | string/React.ReactElement | 'Ok' | 115 | |dismissText | dismiss button text | string/React.ReactElement | 'Dismiss' | 116 | |title | Popup title | string/React.ReactElement | '' | 117 | 118 | 119 | ## Test Case 120 | 121 | ``` 122 | npm test 123 | npm run chrome-test 124 | ``` 125 | 126 | ## Coverage 127 | 128 | ``` 129 | npm run coverage 130 | ``` 131 | 132 | open coverage/ dir 133 | 134 | ## License 135 | 136 | rmc-date-picker is released under the MIT license. 137 | -------------------------------------------------------------------------------- /tests/__snapshots__/DatePicker.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`DatePicker renders correctly 1`] = ` 4 |
9 |
13 |
16 |
19 |
22 |
25 | 2015 26 |
27 |
30 | 2016 31 |
32 |
35 | 2017 36 |
37 |
40 | 2018 41 |
42 |
43 |
44 |
48 |
51 |
54 |
57 |
60 | 1 61 |
62 |
65 | 2 66 |
67 |
70 | 3 71 |
72 |
75 | 4 76 |
77 |
80 | 5 81 |
82 |
85 | 6 86 |
87 |
90 | 7 91 |
92 |
95 | 8 96 |
97 |
100 | 9 101 |
102 |
105 | 10 106 |
107 |
110 | 11 111 |
112 |
115 | 12 116 |
117 |
118 |
119 |
123 |
126 |
129 |
132 |
135 | 1 136 |
137 |
140 | 2 141 |
142 |
145 | 3 146 |
147 |
150 | 4 151 |
152 |
155 | 5 156 |
157 |
160 | 6 161 |
162 |
165 | 7 166 |
167 |
170 | 8 171 |
172 |
175 | 9 176 |
177 |
180 | 10 181 |
182 |
185 | 11 186 |
187 |
190 | 12 191 |
192 |
195 | 13 196 |
197 |
200 | 14 201 |
202 |
205 | 15 206 |
207 |
210 | 16 211 |
212 |
215 | 17 216 |
217 |
220 | 18 221 |
222 |
225 | 19 226 |
227 |
230 | 20 231 |
232 |
235 | 21 236 |
237 |
240 | 22 241 |
242 |
245 | 23 246 |
247 |
250 | 24 251 |
252 |
255 | 25 256 |
257 |
260 | 26 261 |
262 |
265 | 27 266 |
267 |
270 | 28 271 |
272 |
275 | 29 276 |
277 |
280 | 30 281 |
282 |
283 |
284 |
288 |
291 |
294 |
297 |
300 | 12 301 |
302 |
305 | 01 306 |
307 |
310 | 02 311 |
312 |
315 | 03 316 |
317 |
320 | 04 321 |
322 |
325 | 05 326 |
327 |
330 | 06 331 |
332 |
335 | 07 336 |
337 |
340 | 08 341 |
342 |
345 | 09 346 |
347 |
350 | 10 351 |
352 |
355 | 11 356 |
357 |
358 |
359 |
363 |
366 |
369 |
372 |
375 | 00 376 |
377 |
380 | 01 381 |
382 |
385 | 02 386 |
387 |
390 | 03 391 |
392 |
395 | 04 396 |
397 |
400 | 05 401 |
402 |
405 | 06 406 |
407 |
410 | 07 411 |
412 |
415 | 08 416 |
417 |
420 | 09 421 |
422 |
425 | 10 426 |
427 |
430 | 11 431 |
432 |
435 | 12 436 |
437 |
440 | 13 441 |
442 |
445 | 14 446 |
447 |
450 | 15 451 |
452 |
455 | 16 456 |
457 |
460 | 17 461 |
462 |
465 | 18 466 |
467 |
470 | 19 471 |
472 |
475 | 20 476 |
477 |
480 | 21 481 |
482 |
485 | 22 486 |
487 |
490 | 23 491 |
492 |
495 | 24 496 |
497 |
500 | 25 501 |
502 |
505 | 26 506 |
507 |
510 | 27 511 |
512 |
515 | 28 516 |
517 |
520 | 29 521 |
522 |
525 | 30 526 |
527 |
530 | 31 531 |
532 |
535 | 32 536 |
537 |
540 | 33 541 |
542 |
545 | 34 546 |
547 |
550 | 35 551 |
552 |
555 | 36 556 |
557 |
560 | 37 561 |
562 |
565 | 38 566 |
567 |
570 | 39 571 |
572 |
575 | 40 576 |
577 |
580 | 41 581 |
582 |
585 | 42 586 |
587 |
590 | 43 591 |
592 |
595 | 44 596 |
597 |
600 | 45 601 |
602 |
605 | 46 606 |
607 |
610 | 47 611 |
612 |
615 | 48 616 |
617 |
620 | 49 621 |
622 |
625 | 50 626 |
627 |
630 | 51 631 |
632 |
635 | 52 636 |
637 |
640 | 53 641 |
642 |
645 | 54 646 |
647 |
650 | 55 651 |
652 |
655 | 56 656 |
657 |
660 | 57 661 |
662 |
665 | 58 666 |
667 |
670 | 59 671 |
672 |
673 |
674 |
678 |
681 |
684 |
687 |
690 | AM 691 |
692 |
695 | PM 696 |
697 |
698 |
699 |
700 | `; 701 | -------------------------------------------------------------------------------- /src/DatePicker.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import MultiPicker from 'rmc-picker/lib/MultiPicker'; 3 | import Picker from 'rmc-picker/lib/Picker'; 4 | import IDatePickerProps from './IDatePickerProps'; 5 | import defaultLocale from './locale/en_US'; 6 | 7 | function getDaysInMonth(date) { 8 | return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); 9 | } 10 | 11 | function pad(n) { 12 | return n < 10 ? `0${n}` : n + ''; 13 | } 14 | 15 | function cloneDate(date) { 16 | return new Date(+date); 17 | } 18 | 19 | function setMonth(date, month) { 20 | date.setDate(Math.min(date.getDate(), getDaysInMonth(new Date(date.getFullYear(), month)))); 21 | date.setMonth(month); 22 | } 23 | 24 | const DATETIME = 'datetime'; 25 | const DATE = 'date'; 26 | const TIME = 'time'; 27 | const MONTH = 'month'; 28 | const YEAR = 'year'; 29 | const ONE_DAY = 24 * 60 * 60 * 1000; 30 | 31 | class DatePicker extends React.Component { 32 | static defaultProps = { 33 | prefixCls: 'rmc-date-picker', 34 | pickerPrefixCls: 'rmc-picker', 35 | locale: defaultLocale, 36 | mode: DATE, 37 | disabled: false, 38 | minuteStep: 1, 39 | onDateChange() { 40 | }, 41 | use12Hours: false, 42 | }; 43 | 44 | state = { 45 | date: this.props.date || this.props.defaultDate, 46 | }; 47 | 48 | defaultMinDate: any; 49 | defaultMaxDate: any; 50 | 51 | componentWillReceiveProps(nextProps) { 52 | if ('date' in nextProps) { 53 | this.setState({ 54 | date: nextProps.date || nextProps.defaultDate, 55 | }); 56 | } 57 | } 58 | 59 | getNewDate = (values, index) => { 60 | const value = parseInt(values[index], 10); 61 | const props = this.props; 62 | const { mode } = props; 63 | let newValue = cloneDate(this.getDate()); 64 | if (mode === DATETIME || mode === DATE || mode === YEAR || mode === MONTH) { 65 | switch (index) { 66 | case 0: 67 | newValue.setFullYear(value); 68 | break; 69 | case 1: 70 | // Note: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setMonth 71 | // e.g. from 2017-03-31 to 2017-02-28 72 | setMonth(newValue, value); 73 | break; 74 | case 2: 75 | newValue.setDate(value); 76 | break; 77 | case 3: 78 | this.setHours(newValue, value); 79 | break; 80 | case 4: 81 | newValue.setMinutes(value); 82 | break; 83 | case 5: 84 | this.setAmPm(newValue, value); 85 | break; 86 | default: 87 | break; 88 | } 89 | } else if (mode === TIME) { 90 | switch (index) { 91 | case 0: 92 | this.setHours(newValue, value); 93 | break; 94 | case 1: 95 | newValue.setMinutes(value); 96 | break; 97 | case 2: 98 | this.setAmPm(newValue, value); 99 | break; 100 | default: 101 | break; 102 | } 103 | } 104 | return this.clipDate(newValue); 105 | } 106 | 107 | onValueChange = (values, index) => { 108 | const props = this.props; 109 | const newValue = this.getNewDate(values, index); 110 | if (!('date' in props)) { 111 | this.setState({ 112 | date: newValue, 113 | }); 114 | } 115 | if (props.onDateChange) { 116 | props.onDateChange(newValue); 117 | } 118 | if (props.onValueChange) { 119 | props.onValueChange(values, index); 120 | } 121 | } 122 | 123 | onScrollChange = (values, index) => { 124 | const props = this.props; 125 | if (props.onScrollChange) { 126 | const newValue = this.getNewDate(values, index); 127 | props.onScrollChange(newValue, values, index); 128 | } 129 | } 130 | 131 | setHours(date, hour) { 132 | if (this.props.use12Hours) { 133 | const dh = date.getHours(); 134 | let nhour = hour; 135 | nhour = dh >= 12 ? hour + 12 : hour; 136 | nhour = nhour >= 24 ? 0 : nhour; // Make sure no more than one day 137 | date.setHours(nhour); 138 | } else { 139 | date.setHours(hour); 140 | } 141 | } 142 | 143 | setAmPm(date, index) { 144 | if (index === 0) { 145 | date.setTime(+date - ONE_DAY / 2); 146 | } else { 147 | date.setTime(+date + ONE_DAY / 2); 148 | } 149 | } 150 | 151 | getDefaultMinDate() { 152 | if (!this.defaultMinDate) { 153 | this.defaultMinDate = new Date(2000, 1, 1, 0, 0, 0); 154 | } 155 | return this.defaultMinDate; 156 | } 157 | 158 | getDefaultMaxDate() { 159 | if (!this.defaultMaxDate) { 160 | this.defaultMaxDate = new Date(2030, 1, 1, 23, 59, 59); 161 | } 162 | return this.defaultMaxDate; 163 | } 164 | 165 | getDate() { 166 | return this.clipDate(this.state.date || this.getDefaultMinDate()); 167 | } 168 | 169 | // used by rmc-picker/lib/PopupMixin.js 170 | getValue() { 171 | return this.getDate(); 172 | } 173 | 174 | getMinYear() { 175 | return this.getMinDate().getFullYear(); 176 | } 177 | 178 | getMaxYear() { 179 | return this.getMaxDate().getFullYear(); 180 | } 181 | 182 | getMinMonth() { 183 | return this.getMinDate().getMonth(); 184 | } 185 | 186 | getMaxMonth() { 187 | return this.getMaxDate().getMonth(); 188 | } 189 | 190 | getMinDay() { 191 | return this.getMinDate().getDate(); 192 | } 193 | 194 | getMaxDay() { 195 | return this.getMaxDate().getDate(); 196 | } 197 | 198 | getMinHour() { 199 | return this.getMinDate().getHours(); 200 | } 201 | 202 | getMaxHour() { 203 | return this.getMaxDate().getHours(); 204 | } 205 | 206 | getMinMinute() { 207 | return this.getMinDate().getMinutes(); 208 | } 209 | 210 | getMaxMinute() { 211 | return this.getMaxDate().getMinutes(); 212 | } 213 | 214 | getMinDate() { 215 | return this.props.minDate || this.getDefaultMinDate(); 216 | } 217 | 218 | getMaxDate() { 219 | return this.props.maxDate || this.getDefaultMaxDate(); 220 | } 221 | 222 | getDateData() { 223 | const { locale, formatMonth, formatDay, mode } = this.props; 224 | const date = this.getDate(); 225 | const selYear = date.getFullYear(); 226 | const selMonth = date.getMonth(); 227 | const minDateYear = this.getMinYear(); 228 | const maxDateYear = this.getMaxYear(); 229 | const minDateMonth = this.getMinMonth(); 230 | const maxDateMonth = this.getMaxMonth(); 231 | const minDateDay = this.getMinDay(); 232 | const maxDateDay = this.getMaxDay(); 233 | const years: any[] = []; 234 | for (let i = minDateYear; i <= maxDateYear; i++) { 235 | years.push({ 236 | value: i + '', 237 | label: i + locale.year + '', 238 | }); 239 | } 240 | const yearCol = { key: 'year', props: { children: years } }; 241 | if (mode === YEAR) { 242 | return [yearCol]; 243 | } 244 | 245 | const months: any[] = []; 246 | let minMonth = 0; 247 | let maxMonth = 11; 248 | if (minDateYear === selYear) { 249 | minMonth = minDateMonth; 250 | } 251 | if (maxDateYear === selYear) { 252 | maxMonth = maxDateMonth; 253 | } 254 | for (let i = minMonth; i <= maxMonth; i++) { 255 | const label = formatMonth ? formatMonth(i, date) : (i + 1 + locale.month + ''); 256 | months.push({ 257 | value: i + '', 258 | label, 259 | }); 260 | } 261 | const monthCol = { key: 'month', props: { children: months } }; 262 | if (mode === MONTH) { 263 | return [yearCol, monthCol]; 264 | } 265 | 266 | const days: any[] = []; 267 | let minDay = 1; 268 | let maxDay = getDaysInMonth(date); 269 | 270 | if (minDateYear === selYear && minDateMonth === selMonth) { 271 | minDay = minDateDay; 272 | } 273 | if (maxDateYear === selYear && maxDateMonth === selMonth) { 274 | maxDay = maxDateDay; 275 | } 276 | for (let i = minDay; i <= maxDay; i++) { 277 | const label = formatDay ? formatDay(i, date) : (i + locale.day + ''); 278 | days.push({ 279 | value: i + '', 280 | label, 281 | }); 282 | } 283 | return [ 284 | yearCol, 285 | monthCol, 286 | { key: 'day', props: { children: days } }, 287 | ]; 288 | } 289 | 290 | getDisplayHour(rawHour) { 291 | // 12 hour am (midnight 00:00) -> 12 hour pm (noon 12:00) -> 12 hour am (midnight 00:00) 292 | if (this.props.use12Hours) { 293 | if (rawHour === 0) { 294 | rawHour = 12; 295 | } 296 | if (rawHour > 12) { 297 | rawHour -= 12; 298 | } 299 | return rawHour; 300 | } 301 | return rawHour; 302 | } 303 | 304 | getTimeData(date) { 305 | let { minHour = 0, maxHour = 23, minMinute = 0, maxMinute = 59 } = this.props; 306 | const { mode, locale, minuteStep, use12Hours } = this.props; 307 | const minDateMinute = this.getMinMinute(); 308 | const maxDateMinute = this.getMaxMinute(); 309 | const minDateHour = this.getMinHour(); 310 | const maxDateHour = this.getMaxHour(); 311 | const hour = date.getHours(); 312 | if (mode === DATETIME) { 313 | const year = date.getFullYear(); 314 | const month = date.getMonth(); 315 | const day = date.getDate(); 316 | const minDateYear = this.getMinYear(); 317 | const maxDateYear = this.getMaxYear(); 318 | const minDateMonth = this.getMinMonth(); 319 | const maxDateMonth = this.getMaxMonth(); 320 | const minDateDay = this.getMinDay(); 321 | const maxDateDay = this.getMaxDay(); 322 | if (minDateYear === year && minDateMonth === month && minDateDay === day) { 323 | minHour = minDateHour; 324 | if (minDateHour === hour) { 325 | minMinute = minDateMinute; 326 | } 327 | } 328 | if (maxDateYear === year && maxDateMonth === month && maxDateDay === day) { 329 | maxHour = maxDateHour; 330 | if (maxDateHour === hour) { 331 | maxMinute = maxDateMinute; 332 | } 333 | } 334 | } else { 335 | minHour = minDateHour; 336 | if (minDateHour === hour) { 337 | minMinute = minDateMinute; 338 | } 339 | maxHour = maxDateHour; 340 | if (maxDateHour === hour) { 341 | maxMinute = maxDateMinute; 342 | } 343 | } 344 | 345 | const hours: any[] = []; 346 | if (minHour === 0 && maxHour === 0 || minHour !== 0 && maxHour !== 0) { 347 | minHour = this.getDisplayHour(minHour); 348 | } else if (minHour === 0 && use12Hours) { 349 | minHour = 1; 350 | hours.push({ value: '0', label: locale.hour ? '12' + locale.hour : '12' }); 351 | } 352 | maxHour = this.getDisplayHour(maxHour); 353 | for (let i = minHour; i <= maxHour; i++) { 354 | hours.push({ 355 | value: i + '', 356 | label: locale.hour ? i + locale.hour + '' : pad(i), 357 | }); 358 | } 359 | 360 | const minutes: any[] = []; 361 | const selMinute = date.getMinutes(); 362 | for (let i = minMinute; i <= maxMinute; i += minuteStep!) { 363 | minutes.push({ 364 | value: i + '', 365 | label: locale.minute ? i + locale.minute + '' : pad(i), 366 | }); 367 | if (selMinute > i && selMinute < i + minuteStep!) { 368 | minutes.push({ 369 | value: selMinute + '', 370 | label: locale.minute ? selMinute + locale.minute + '' : pad(selMinute), 371 | }); 372 | } 373 | } 374 | const cols = [ 375 | { key: 'hours', props: { children: hours } }, 376 | { key: 'minutes', props: { children: minutes } }, 377 | ].concat(use12Hours ? [{ 378 | key: 'ampm', 379 | props: { children: [{ value: '0', label: locale.am }, { value: '1', label: locale.pm }] }, 380 | }] : []); 381 | return { cols, selMinute }; 382 | } 383 | 384 | clipDate(date) { 385 | const { mode } = this.props; 386 | const minDate = this.getMinDate(); 387 | const maxDate = this.getMaxDate(); 388 | if (mode === DATETIME) { 389 | if (date < minDate) { 390 | return cloneDate(minDate); 391 | } 392 | if (date > maxDate) { 393 | return cloneDate(maxDate); 394 | } 395 | } else if (mode === DATE || mode === YEAR || mode === MONTH) { 396 | // compare-two-dates: https://stackoverflow.com/a/14629978/2190503 397 | if (+date + ONE_DAY <= minDate) { 398 | return cloneDate(minDate); 399 | } 400 | if (date >= +maxDate + ONE_DAY) { 401 | return cloneDate(maxDate); 402 | } 403 | } else if (mode === TIME) { 404 | const maxHour = maxDate.getHours(); 405 | const maxMinutes = maxDate.getMinutes(); 406 | const minHour = minDate.getHours(); 407 | const minMinutes = minDate.getMinutes(); 408 | const hour = date.getHours(); 409 | const minutes = date.getMinutes(); 410 | if (hour < minHour || hour === minHour && minutes < minMinutes) { 411 | return cloneDate(minDate); 412 | } 413 | if (hour > maxHour || hour === maxHour && minutes > maxMinutes) { 414 | return cloneDate(maxDate); 415 | } 416 | } 417 | return date; 418 | } 419 | 420 | getValueCols() { 421 | const { mode, use12Hours } = this.props; 422 | const date = this.getDate(); 423 | let cols: any[] = []; 424 | let value: any[] = []; 425 | 426 | if (mode === YEAR) { 427 | return { 428 | cols: this.getDateData(), 429 | value: [date.getFullYear() + ''], 430 | }; 431 | } 432 | 433 | if (mode === MONTH) { 434 | return { 435 | cols: this.getDateData(), 436 | value: [date.getFullYear() + '', date.getMonth() + ''], 437 | }; 438 | } 439 | 440 | if (mode === DATETIME || mode === DATE) { 441 | cols = this.getDateData(); 442 | value = [date.getFullYear() + '', date.getMonth() + '', date.getDate() + '']; 443 | } 444 | 445 | if (mode === DATETIME || mode === TIME) { 446 | const time = this.getTimeData(date); 447 | cols = cols.concat(time.cols); 448 | const hour = date.getHours(); 449 | let dtValue = [hour + '', time.selMinute + '']; 450 | let nhour = hour; 451 | if (use12Hours) { 452 | nhour = hour > 12 ? hour - 12 : hour; 453 | dtValue = [nhour + '', time.selMinute + '', (hour >= 12 ? 1 : 0) + '']; 454 | } 455 | value = value.concat(dtValue); 456 | } 457 | return { 458 | value, 459 | cols, 460 | }; 461 | } 462 | 463 | render() { 464 | const { value, cols } = this.getValueCols(); 465 | const { 466 | disabled, pickerPrefixCls, prefixCls, rootNativeProps, className, style, itemStyle, 467 | } = this.props; 468 | const multiStyle = { 469 | flexDirection: 'row', 470 | alignItems: 'center', 471 | ...style, 472 | }; 473 | return ( 474 | 483 | {cols.map(p => ( 484 | 491 | {p.props.children.map(item => ( 492 | 493 | {item.label} 494 | 495 | ))} 496 | 497 | ))} 498 | 499 | ); 500 | } 501 | } 502 | 503 | export default DatePicker; 504 | --------------------------------------------------------------------------------