Commit 0f6778937cce9dbbc6d1c99b4d0da3f8dfd7283b
1 parent
17e1fcf1
update DatePicker
update DatePicker
Showing
11 changed files
with
830 additions
and
19 deletions
Show diff stats
src/components/date-picker/base/date-table.vue
1 | 1 | <template> |
2 | - | |
2 | + <table | |
3 | + cellspacing="0" | |
4 | + cellpadding="0" | |
5 | + :class="classes" | |
6 | + @click="handleClick" | |
7 | + @mousemove="handleMouseMove"> | |
8 | + <tbody> | |
9 | + <tr> | |
10 | + <th v-if="showWeekNumber"></th> | |
11 | + <th>日</th> | |
12 | + <th>一</th> | |
13 | + <th>二</th> | |
14 | + <th>三</th> | |
15 | + <th>四</th> | |
16 | + <th>五</th> | |
17 | + <th>六</th> | |
18 | + </tr> | |
19 | + <tr :class="rowCls(row[1])" v-for="row in rows"> | |
20 | + <td :class="getCellClasses(cell)" v-for="cell in row">{{ cell.text }}</td> | |
21 | + </tr> | |
22 | + </tbody> | |
23 | + </table> | |
3 | 24 | </template> |
4 | 25 | <script> |
26 | + const prefixCls = 'ivu-date-picker-table'; | |
27 | + | |
5 | 28 | export default { |
6 | - props: {}, | |
29 | + props: { | |
30 | + date: {}, | |
31 | + year: {}, | |
32 | + month: {}, | |
33 | + week: {}, | |
34 | + selectionMode: { | |
35 | + default: 'day' | |
36 | + }, | |
37 | + showWeekNumber: { | |
38 | + type: Boolean, | |
39 | + default: false | |
40 | + }, | |
41 | + disabledDate: {}, | |
42 | + minDate: {}, | |
43 | + maxDate: {}, | |
44 | + rangeState: { | |
45 | + default () { | |
46 | + return { | |
47 | + endDate: null, | |
48 | + selecting: false, | |
49 | + row: null, | |
50 | + column: null | |
51 | + }; | |
52 | + } | |
53 | + }, | |
54 | + value: {} | |
55 | + }, | |
7 | 56 | data () { |
8 | - return {} | |
57 | + return { | |
58 | + prefixCls: prefixCls | |
59 | + } | |
60 | + }, | |
61 | + computed: { | |
62 | + classes () { | |
63 | + return [ | |
64 | + `${prefixCls}`, | |
65 | + { | |
66 | + [`${prefixCls}-week-mode`]: this.selectionMode === 'week' | |
67 | + } | |
68 | + ] | |
69 | + } | |
9 | 70 | }, |
10 | - computed: {}, | |
11 | - methods: {} | |
71 | + methods: { | |
72 | + handleClick () { | |
73 | + | |
74 | + }, | |
75 | + handleMouseMove () { | |
76 | + | |
77 | + }, | |
78 | + rowCls (cell) { | |
79 | + return [ | |
80 | + `${prefixCls}-row`, | |
81 | + { | |
82 | + [`${prefixCls}-row-current`]: this.value && this.isWeekActive(cell) | |
83 | + } | |
84 | + ] | |
85 | + }, | |
86 | + isWeekActive (cell) { | |
87 | + | |
88 | + }, | |
89 | + getCellCls (cell) { | |
90 | + return [ | |
91 | + `${prefixCls}-cell`, | |
92 | + { | |
93 | + [`${prefixCls}-cell-today`]: cell.type === 'today' | |
94 | + } | |
95 | + ] | |
96 | + } | |
97 | + } | |
12 | 98 | } |
13 | 99 | </script> |
14 | 100 | \ No newline at end of file | ... | ... |
src/components/date-picker/base/month-table.vue
src/components/date-picker/base/year-table.vue
src/components/date-picker/panel/date.vue
1 | 1 | <template> |
2 | - | |
2 | + <div :class="[prefixCls + '-body-wrapper']"> | |
3 | + <div :class="[prefixCls + '-sidebar']" v-if="shortcuts"> | |
4 | + <div | |
5 | + :class="[prefixCls + '-shortcut']" | |
6 | + v-for="shortcut in shortcuts" | |
7 | + @click="handleShortcutClick(shortcut)">{{ shortcut.text }}</div> | |
8 | + </div> | |
9 | + <div :class="[prefixCls + '-body']"> | |
10 | + <div :class="[datePrefixCls + '-header']" v-show="currentView !== 'time'"> | |
11 | + <span | |
12 | + :class="iconBtnCls('prev', '-double')" | |
13 | + @click="prevYear"></span> | |
14 | + <span | |
15 | + :class="iconBtnCls('prev')" | |
16 | + @click="prevMonth" | |
17 | + v-show="currentView === 'date'"></span> | |
18 | + <span | |
19 | + :class="[datePrefixCls + '-header-label']" | |
20 | + @click="showYearPicker">{{ }}</span> | |
21 | + <span | |
22 | + :class="[datePrefixCls + '-header-label']" | |
23 | + @click="showMonthPicker" | |
24 | + v-show="currentView === 'date'">{{ }}</span> | |
25 | + <span | |
26 | + :class="iconBtnCls('next')" | |
27 | + @click="nextMonth" | |
28 | + v-show="currentView === 'date'"></span> | |
29 | + <span | |
30 | + :class="iconBtnCls('next', '-double')" | |
31 | + @click="nextYear"></span> | |
32 | + </div> | |
33 | + <div :class="[prefixCls + '-content']"> | |
34 | + <date-table | |
35 | + v-show="currentView === 'date'"></date-table> | |
36 | + <year-table | |
37 | + v-show="currentView === 'year'"></year-table> | |
38 | + <month-table | |
39 | + v-show="currentView === 'month'"></month-table> | |
40 | + </div> | |
41 | + </div> | |
42 | + </div> | |
3 | 43 | </template> |
4 | 44 | <script> |
45 | + import DateTable from '../base/date-table.vue'; | |
46 | + import YearTable from '../base/year-table.vue'; | |
47 | + import MonthTable from '../base/month-table.vue'; | |
48 | + | |
49 | + const prefixCls = 'ivu-picker-panel'; | |
50 | + const datePrefixCls = 'ivu-date-picker'; | |
51 | + | |
5 | 52 | export default { |
6 | - props: {}, | |
53 | + components: { DateTable, YearTable, MonthTable }, | |
7 | 54 | data () { |
8 | - return {} | |
55 | + return { | |
56 | + prefixCls: prefixCls, | |
57 | + datePrefixCls: datePrefixCls, | |
58 | + shortcuts: [], | |
59 | + currentView: 'date' | |
60 | + } | |
9 | 61 | }, |
10 | 62 | computed: {}, |
11 | - methods: {} | |
63 | + methods: { | |
64 | + handleShortcutClick (shortcut) { | |
65 | + | |
66 | + }, | |
67 | + iconBtnCls (direction, type = '') { | |
68 | + return [ | |
69 | + `${prefixCls}-icon-btn`, | |
70 | + `${datePrefixCls}-${direction}-btn`, | |
71 | + `${datePrefixCls}-${direction}-btn-arrow${type}`, | |
72 | + ] | |
73 | + }, | |
74 | + prevYear () { | |
75 | + | |
76 | + }, | |
77 | + nextYear () { | |
78 | + | |
79 | + }, | |
80 | + prevMonth () { | |
81 | + | |
82 | + }, | |
83 | + nextMonth () { | |
84 | + | |
85 | + }, | |
86 | + showYearPicker () { | |
87 | + | |
88 | + }, | |
89 | + showMonthPicker () { | |
90 | + | |
91 | + } | |
92 | + }, | |
93 | + ready () { | |
94 | + console.log(123) | |
95 | + }, | |
96 | + beforeDestroy () { | |
97 | + console.log(456) | |
98 | + } | |
12 | 99 | } |
13 | 100 | </script> |
14 | 101 | \ No newline at end of file | ... | ... |
src/components/date-picker/picker.vue
1 | 1 | <template> |
2 | - | |
2 | + <div | |
3 | + :class="[prefixCls]" | |
4 | + v-clickoutside="handleClose" | |
5 | + @mouseenter="handleMouseenter" | |
6 | + @mouseleave="handleMouseleave"> | |
7 | + <i-input | |
8 | + v-el:reference | |
9 | + :class="[prefixCls + '-editor']" | |
10 | + :readonly="!editable || readonly" | |
11 | + :disabled="disabled" | |
12 | + :size="size" | |
13 | + :placeholder="placeholder" | |
14 | + :value.sync="visualValue" | |
15 | + @on-focus="handleFocus" | |
16 | + @on-blur="handleBlur" | |
17 | + @on-click="handleIconClick" | |
18 | + :icon="iconType"></i-input> | |
19 | + <Drop v-show="visible" :placement="placement" transition="slide-up" v-ref:drop> | |
20 | + <div v-el:picker></div> | |
21 | + </Drop> | |
22 | + </div> | |
3 | 23 | </template> |
4 | 24 | <script> |
25 | + import Vue from 'vue'; | |
26 | + import iInput from '../../components/input/input.vue'; | |
27 | + import Drop from '../../components/select/dropdown.vue'; | |
28 | + import clickoutside from '../../directives/clickoutside'; | |
29 | + import { oneOf } from '../../utils/assist'; | |
30 | + | |
31 | + const prefixCls = 'ivu-date-picker'; | |
32 | + | |
33 | + const DEFAULT_FORMATS = { | |
34 | + date: 'yyyy-MM-dd', | |
35 | + month: 'yyyy-MM', | |
36 | + datetime: 'yyyy-MM-dd HH:mm:ss', | |
37 | + time: 'HH:mm:ss', | |
38 | + timerange: 'HH:mm:ss', | |
39 | + daterange: 'yyyy-MM-dd', | |
40 | + datetimerange: 'yyyy-MM-dd HH:mm:ss' | |
41 | + }; | |
42 | + | |
43 | + const PLACEMENT_MAP = { | |
44 | + left: 'bottom-start', | |
45 | + center: 'bottom-center', | |
46 | + right: 'bottom-end' | |
47 | + }; | |
48 | + | |
5 | 49 | export default { |
6 | - props: {}, | |
50 | + components: { iInput, Drop }, | |
51 | + directives: { clickoutside }, | |
52 | + props: { | |
53 | + format: { | |
54 | + type: String | |
55 | + }, | |
56 | + readonly: { | |
57 | + type: Boolean, | |
58 | + default: false | |
59 | + }, | |
60 | + disabled: { | |
61 | + type: Boolean, | |
62 | + default: false | |
63 | + }, | |
64 | + editable: { | |
65 | + type: Boolean, | |
66 | + default: true | |
67 | + }, | |
68 | + size: { | |
69 | + validator (value) { | |
70 | + return oneOf(value, ['small', 'large']); | |
71 | + } | |
72 | + }, | |
73 | + placeholder: { | |
74 | + type: String, | |
75 | + default: '' | |
76 | + }, | |
77 | + align: { | |
78 | + validator (value) { | |
79 | + return oneOf(value, ['left', 'center', 'right']); | |
80 | + }, | |
81 | + default: 'left' | |
82 | + }, | |
83 | + options: { | |
84 | + type: Object | |
85 | + } | |
86 | + }, | |
7 | 87 | data () { |
8 | - return {} | |
88 | + return { | |
89 | + prefixCls: prefixCls, | |
90 | + showClose: false, | |
91 | + visualValue: '', | |
92 | + visible: false, | |
93 | + picker: null | |
94 | + } | |
95 | + }, | |
96 | + computed: { | |
97 | + iconType () { | |
98 | + return this.showClose ? 'ios-close' : 'ios-calendar-outline'; | |
99 | + }, | |
100 | + placement () { | |
101 | + return PLACEMENT_MAP[this.align]; | |
102 | + } | |
103 | + }, | |
104 | + methods: { | |
105 | + handleClose () { | |
106 | + this.visible = false; | |
107 | + }, | |
108 | + handleFocus () { | |
109 | + this.visible = true; | |
110 | + }, | |
111 | + handleBlur () { | |
112 | + | |
113 | + }, | |
114 | + handleMouseenter () { | |
115 | + if (this.readonly || this.disabled) return; | |
116 | + if (this.visualValue) { | |
117 | + this.showClose = true; | |
118 | + } | |
119 | + }, | |
120 | + handleMouseleave () { | |
121 | + this.showClose = false; | |
122 | + }, | |
123 | + handleIconClick () { | |
124 | + | |
125 | + }, | |
126 | + showPicker () { | |
127 | + if (!this.picker) { | |
128 | + this.picker = new Vue(this.panel).$mount(this.$els.picker); | |
129 | + } | |
130 | + } | |
131 | + }, | |
132 | + watch: { | |
133 | + visible (val) { | |
134 | + if (val) { | |
135 | + this.showPicker(); | |
136 | + this.$refs.drop.update(); | |
137 | + } else { | |
138 | + this.$refs.drop.destroy(); | |
139 | + } | |
140 | + } | |
9 | 141 | }, |
10 | - computed: {}, | |
11 | - methods: {} | |
142 | + beforeDestroy () { | |
143 | + if (this.picker) { | |
144 | + this.picker.$destroy(); | |
145 | + } | |
146 | + } | |
12 | 147 | } |
13 | 148 | </script> |
14 | 149 | \ No newline at end of file | ... | ... |
src/components/date-picker/picker/date-picker.js
... | ... | @@ -9,11 +9,15 @@ const getPanel = function (type) { |
9 | 9 | return DatePanel; |
10 | 10 | }; |
11 | 11 | |
12 | +import { oneOf } from '../../../utils/assist'; | |
13 | + | |
12 | 14 | export default { |
13 | 15 | mixins: [Picker], |
14 | 16 | props: { |
15 | 17 | type: { |
16 | - type: String, | |
18 | + validator (value) { | |
19 | + return oneOf(value, ['year', 'month', 'week', 'date', 'daterange', 'datetime', 'datetimerange']); | |
20 | + }, | |
17 | 21 | default: 'date' |
18 | 22 | } |
19 | 23 | }, | ... | ... |
1 | +import dateUtil from '../../utils/date'; | |
2 | + | |
3 | +const newArray = function(start, end) { | |
4 | + let result = []; | |
5 | + for (let i = start; i <= end; i++) { | |
6 | + result.push(i); | |
7 | + } | |
8 | + return result; | |
9 | +}; | |
10 | + | |
11 | +export const toDate = function(date) { | |
12 | + date = new Date(date); | |
13 | + if (isNaN(date.getTime())) return null; | |
14 | + return date; | |
15 | +}; | |
16 | + | |
17 | +export const formatDate = function(date, format) { | |
18 | + date = toDate(date); | |
19 | + if (!date) return ''; | |
20 | + return dateUtil.format(date, format || 'yyyy-MM-dd'); | |
21 | +}; | |
22 | + | |
23 | +export const parseDate = function(string, format) { | |
24 | + return dateUtil.parse(string, format || 'yyyy-MM-dd'); | |
25 | +}; | |
26 | + | |
27 | +export const getDayCountOfMonth = function(year, month) { | |
28 | + if (month === 3 || month === 5 || month === 8 || month === 10) { | |
29 | + return 30; | |
30 | + } | |
31 | + | |
32 | + if (month === 1) { | |
33 | + if (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0) { | |
34 | + return 29; | |
35 | + } else { | |
36 | + return 28; | |
37 | + } | |
38 | + } | |
39 | + | |
40 | + return 31; | |
41 | +}; | |
42 | + | |
43 | +export const getFirstDayOfMonth = function(date) { | |
44 | + const temp = new Date(date.getTime()); | |
45 | + temp.setDate(1); | |
46 | + return temp.getDay(); | |
47 | +}; | |
48 | + | |
49 | +export const DAY_DURATION = 86400000; | |
50 | + | |
51 | +export const getStartDateOfMonth = function(year, month) { | |
52 | + const result = new Date(year, month, 1); | |
53 | + const day = result.getDay(); | |
54 | + | |
55 | + if (day === 0) { | |
56 | + result.setTime(result.getTime() - DAY_DURATION * 7); | |
57 | + } else { | |
58 | + result.setTime(result.getTime() - DAY_DURATION * day); | |
59 | + } | |
60 | + | |
61 | + return result; | |
62 | +}; | |
63 | + | |
64 | +export const getWeekNumber = function(src) { | |
65 | + const date = new Date(src.getTime()); | |
66 | + date.setHours(0, 0, 0, 0); | |
67 | + // Thursday in current week decides the year. | |
68 | + date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7); | |
69 | + // January 4 is always in week 1. | |
70 | + const week1 = new Date(date.getFullYear(), 0, 4); | |
71 | + // Adjust to Thursday in week 1 and count number of weeks from date to week 1. | |
72 | + return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7); | |
73 | +}; | |
74 | + | |
75 | +export const prevMonth = function(src) { | |
76 | + const year = src.getFullYear(); | |
77 | + const month = src.getMonth(); | |
78 | + const date = src.getDate(); | |
79 | + | |
80 | + const newYear = month === 0 ? year - 1 : year; | |
81 | + const newMonth = month === 0 ? 11 : month - 1; | |
82 | + | |
83 | + const newMonthDayCount = getDayCountOfMonth(newYear, newMonth); | |
84 | + if (newMonthDayCount < date) { | |
85 | + src.setDate(newMonthDayCount); | |
86 | + } | |
87 | + | |
88 | + src.setMonth(newMonth); | |
89 | + src.setFullYear(newYear); | |
90 | + | |
91 | + return new Date(src.getTime()); | |
92 | +}; | |
93 | + | |
94 | +export const nextMonth = function(src) { | |
95 | + const year = src.getFullYear(); | |
96 | + const month = src.getMonth(); | |
97 | + const date = src.getDate(); | |
98 | + | |
99 | + const newYear = month === 11 ? year + 1 : year; | |
100 | + const newMonth = month === 11 ? 0 : month + 1; | |
101 | + | |
102 | + const newMonthDayCount = getDayCountOfMonth(newYear, newMonth); | |
103 | + if (newMonthDayCount < date) { | |
104 | + src.setDate(newMonthDayCount); | |
105 | + } | |
106 | + | |
107 | + src.setMonth(newMonth); | |
108 | + src.setFullYear(newYear); | |
109 | + | |
110 | + return new Date(src.getTime()); | |
111 | +}; | |
112 | + | |
113 | +export const getRangeHours = function(ranges) { | |
114 | + const hours = []; | |
115 | + let disabledHours = []; | |
116 | + | |
117 | + (ranges || []).forEach(range => { | |
118 | + const value = range.map(date => date.getHours()); | |
119 | + | |
120 | + disabledHours = disabledHours.concat(newArray(value[0], value[1])); | |
121 | + }); | |
122 | + | |
123 | + if (disabledHours.length) { | |
124 | + for (let i = 0; i < 24; i++) { | |
125 | + hours[i] = disabledHours.indexOf(i) === -1; | |
126 | + } | |
127 | + } else { | |
128 | + for (let i = 0; i < 24; i++) { | |
129 | + hours[i] = false; | |
130 | + } | |
131 | + } | |
132 | + | |
133 | + return hours; | |
134 | +}; | |
135 | + | |
136 | +export const limitRange = function(date, ranges) { | |
137 | + if (!ranges || !ranges.length) return date; | |
138 | + | |
139 | + const len = ranges.length; | |
140 | + const format = 'HH:mm:ss'; | |
141 | + | |
142 | + date = dateUtil.parse(dateUtil.format(date, format), format); | |
143 | + for (let i = 0; i < len; i++) { | |
144 | + const range = ranges[i]; | |
145 | + if (date >= range[0] && date <= range[1]) { | |
146 | + return date; | |
147 | + } | |
148 | + } | |
149 | + | |
150 | + let maxDate = ranges[0][0]; | |
151 | + let minDate = ranges[0][0]; | |
152 | + | |
153 | + ranges.forEach(range => { | |
154 | + minDate = new Date(Math.min(range[0], minDate)); | |
155 | + maxDate = new Date(Math.max(range[1], maxDate)); | |
156 | + }); | |
157 | + | |
158 | + return date < minDate ? minDate : maxDate; | |
159 | +}; | ... | ... |
1 | +/*eslint-disable*/ | |
2 | +// 把 YYYY-MM-DD 改成了 yyyy-MM-dd | |
3 | +(function (main) { | |
4 | + 'use strict'; | |
5 | + | |
6 | + /** | |
7 | + * Parse or format dates | |
8 | + * @class fecha | |
9 | + */ | |
10 | + var fecha = {}; | |
11 | + var token = /d{1,4}|M{1,4}|yy(?:yy)?|S{1,3}|Do|ZZ|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g; | |
12 | + var twoDigits = /\d\d?/; | |
13 | + var threeDigits = /\d{3}/; | |
14 | + var fourDigits = /\d{4}/; | |
15 | + var word = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i; | |
16 | + var noop = function () { | |
17 | + }; | |
18 | + | |
19 | + function shorten(arr, sLen) { | |
20 | + var newArr = []; | |
21 | + for (var i = 0, len = arr.length; i < len; i++) { | |
22 | + newArr.push(arr[i].substr(0, sLen)); | |
23 | + } | |
24 | + return newArr; | |
25 | + } | |
26 | + | |
27 | + function monthUpdate(arrName) { | |
28 | + return function (d, v, i18n) { | |
29 | + var index = i18n[arrName].indexOf(v.charAt(0).toUpperCase() + v.substr(1).toLowerCase()); | |
30 | + if (~index) { | |
31 | + d.month = index; | |
32 | + } | |
33 | + }; | |
34 | + } | |
35 | + | |
36 | + function pad(val, len) { | |
37 | + val = String(val); | |
38 | + len = len || 2; | |
39 | + while (val.length < len) { | |
40 | + val = '0' + val; | |
41 | + } | |
42 | + return val; | |
43 | + } | |
44 | + | |
45 | + var dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; | |
46 | + var monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; | |
47 | + var monthNamesShort = shorten(monthNames, 3); | |
48 | + var dayNamesShort = shorten(dayNames, 3); | |
49 | + fecha.i18n = { | |
50 | + dayNamesShort: dayNamesShort, | |
51 | + dayNames: dayNames, | |
52 | + monthNamesShort: monthNamesShort, | |
53 | + monthNames: monthNames, | |
54 | + amPm: ['am', 'pm'], | |
55 | + DoFn: function DoFn(D) { | |
56 | + return D + ['th', 'st', 'nd', 'rd'][D % 10 > 3 ? 0 : (D - D % 10 !== 10) * D % 10]; | |
57 | + } | |
58 | + }; | |
59 | + | |
60 | + var formatFlags = { | |
61 | + D: function (dateObj) { | |
62 | + return dateObj.getDay(); | |
63 | + }, | |
64 | + DD: function (dateObj) { | |
65 | + return pad(dateObj.getDay()); | |
66 | + }, | |
67 | + Do: function (dateObj, i18n) { | |
68 | + return i18n.DoFn(dateObj.getDate()); | |
69 | + }, | |
70 | + d: function (dateObj) { | |
71 | + return dateObj.getDate(); | |
72 | + }, | |
73 | + dd: function (dateObj) { | |
74 | + return pad(dateObj.getDate()); | |
75 | + }, | |
76 | + ddd: function (dateObj, i18n) { | |
77 | + return i18n.dayNamesShort[dateObj.getDay()]; | |
78 | + }, | |
79 | + dddd: function (dateObj, i18n) { | |
80 | + return i18n.dayNames[dateObj.getDay()]; | |
81 | + }, | |
82 | + M: function (dateObj) { | |
83 | + return dateObj.getMonth() + 1; | |
84 | + }, | |
85 | + MM: function (dateObj) { | |
86 | + return pad(dateObj.getMonth() + 1); | |
87 | + }, | |
88 | + MMM: function (dateObj, i18n) { | |
89 | + return i18n.monthNamesShort[dateObj.getMonth()]; | |
90 | + }, | |
91 | + MMMM: function (dateObj, i18n) { | |
92 | + return i18n.monthNames[dateObj.getMonth()]; | |
93 | + }, | |
94 | + yy: function (dateObj) { | |
95 | + return String(dateObj.getFullYear()).substr(2); | |
96 | + }, | |
97 | + yyyy: function (dateObj) { | |
98 | + return dateObj.getFullYear(); | |
99 | + }, | |
100 | + h: function (dateObj) { | |
101 | + return dateObj.getHours() % 12 || 12; | |
102 | + }, | |
103 | + hh: function (dateObj) { | |
104 | + return pad(dateObj.getHours() % 12 || 12); | |
105 | + }, | |
106 | + H: function (dateObj) { | |
107 | + return dateObj.getHours(); | |
108 | + }, | |
109 | + HH: function (dateObj) { | |
110 | + return pad(dateObj.getHours()); | |
111 | + }, | |
112 | + m: function (dateObj) { | |
113 | + return dateObj.getMinutes(); | |
114 | + }, | |
115 | + mm: function (dateObj) { | |
116 | + return pad(dateObj.getMinutes()); | |
117 | + }, | |
118 | + s: function (dateObj) { | |
119 | + return dateObj.getSeconds(); | |
120 | + }, | |
121 | + ss: function (dateObj) { | |
122 | + return pad(dateObj.getSeconds()); | |
123 | + }, | |
124 | + S: function (dateObj) { | |
125 | + return Math.round(dateObj.getMilliseconds() / 100); | |
126 | + }, | |
127 | + SS: function (dateObj) { | |
128 | + return pad(Math.round(dateObj.getMilliseconds() / 10), 2); | |
129 | + }, | |
130 | + SSS: function (dateObj) { | |
131 | + return pad(dateObj.getMilliseconds(), 3); | |
132 | + }, | |
133 | + a: function (dateObj, i18n) { | |
134 | + return dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1]; | |
135 | + }, | |
136 | + A: function (dateObj, i18n) { | |
137 | + return dateObj.getHours() < 12 ? i18n.amPm[0].toUpperCase() : i18n.amPm[1].toUpperCase(); | |
138 | + }, | |
139 | + ZZ: function (dateObj) { | |
140 | + var o = dateObj.getTimezoneOffset(); | |
141 | + return (o > 0 ? '-' : '+') + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4); | |
142 | + } | |
143 | + }; | |
144 | + | |
145 | + var parseFlags = { | |
146 | + d: [twoDigits, function (d, v) { | |
147 | + d.day = v; | |
148 | + }], | |
149 | + M: [twoDigits, function (d, v) { | |
150 | + d.month = v - 1; | |
151 | + }], | |
152 | + yy: [twoDigits, function (d, v) { | |
153 | + var da = new Date(), cent = +('' + da.getFullYear()).substr(0, 2); | |
154 | + d.year = '' + (v > 68 ? cent - 1 : cent) + v; | |
155 | + }], | |
156 | + h: [twoDigits, function (d, v) { | |
157 | + d.hour = v; | |
158 | + }], | |
159 | + m: [twoDigits, function (d, v) { | |
160 | + d.minute = v; | |
161 | + }], | |
162 | + s: [twoDigits, function (d, v) { | |
163 | + d.second = v; | |
164 | + }], | |
165 | + yyyy: [fourDigits, function (d, v) { | |
166 | + d.year = v; | |
167 | + }], | |
168 | + S: [/\d/, function (d, v) { | |
169 | + d.millisecond = v * 100; | |
170 | + }], | |
171 | + SS: [/\d{2}/, function (d, v) { | |
172 | + d.millisecond = v * 10; | |
173 | + }], | |
174 | + SSS: [threeDigits, function (d, v) { | |
175 | + d.millisecond = v; | |
176 | + }], | |
177 | + D: [twoDigits, noop], | |
178 | + ddd: [word, noop], | |
179 | + MMM: [word, monthUpdate('monthNamesShort')], | |
180 | + MMMM: [word, monthUpdate('monthNames')], | |
181 | + a: [word, function (d, v, i18n) { | |
182 | + var val = v.toLowerCase(); | |
183 | + if (val === i18n.amPm[0]) { | |
184 | + d.isPm = false; | |
185 | + } else if (val === i18n.amPm[1]) { | |
186 | + d.isPm = true; | |
187 | + } | |
188 | + }], | |
189 | + ZZ: [/[\+\-]\d\d:?\d\d/, function (d, v) { | |
190 | + var parts = (v + '').match(/([\+\-]|\d\d)/gi), minutes; | |
191 | + | |
192 | + if (parts) { | |
193 | + minutes = +(parts[1] * 60) + parseInt(parts[2], 10); | |
194 | + d.timezoneOffset = parts[0] === '+' ? minutes : -minutes; | |
195 | + } | |
196 | + }] | |
197 | + }; | |
198 | + parseFlags.DD = parseFlags.DD; | |
199 | + parseFlags.dddd = parseFlags.ddd; | |
200 | + parseFlags.Do = parseFlags.dd = parseFlags.d; | |
201 | + parseFlags.mm = parseFlags.m; | |
202 | + parseFlags.hh = parseFlags.H = parseFlags.HH = parseFlags.h; | |
203 | + parseFlags.MM = parseFlags.M; | |
204 | + parseFlags.ss = parseFlags.s; | |
205 | + parseFlags.A = parseFlags.a; | |
206 | + | |
207 | + | |
208 | + // Some common format strings | |
209 | + fecha.masks = { | |
210 | + 'default': 'ddd MMM dd yyyy HH:mm:ss', | |
211 | + shortDate: 'M/D/yy', | |
212 | + mediumDate: 'MMM d, yyyy', | |
213 | + longDate: 'MMMM d, yyyy', | |
214 | + fullDate: 'dddd, MMMM d, yyyy', | |
215 | + shortTime: 'HH:mm', | |
216 | + mediumTime: 'HH:mm:ss', | |
217 | + longTime: 'HH:mm:ss.SSS' | |
218 | + }; | |
219 | + | |
220 | + /*** | |
221 | + * Format a date | |
222 | + * @method format | |
223 | + * @param {Date|number} dateObj | |
224 | + * @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate' | |
225 | + */ | |
226 | + fecha.format = function (dateObj, mask, i18nSettings) { | |
227 | + var i18n = i18nSettings || fecha.i18n; | |
228 | + | |
229 | + if (typeof dateObj === 'number') { | |
230 | + dateObj = new Date(dateObj); | |
231 | + } | |
232 | + | |
233 | + if (Object.prototype.toString.call(dateObj) !== '[object Date]' || isNaN(dateObj.getTime())) { | |
234 | + throw new Error('Invalid Date in fecha.format'); | |
235 | + } | |
236 | + | |
237 | + mask = fecha.masks[mask] || mask || fecha.masks['default']; | |
238 | + | |
239 | + return mask.replace(token, function ($0) { | |
240 | + return $0 in formatFlags ? formatFlags[$0](dateObj, i18n) : $0.slice(1, $0.length - 1); | |
241 | + }); | |
242 | + }; | |
243 | + | |
244 | + /** | |
245 | + * Parse a date string into an object, changes - into / | |
246 | + * @method parse | |
247 | + * @param {string} dateStr Date string | |
248 | + * @param {string} format Date parse format | |
249 | + * @returns {Date|boolean} | |
250 | + */ | |
251 | + fecha.parse = function (dateStr, format, i18nSettings) { | |
252 | + var i18n = i18nSettings || fecha.i18n; | |
253 | + | |
254 | + if (typeof format !== 'string') { | |
255 | + throw new Error('Invalid format in fecha.parse'); | |
256 | + } | |
257 | + | |
258 | + format = fecha.masks[format] || format; | |
259 | + | |
260 | + // Avoid regular expression denial of service, fail early for really long strings | |
261 | + // https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS | |
262 | + if (dateStr.length > 1000) { | |
263 | + return false; | |
264 | + } | |
265 | + | |
266 | + var isValid = true; | |
267 | + var dateInfo = {}; | |
268 | + format.replace(token, function ($0) { | |
269 | + if (parseFlags[$0]) { | |
270 | + var info = parseFlags[$0]; | |
271 | + var index = dateStr.search(info[0]); | |
272 | + if (!~index) { | |
273 | + isValid = false; | |
274 | + } else { | |
275 | + dateStr.replace(info[0], function (result) { | |
276 | + info[1](dateInfo, result, i18n); | |
277 | + dateStr = dateStr.substr(index + result.length); | |
278 | + return result; | |
279 | + }); | |
280 | + } | |
281 | + } | |
282 | + | |
283 | + return parseFlags[$0] ? '' : $0.slice(1, $0.length - 1); | |
284 | + }); | |
285 | + | |
286 | + if (!isValid) { | |
287 | + return false; | |
288 | + } | |
289 | + | |
290 | + var today = new Date(); | |
291 | + if (dateInfo.isPm === true && dateInfo.hour != null && +dateInfo.hour !== 12) { | |
292 | + dateInfo.hour = +dateInfo.hour + 12; | |
293 | + } else if (dateInfo.isPm === false && +dateInfo.hour === 12) { | |
294 | + dateInfo.hour = 0; | |
295 | + } | |
296 | + | |
297 | + var date; | |
298 | + if (dateInfo.timezoneOffset != null) { | |
299 | + dateInfo.minute = +(dateInfo.minute || 0) - +dateInfo.timezoneOffset; | |
300 | + date = new Date(Date.UTC(dateInfo.year || today.getFullYear(), dateInfo.month || 0, dateInfo.day || 1, | |
301 | + dateInfo.hour || 0, dateInfo.minute || 0, dateInfo.second || 0, dateInfo.millisecond || 0)); | |
302 | + } else { | |
303 | + date = new Date(dateInfo.year || today.getFullYear(), dateInfo.month || 0, dateInfo.day || 1, | |
304 | + dateInfo.hour || 0, dateInfo.minute || 0, dateInfo.second || 0, dateInfo.millisecond || 0); | |
305 | + } | |
306 | + return date; | |
307 | + }; | |
308 | + | |
309 | + /* istanbul ignore next */ | |
310 | + if (typeof module !== 'undefined' && module.exports) { | |
311 | + module.exports = fecha; | |
312 | + } else if (typeof define === 'function' && define.amd) { | |
313 | + define(function () { | |
314 | + return fecha; | |
315 | + }); | |
316 | + } else { | |
317 | + main.fecha = fecha; | |
318 | + } | |
319 | +})(this); | ... | ... |
test/app.vue
test/main.js
1 | +<template> | |
2 | + <div style="margin: 50px"> | |
3 | + <date-picker style="width:200px" placeholder="请选择日期"></date-picker> | |
4 | + </div> | |
5 | +</template> | |
6 | +<script> | |
7 | + export default { | |
8 | + props: {}, | |
9 | + data () { | |
10 | + return {} | |
11 | + }, | |
12 | + computed: {}, | |
13 | + methods: {} | |
14 | + } | |
15 | +</script> | |
0 | 16 | \ No newline at end of file | ... | ... |