diff --git a/changelogs/upcoming/7705.md b/changelogs/upcoming/7705.md
new file mode 100644
index 00000000000..55c3d3c6678
--- /dev/null
+++ b/changelogs/upcoming/7705.md
@@ -0,0 +1,3 @@
+**Bug fixes**
+
+- Fixed `EuiSuperDatePicker` to validate date string with respect of locale on `EuiAbsoluteTab`.
diff --git a/src-docs/src/views/super_date_picker/super_date_picker_example.js b/src-docs/src/views/super_date_picker/super_date_picker_example.js
index 1607e80d973..4fea50c1a86 100644
--- a/src-docs/src/views/super_date_picker/super_date_picker_example.js
+++ b/src-docs/src/views/super_date_picker/super_date_picker_example.js
@@ -4,6 +4,7 @@ import { Link } from 'react-router-dom';
import { GuideSectionTypes } from '../../components';
import {
+ EuiCallOut,
EuiCode,
EuiCodeBlock,
EuiIcon,
@@ -37,6 +38,9 @@ const autoRefreshOnlySource = require('!!raw-loader!./auto_refresh_only');
import SuperDatePickerPattern from './super_date_picker_pattern';
const superDatePickerPatternSource = require('!!raw-loader!./super_date_picker_pattern');
+import SuperDatePickerLocale from './super_date_picker_locale';
+const superDatePickerLocaleSource = require('!!raw-loader!./super_date_picker_locale');
+
const superDatePickerSnippet = `
`;
+const superDatePickerLocaleSnippet = ``;
+
export const SuperDatePickerExample = {
title: 'Super date picker',
intro: (
@@ -346,5 +358,38 @@ if (!endMoment || !endMoment.isValid()) {
demo: ,
dempPanelProps: { color: 'subdued' },
},
+ {
+ title: 'Locale',
+ source: [
+ {
+ type: GuideSectionTypes.TSX,
+ code: superDatePickerLocaleSource,
+ },
+ ],
+ text: (
+ <>
+
+ Locale formatting is achieved by using the locale
+ ,timeFormat, and dateFormat{' '}
+ props. The latter will take any moment(){' '}
+ notation. Check{' '}
+
+ Date format by country
+ {' '}
+ for formatting examples.
+
+
+ Moment will try to load the locale on demand when it is used.
+ Bundlers that do not support dynamic require statements will need to
+ explicitly import the locale, e.g.{' '}
+ {"import 'moment/locale/zh-cn'"}. See the below
+ demo TSX for examples.
+
+ >
+ ),
+ props: { EuiSuperDatePicker },
+ snippet: superDatePickerLocaleSnippet,
+ demo: ,
+ },
],
};
diff --git a/src-docs/src/views/super_date_picker/super_date_picker_locale.tsx b/src-docs/src/views/super_date_picker/super_date_picker_locale.tsx
new file mode 100644
index 00000000000..d19a304ac4a
--- /dev/null
+++ b/src-docs/src/views/super_date_picker/super_date_picker_locale.tsx
@@ -0,0 +1,100 @@
+import React, { useState } from 'react';
+
+// NOTE: These explicit imports are required for CodeSandbox and any
+// bundler that does not support Moment dynamically loading locales
+import 'moment/locale/zh-cn';
+import 'moment/locale/ja';
+import 'moment/locale/fr';
+
+import {
+ EuiButtonGroup,
+ EuiComboBox,
+ EuiComboBoxOptionOption,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiSpacer,
+ EuiSuperDatePicker,
+ OnTimeChangeProps,
+} from '../../../../src/components';
+import { htmlIdGenerator } from '../../../../src/services';
+
+const localeId = htmlIdGenerator('locale');
+const locales = [
+ { id: localeId(), label: 'en' },
+ { id: localeId(), label: 'zh-CN' },
+ { id: localeId(), label: 'ja-JP' },
+ { id: localeId(), label: 'fr-FR' },
+];
+const dateFormats = [
+ { label: 'MMM D, YYYY @ HH:mm:ss.SSS' },
+ { label: 'dddd, MMMM Do YYYY, h:mm:ss a' },
+ { label: 'YYYY-MM-DDTHH:mm:ss.SSSZ' },
+];
+
+export default () => {
+ const [start, setStart] = useState('now-1h');
+ const [end, setEnd] = useState('now-15m');
+ const onTimeChange = ({ start, end }: OnTimeChangeProps) => {
+ setStart(start);
+ setEnd(end);
+ };
+
+ const [locale, setLocale] = useState();
+ const [localeSelected, setLocaleSelected] = useState(locales[0].id);
+ const onLocaleChange = (optionId: React.SetStateAction) => {
+ setLocale(locales.find(({ id }) => id === optionId)!.label);
+ setLocaleSelected(optionId);
+ };
+
+ const [dateFormat, setDateFormat] = useState();
+ const [dateFormatsSelected, setDateFormatsSelected] = useState([
+ dateFormats[0],
+ ]);
+ const onDateFormatChange = (selectedOptions: EuiComboBoxOptionOption[]) => {
+ setDateFormat(selectedOptions.length ? selectedOptions[0].label : '');
+ setDateFormatsSelected(selectedOptions);
+ };
+ const onDateFormatCreate = (searchValue: string) => {
+ const normalizedSearchValue = searchValue.trim().toLowerCase();
+ if (!normalizedSearchValue) return;
+
+ setDateFormat(searchValue);
+ setDateFormatsSelected([{ label: searchValue }]);
+ };
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
diff --git a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.test.tsx b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.test.tsx
index 517212930a6..0a6ef20758f 100644
--- a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.test.tsx
+++ b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.test.tsx
@@ -11,6 +11,7 @@ import { fireEvent } from '@testing-library/react';
import { render } from '../../../../test/rtl';
import { EuiAbsoluteTab } from './absolute_tab';
+import { LocaleSpecifier } from 'moment';
// Mock EuiDatePicker - 3rd party datepicker lib causes render issues
jest.mock('../../date_picker', () => ({
@@ -105,6 +106,27 @@ describe('EuiAbsoluteTab', () => {
expect(input).toHaveValue('Jan 31st 01');
});
+ describe('parses date string in locale', () => {
+ test.each<{
+ locale: LocaleSpecifier;
+ dateString: string;
+ }>([
+ { locale: 'en', dateString: 'Mon Jan 1st' },
+ { locale: 'zh-CN', dateString: '周一 1月 1日' },
+ { locale: 'ja-JP', dateString: '月 1月 1日' },
+ { locale: 'fr-FR', dateString: 'lun. janv. 1er' },
+ ])('%p', ({ locale, dateString }) => {
+ const { getByTestSubject } = render(
+
+ );
+ const input = getByTestSubject('superDatePickerAbsoluteDateInput');
+
+ changeInput(input, dateString);
+ expect(input).not.toBeInvalid();
+ expect(input).toHaveValue(dateString);
+ });
+ });
+
describe('allows several other common date formats, and autoformats them to the `dateFormat` prop', () => {
const assertOutput = (input: HTMLInputElement) => {
// Exclude hours from assertion, because moment uses local machine timezone
diff --git a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx
index 8eae41674e0..a0cd792a165 100644
--- a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx
+++ b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx
@@ -116,10 +116,15 @@ export class EuiAbsoluteTab extends Component<
return this.setState(invalidDateState);
}
- const { onChange, dateFormat } = this.props;
+ const { onChange, dateFormat, locale } = this.props;
- // Attempt to parse with passed `dateFormat`
- let valueAsMoment = moment(textInputValue, dateFormat, true);
+ // Attempt to parse with passed `dateFormat` and `locale`
+ let valueAsMoment = moment(
+ textInputValue,
+ dateFormat,
+ typeof locale === 'string' ? locale : 'en', // Narrow the union type to string
+ true
+ );
let dateIsValid = valueAsMoment.isValid();
// If not valid, try a few other other standardized formats