mirror of https://github.com/ElemeFE/element
DatePicker: Daylight Saving Time (#7599)
* date-table: fix daylight saving time highlight * test: update date-picker range testpull/7603/head
parent
8313016dae
commit
af46f968ab
|
@ -30,7 +30,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getFirstDayOfMonth, getDayCountOfMonth, getWeekNumber, getStartDateOfMonth, DAY_DURATION, isDate } from '../util';
|
import { getFirstDayOfMonth, getDayCountOfMonth, getWeekNumber, getStartDateOfMonth, nextDate, isDate } from '../util';
|
||||||
import { hasClass } from 'element-ui/src/utils/dom';
|
import { hasClass } from 'element-ui/src/utils/dom';
|
||||||
import Locale from 'element-ui/src/mixins/locale';
|
import Locale from 'element-ui/src/mixins/locale';
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@
|
||||||
|
|
||||||
if (this.showWeekNumber) {
|
if (this.showWeekNumber) {
|
||||||
if (!row[0]) {
|
if (!row[0]) {
|
||||||
row[0] = { type: 'week', text: getWeekNumber(new Date(startDate.getTime() + DAY_DURATION * (i * 7 + 1))) };
|
row[0] = { type: 'week', text: getWeekNumber(nextDate(startDate, i * 7 + 1)) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@
|
||||||
cell.type = 'normal';
|
cell.type = 'normal';
|
||||||
|
|
||||||
const index = i * 7 + j;
|
const index = i * 7 + j;
|
||||||
const time = startDate.getTime() + DAY_DURATION * (index - offset);
|
const time = nextDate(startDate, index - offset).getTime();
|
||||||
cell.inRange = time >= clearHours(this.minDate) && time <= clearHours(this.maxDate);
|
cell.inRange = time >= clearHours(this.minDate) && time <= clearHours(this.maxDate);
|
||||||
cell.start = this.minDate && time === clearHours(this.minDate);
|
cell.start = this.minDate && time === clearHours(this.minDate);
|
||||||
cell.end = this.maxDate && time === clearHours(this.maxDate);
|
cell.end = this.maxDate && time === clearHours(this.maxDate);
|
||||||
|
@ -289,22 +289,8 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
getDateOfCell(row, column) {
|
getDateOfCell(row, column) {
|
||||||
const startDate = this.startDate;
|
const offsetFromStart = row * 7 + (column - (this.showWeekNumber ? 1 : 0)) - this.offsetDay;
|
||||||
|
return nextDate(this.startDate, offsetFromStart);
|
||||||
return new Date(startDate.getTime() + (row * 7 + (column - (this.showWeekNumber ? 1 : 0)) - this.offsetDay) * DAY_DURATION);
|
|
||||||
},
|
|
||||||
|
|
||||||
getCellByDate(date) {
|
|
||||||
const startDate = this.startDate;
|
|
||||||
const rows = this.rows;
|
|
||||||
const index = (date - startDate) / DAY_DURATION;
|
|
||||||
const row = rows[Math.floor(index / 7)];
|
|
||||||
|
|
||||||
if (this.showWeekNumber) {
|
|
||||||
return row[index % 7 + 1];
|
|
||||||
} else {
|
|
||||||
return row[index % 7];
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
isWeekActive(cell) {
|
isWeekActive(cell) {
|
||||||
|
@ -343,7 +329,7 @@
|
||||||
|
|
||||||
const cell = row[j];
|
const cell = row[j];
|
||||||
const index = i * 7 + j + (this.showWeekNumber ? -1 : 0);
|
const index = i * 7 + j + (this.showWeekNumber ? -1 : 0);
|
||||||
const time = startDate.getTime() + DAY_DURATION * (index - this.offsetDay);
|
const time = nextDate(startDate, index - this.offsetDay).getTime();
|
||||||
|
|
||||||
cell.inRange = minDate && time >= clearHours(minDate) && time <= clearHours(maxDate);
|
cell.inRange = minDate && time >= clearHours(minDate) && time <= clearHours(maxDate);
|
||||||
cell.start = minDate && time === clearHours(minDate.getTime());
|
cell.start = minDate && time === clearHours(minDate.getTime());
|
||||||
|
|
|
@ -49,14 +49,13 @@
|
||||||
|
|
||||||
<script type="text/babel">
|
<script type="text/babel">
|
||||||
import Locale from 'element-ui/src/mixins/locale';
|
import Locale from 'element-ui/src/mixins/locale';
|
||||||
import { isDate, range, getDayCountOfMonth } from '../util';
|
import { isDate, range, getDayCountOfMonth, nextDate } from '../util';
|
||||||
import { hasClass } from 'element-ui/src/utils/dom';
|
import { hasClass } from 'element-ui/src/utils/dom';
|
||||||
|
|
||||||
const datesInMonth = (year, month) => {
|
const datesInMonth = (year, month) => {
|
||||||
const numOfDays = getDayCountOfMonth(year, month);
|
const numOfDays = getDayCountOfMonth(year, month);
|
||||||
const firstDay = new Date(year, month, 1);
|
const firstDay = new Date(year, month, 1);
|
||||||
const ONE_DAY = 8.64e7;
|
return range(numOfDays).map(n => nextDate(firstDay, n));
|
||||||
return range(numOfDays).map(n => new Date(firstDay.getTime() + n * ONE_DAY));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
|
@ -45,15 +45,12 @@
|
||||||
|
|
||||||
<script type="text/babel">
|
<script type="text/babel">
|
||||||
import { hasClass } from 'element-ui/src/utils/dom';
|
import { hasClass } from 'element-ui/src/utils/dom';
|
||||||
import { isDate, range } from '../util';
|
import { isDate, range, nextDate, getDayCountOfYear } from '../util';
|
||||||
|
|
||||||
const isLeapYear = year => year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0);
|
|
||||||
|
|
||||||
const datesInYear = year => {
|
const datesInYear = year => {
|
||||||
const numOfDays = isLeapYear(year) ? 366 : 365;
|
const numOfDays = getDayCountOfYear(year);
|
||||||
const firstDay = new Date(year, 0, 1);
|
const firstDay = new Date(year, 0, 1);
|
||||||
const ONE_DAY = 8.64e7;
|
return range(numOfDays).map(n => nextDate(firstDay, n));
|
||||||
return range(numOfDays).map(n => new Date(firstDay.getTime() + ONE_DAY));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
|
@ -61,25 +61,37 @@ export const getDayCountOfMonth = function(year, month) {
|
||||||
return 31;
|
return 31;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getDayCountOfYear = function(year) {
|
||||||
|
const isLeapYear = year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0);
|
||||||
|
return isLeapYear ? 366 : 365;
|
||||||
|
};
|
||||||
|
|
||||||
export const getFirstDayOfMonth = function(date) {
|
export const getFirstDayOfMonth = function(date) {
|
||||||
const temp = new Date(date.getTime());
|
const temp = new Date(date.getTime());
|
||||||
temp.setDate(1);
|
temp.setDate(1);
|
||||||
return temp.getDay();
|
return temp.getDay();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DAY_DURATION = 86400000;
|
// see: https://stackoverflow.com/questions/3674539/incrementing-a-date-in-javascript
|
||||||
|
// {prev, next} Date should work for Daylight Saving Time
|
||||||
|
// Adding 24 * 60 * 60 * 1000 does not work in the above scenario
|
||||||
|
export const prevDate = function(date, amount = 1) {
|
||||||
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate() - amount);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const nextDate = function(date, amount = 1) {
|
||||||
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate() + amount);
|
||||||
|
};
|
||||||
|
|
||||||
export const getStartDateOfMonth = function(year, month) {
|
export const getStartDateOfMonth = function(year, month) {
|
||||||
const result = new Date(year, month, 1);
|
const result = new Date(year, month, 1);
|
||||||
const day = result.getDay();
|
const day = result.getDay();
|
||||||
|
|
||||||
if (day === 0) {
|
if (day === 0) {
|
||||||
result.setTime(result.getTime() - DAY_DURATION * 7);
|
return prevDate(result, 7);
|
||||||
} else {
|
} else {
|
||||||
result.setTime(result.getTime() - DAY_DURATION * day);
|
return prevDate(result, day);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getWeekNumber = function(src) {
|
export const getWeekNumber = function(src) {
|
||||||
|
@ -90,6 +102,7 @@ export const getWeekNumber = function(src) {
|
||||||
// January 4 is always in week 1.
|
// January 4 is always in week 1.
|
||||||
const week1 = new Date(date.getFullYear(), 0, 4);
|
const week1 = new Date(date.getFullYear(), 0, 4);
|
||||||
// Adjust to Thursday in week 1 and count number of weeks from date to week 1.
|
// Adjust to Thursday in week 1 and count number of weeks from date to week 1.
|
||||||
|
// Rounding should be fine for Daylight Saving Time. Its shift should never be more than 12 hours.
|
||||||
return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7);
|
return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -208,13 +221,3 @@ export const nextYear = function(date, amount = 1) {
|
||||||
const monthDate = Math.min(date.getDate(), getDayCountOfMonth(year, month));
|
const monthDate = Math.min(date.getDate(), getDayCountOfMonth(year, month));
|
||||||
return modifyDate(date, year, month, monthDate);
|
return modifyDate(date, year, month, monthDate);
|
||||||
};
|
};
|
||||||
|
|
||||||
// {prev, next} Date works for daylight saving time
|
|
||||||
// add / subtract one day's duration does not work
|
|
||||||
export const prevDate = function(date, amount = 1) {
|
|
||||||
return new Date(date.getFullYear(), date.getMonth(), date.getDate() - amount);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const nextDate = function(date, amount = 1) {
|
|
||||||
return new Date(date.getFullYear(), date.getMonth(), date.getDate() + amount);
|
|
||||||
};
|
|
||||||
|
|
|
@ -1076,36 +1076,50 @@ describe('DatePicker', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('type:daterange', done => {
|
describe('type:daterange', () => {
|
||||||
vm = createTest(DatePicker, {
|
it('works', done => {
|
||||||
type: 'daterange'
|
vm = createVue({
|
||||||
|
template: '<el-date-picker type="daterange" v-model="value" ref="compo" />',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
}, true);
|
}, true);
|
||||||
const input = vm.$el.querySelector('input');
|
|
||||||
|
|
||||||
input.click();
|
const rangePicker = vm.$refs.compo;
|
||||||
|
const inputs = rangePicker.$el.querySelectorAll('input');
|
||||||
|
inputs[0].focus();
|
||||||
|
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
const panels = vm.picker.$el.querySelectorAll('.el-date-range-picker__content');
|
const panels = rangePicker.picker.$el.querySelectorAll('.el-date-range-picker__content');
|
||||||
|
|
||||||
expect(Array.prototype.slice.call(panels)).to.length(2);
|
expect(Array.prototype.slice.call(panels)).to.length(2);
|
||||||
|
|
||||||
panels[0].querySelector('td.available').click();
|
panels[0].querySelector('td.available').click();
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
panels[1].querySelector('td.available').click();
|
panels[1].querySelector('td.available').click();
|
||||||
|
setTimeout(_ => {
|
||||||
const {
|
inputs[0].focus();
|
||||||
minDate,
|
setTimeout(_ => {
|
||||||
maxDate
|
// correct highlight
|
||||||
} = vm.picker;
|
const startDate = rangePicker.picker.$el.querySelectorAll('.start-date');
|
||||||
expect(minDate).to.exist;
|
const endDate = rangePicker.picker.$el.querySelectorAll('.end-date');
|
||||||
expect(maxDate).to.exist;
|
const inRangeDate = rangePicker.picker.$el.querySelectorAll('.in-range');
|
||||||
expect(maxDate > minDate).to.true;
|
expect(startDate.length).to.equal(1);
|
||||||
|
expect(endDate.length).to.equal(1);
|
||||||
|
expect(inRangeDate.length).to.above(0);
|
||||||
|
// value is array
|
||||||
|
expect(vm.value).to.be.an.instanceof(Array);
|
||||||
|
// input text is something like date string
|
||||||
|
expect(inputs[0].value.length).to.equal(10);
|
||||||
|
expect(inputs[1].value.length).to.equal(10);
|
||||||
done();
|
done();
|
||||||
}, DELAY);
|
}, DELAY);
|
||||||
}, DELAY);
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
|
}, DELAY);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('type:daterange with unlink-panels', done => {
|
it('unlink panels', done => {
|
||||||
vm = createTest(DatePicker, {
|
vm = createTest(DatePicker, {
|
||||||
type: 'daterange',
|
type: 'daterange',
|
||||||
unlinkPanels: true
|
unlinkPanels: true
|
||||||
|
@ -1136,6 +1150,33 @@ describe('DatePicker', () => {
|
||||||
}, DELAY);
|
}, DELAY);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('daylight saving time highlight', done => {
|
||||||
|
// Run test with environment variable TZ=Australia/Sydney
|
||||||
|
// The following test uses Australian Eastern Daylight Time (AEDT)
|
||||||
|
// AEST -> AEDT shift happened on 2016-10-02 02:00:00
|
||||||
|
vm = createVue({
|
||||||
|
template: '<el-date-picker type="daterange" v-model="value" ref="compo" />',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: [new Date(2016, 9, 1), new Date(2016, 9, 3)]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
const rangePicker = vm.$refs.compo;
|
||||||
|
const inputs = rangePicker.$el.querySelectorAll('input');
|
||||||
|
inputs[0].focus();
|
||||||
|
|
||||||
|
setTimeout(_ => {
|
||||||
|
const startDate = rangePicker.picker.$el.querySelectorAll('.start-date');
|
||||||
|
const endDate = rangePicker.picker.$el.querySelectorAll('.end-date');
|
||||||
|
expect(startDate.length).to.equal(1);
|
||||||
|
expect(endDate.length).to.equal(1);
|
||||||
|
done();
|
||||||
|
}, DELAY);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('type:datetimerange', () => {
|
describe('type:datetimerange', () => {
|
||||||
let vm;
|
let vm;
|
||||||
beforeEach(done => {
|
beforeEach(done => {
|
||||||
|
|
Loading…
Reference in New Issue