mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-24 14:58:36 +08:00
fix(datetime): default to local date (#17706)
This commit is contained in:

committed by
Adam Bradley

parent
eb5494e932
commit
bab56e8947
@ -241,7 +241,38 @@ export function parseDate(val: string | undefined | null): DatetimeData | undefi
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a valid UTC datetime string
|
||||||
|
* To the user's local timezone
|
||||||
|
* Note: This is not meant for time strings
|
||||||
|
* such as "01:47"
|
||||||
|
*/
|
||||||
|
export const getLocalDateTime = (dateString = ''): Date => {
|
||||||
|
const date = (dateString.length > 0) ? new Date(dateString) : new Date();
|
||||||
|
|
||||||
|
return new Date(
|
||||||
|
Date.UTC(
|
||||||
|
date.getFullYear(),
|
||||||
|
date.getMonth(),
|
||||||
|
date.getDate(),
|
||||||
|
date.getHours(),
|
||||||
|
date.getMinutes(),
|
||||||
|
date.getSeconds(),
|
||||||
|
date.getMilliseconds()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export function updateDate(existingData: DatetimeData, newData: any): boolean {
|
export function updateDate(existingData: DatetimeData, newData: any): boolean {
|
||||||
|
|
||||||
|
if (!newData || typeof newData === 'string') {
|
||||||
|
const localDateTime = getLocalDateTime(newData);
|
||||||
|
|
||||||
|
if (!Number.isNaN(localDateTime.getTime())) {
|
||||||
|
newData = localDateTime.toISOString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (newData && newData !== '') {
|
if (newData && newData !== '') {
|
||||||
|
|
||||||
if (typeof newData === 'string') {
|
if (typeof newData === 'string') {
|
||||||
@ -368,6 +399,7 @@ export function convertDataToISO(data: DatetimeData): string {
|
|||||||
rtn += 'Z';
|
rtn += 'Z';
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// YYYY-MM-DDTHH:mm:SS+/-HH:mm
|
// YYYY-MM-DDTHH:mm:SS+/-HH:mm
|
||||||
rtn += (data.tzOffset > 0 ? '+' : '-') + twoDigit(Math.floor(Math.abs(data.tzOffset / 60))) + ':' + twoDigit(data.tzOffset % 60);
|
rtn += (data.tzOffset > 0 ? '+' : '-') + twoDigit(Math.floor(Math.abs(data.tzOffset / 60))) + ':' + twoDigit(data.tzOffset % 60);
|
||||||
}
|
}
|
||||||
|
@ -307,6 +307,19 @@ export class Datetime implements ComponentInterface {
|
|||||||
text: this.doneText,
|
text: this.doneText,
|
||||||
handler: (data: any) => {
|
handler: (data: any) => {
|
||||||
this.updateDatetimeValue(data);
|
this.updateDatetimeValue(data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent convertDataToISO from doing any
|
||||||
|
* kind of transformation based on timezone
|
||||||
|
* This cancels out any change it attempts to make
|
||||||
|
*
|
||||||
|
* Important: Take the timezone offset based on
|
||||||
|
* the date that is currently selected, otherwise
|
||||||
|
* there can be 1 hr difference when dealing w/ DST
|
||||||
|
*/
|
||||||
|
const date = new Date(convertDataToISO(this.datetimeValue));
|
||||||
|
this.datetimeValue.tzOffset = date.getTimezoneOffset() * -1;
|
||||||
|
|
||||||
this.value = convertDataToISO(this.datetimeValue);
|
this.value = convertDataToISO(this.datetimeValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -360,6 +373,7 @@ export class Datetime implements ComponentInterface {
|
|||||||
// cool, we've loaded up the columns with options
|
// cool, we've loaded up the columns with options
|
||||||
// preselect the option for this column
|
// preselect the option for this column
|
||||||
const optValue = getDateValue(this.datetimeValue, format);
|
const optValue = getDateValue(this.datetimeValue, format);
|
||||||
|
|
||||||
const selectedIndex = colOptions.findIndex(opt => opt.value === optValue);
|
const selectedIndex = colOptions.findIndex(opt => opt.value === optValue);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -527,6 +541,7 @@ export class Datetime implements ComponentInterface {
|
|||||||
private getText() {
|
private getText() {
|
||||||
// create the text of the formatted data
|
// create the text of the formatted data
|
||||||
const template = this.displayFormat || this.pickerFormat || DEFAULT_FORMAT;
|
const template = this.displayFormat || this.pickerFormat || DEFAULT_FORMAT;
|
||||||
|
|
||||||
return renderDatetime(template, this.datetimeValue, this.locale);
|
return renderDatetime(template, this.datetimeValue, this.locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { DatetimeOptions } from '../datetime-interface';
|
import { DatetimeData, getDateValue, getLocalDateTime } from '../datetime-util';
|
||||||
import { DatetimeData, getDateValue } from '../datetime-util';
|
|
||||||
|
|
||||||
describe('Datetime', () => {
|
describe('Datetime', () => {
|
||||||
describe('getDateValue()', () => {
|
describe('getDateValue()', () => {
|
||||||
@ -32,4 +31,30 @@ describe('Datetime', () => {
|
|||||||
expect(yearValue).toEqual(date.getFullYear());
|
expect(yearValue).toEqual(date.getFullYear());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getLocalDateTime()', () => {
|
||||||
|
it('should format a datetime string according to the local timezone', () => {
|
||||||
|
|
||||||
|
const dateStringTests = [
|
||||||
|
{ expectedHourUTC: 12, input: `2019-03-02T12:08:06.601-00:00`, expectedOutput: `2019-03-02T%HOUR%:08:06.601Z` },
|
||||||
|
{ expectedHourUTC: 12, input: `2019-11-02T12:08:06.601-00:00`, expectedOutput: `2019-11-02T%HOUR%:08:06.601Z` },
|
||||||
|
{ expectedHourUTC: 8, input: `1994-12-15T13:47:20.789+05:00`, expectedOutput: `1994-12-15T%HOUR%:47:20.789Z` },
|
||||||
|
{ expectedHourUTC: 18, input: `1994-12-15T13:47:20.789-05:00`, expectedOutput: `1994-12-15T%HOUR%:47:20.789Z` },
|
||||||
|
{ expectedHourUTC: 9, input: `2019-02-14T09:00:00.000Z`, expectedOutput: `2019-02-14T%HOUR%:00:00.000Z` }
|
||||||
|
];
|
||||||
|
|
||||||
|
dateStringTests.forEach(test => {
|
||||||
|
const convertToLocal = getLocalDateTime(test.input);
|
||||||
|
|
||||||
|
const timeZoneOffset = convertToLocal.getTimezoneOffset() / 60;
|
||||||
|
const expectedDateString = test.expectedOutput.replace('%HOUR%', padNumber(test.expectedHourUTC - timeZoneOffset));
|
||||||
|
|
||||||
|
expect(convertToLocal.toISOString()).toEqual(expectedDateString);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function padNumber(number: number, totalLength: number = 2): string {
|
||||||
|
return number.toString().padStart(totalLength, '0');
|
||||||
|
}
|
Reference in New Issue
Block a user