diff --git a/src/locale/Language.js b/src/locale/Language.js index 282e3f55..5a778ba1 100755 --- a/src/locale/Language.js +++ b/src/locale/Language.js @@ -53,4 +53,14 @@ export default class Language { } this._days = days } + + getMonthByAbbrName(name) { + const monthValue = this._monthsAbbr.findIndex((month) => month === name) + 1 + return monthValue < 10 ? `0${monthValue}` : `${monthValue}` + } + + getMonthByName(name) { + const monthValue = this._months.findIndex((month) => month === name) + 1 + return monthValue < 10 ? `0${monthValue}` : `${monthValue}` + } } diff --git a/src/utils/DateUtils.js b/src/utils/DateUtils.js index 9680529e..487d0861 100755 --- a/src/utils/DateUtils.js +++ b/src/utils/DateUtils.js @@ -194,16 +194,16 @@ const utils = { /** * Formats date object * @param {Date} date - * @param {String} format + * @param {String} formatStr * @param {Object} translation * @return {String} */ - formatDate(date, format, translation) { + formatDate(date, formatStr, translation) { const translationTemp = (!translation) ? en : translation const year = this.getFullYear(date) const month = this.getMonth(date) + 1 const day = this.getDate(date) - return format + return formatStr .replace(/dd/, (`0${day}`).slice(-2)) .replace(/d/, day) .replace(/yyyy/, year) @@ -212,8 +212,61 @@ const utils = { .replace(/MMM/, this.getMonthNameAbbr(this.getMonth(date), translationTemp.monthsAbbr)) .replace(/MM/, (`0${month}`).slice(-2)) .replace(/M(?![aäe])/, month) - .replace(/su/, this.getNthSuffix(this.getDate(date))) - .replace(/D(?![eéi])/, this.getDayNameAbbr(date, translationTemp.days)) + .replace(/o/, this.getNthSuffix(this.getDate(date))) + .replace(/E(?![eéi])/, this.getDayNameAbbr(date, translationTemp.days)) + }, + + /** + * makes date parseable + * to use with international dates + * @param {String} dateStr + * @param {String|Function} formatStr + * @param {Object} translation + * @param {Function} parser + * @return {Date | String} + */ + parseDate(dateStr, formatStr, translation, parser) { + const translationTemp = (!translation) ? en : translation + if (!(dateStr && formatStr)) { + return dateStr + } + if (typeof formatStr === 'function') { + if (!parser || typeof parser !== 'function') { + throw new Error('Parser need to be a function if you are using a custom formatter') + } + return parser(dateStr) + } + const splitter = formatStr.match(/-|\/|\s|\./) || ['-'] + const df = formatStr.split(splitter[0]) + const ds = dateStr.split(splitter[0]) + const ymd = [ + 0, + 0, + 0, + ] + for (let i = 0; i < df.length; i += 1) { + if (/yyyy/i.test(df[i])) { + ymd[0] = ds[i] + } else if (/mmmm/i.test(df[i])) { + ymd[1] = translationTemp.getMonthByName(ds[i]) + } else if (/mmm/i.test(df[i])) { + ymd[1] = translationTemp.getMonthByAbbrName(ds[i]) + } else if (/mm/i.test(df[i])) { + ymd[1] = ds[i] + } else if (/m/i.test(df[i])) { + ymd[1] = ds[i] + } else if (/dd/i.test(df[i])) { + ymd[2] = ds[i] + } else if (/d/i.test(df[i])) { + const tmp = ds[i].replace(/st|rd|nd|th/g, '') + ymd[2] = tmp < 10 ? `0${tmp}` : `${tmp}` + } + } + const dat = `${ymd.join('-')}T00:00:00Z` + if (Number.isNaN(Date.parse(dat))) { + return dateStr + } + return dat }, /** diff --git a/test/unit/specs/DateInput/typedDates.spec.js b/test/unit/specs/DateInput/typedDates.spec.js index 77da805c..09883e2f 100755 --- a/test/unit/specs/DateInput/typedDates.spec.js +++ b/test/unit/specs/DateInput/typedDates.spec.js @@ -1,5 +1,8 @@ import { shallowMount } from '@vue/test-utils' -import { format } from 'date-fns' +import { + format, + parse, +} from 'date-fns' import DateInput from '~/components/DateInput' import { en } from '~/locale' @@ -82,14 +85,17 @@ describe('DateInput', () => { selectedDate: new Date(dateString), typeable: true, format(date) { - return format(new Date(date), 'dd-MM-yyyy') + return format(new Date(date), 'dd.MM.yyyy') + }, + parser(date) { + return parse(date, 'dd.MM.yyyy', new Date()) }, }) const input = wrapper.find('input') - wrapper.vm.input.value = dateString - expect(wrapper.vm.input.value).toEqual(dateString) + input.element.value = dateString + expect(input.element.value).toEqual(dateString) input.trigger('keyup') - expect(wrapper.vm.formattedValue).toEqual(dateString) + expect(wrapper.vm.formattedValue).toEqual('12.08.2018') }) it('emits the date when typed', () => { diff --git a/test/unit/specs/DateUtils.spec.js b/test/unit/specs/DateUtils.spec.js index 2debdb90..af9a2b1d 100755 --- a/test/unit/specs/DateUtils.spec.js +++ b/test/unit/specs/DateUtils.spec.js @@ -31,21 +31,41 @@ describe('DateUtils', () => { expect(DateUtils.formatDate(new Date(2016, 0, 9), 'dd MMM yyyy')).toEqual('09 Jan 2016') expect(DateUtils.formatDate(new Date(2016, 0, 9), 'dd MMM yy')).toEqual('09 Jan 16') expect(DateUtils.formatDate(new Date(2016, 2, 9), 'yyyy-MM-dd')).toEqual('2016-03-09') - expect(DateUtils.formatDate(new Date(2016, 2, 9), 'dsu MMMM yyyy')).toEqual('9th March 2016') - expect(DateUtils.formatDate(new Date(2016, 2, 1), 'dsu MMMM yyyy')).toEqual('1st March 2016') - expect(DateUtils.formatDate(new Date(2016, 2, 2), 'dsu MMMM yyyy')).toEqual('2nd March 2016') - expect(DateUtils.formatDate(new Date(2016, 2, 3), 'dsu MMMM yyyy')).toEqual('3rd March 2016') - expect(DateUtils.formatDate(new Date(2016, 7, 1), 'D dsu MMMM yyyy')) + expect(DateUtils.formatDate(new Date(2016, 2, 9), 'do MMMM yyyy')).toEqual('9th March 2016') + expect(DateUtils.formatDate(new Date(2016, 2, 1), 'do MMMM yyyy')).toEqual('1st March 2016') + expect(DateUtils.formatDate(new Date(2016, 2, 2), 'do MMMM yyyy')).toEqual('2nd March 2016') + expect(DateUtils.formatDate(new Date(2016, 2, 3), 'do MMMM yyyy')).toEqual('3rd March 2016') + expect(DateUtils.formatDate(new Date(2016, 7, 1), 'E do MMMM yyyy')) .toEqual('Mon 1st August 2016') - expect(DateUtils.formatDate(new Date(2016, 8, 1), 'D dsu MMMM yyyy')) + expect(DateUtils.formatDate(new Date(2016, 8, 1), 'E do MMMM yyyy')) .toEqual('Thu 1st September 2016') - expect(DateUtils.formatDate(new Date(2016, 7, 7), 'D dsu MMMM yyyy')) + expect(DateUtils.formatDate(new Date(2016, 7, 7), 'E do MMMM yyyy')) .toEqual('Sun 7th August 2016') expect(DateUtils.formatDate(new Date(2016, 11, 2), 'dd MMM yyyy')).toEqual('02 Dec 2016') }) + it('should parse english dates', () => { + expect(DateUtils.parseDate('16 April 2020', 'd MMMM yyyy', en, null)) + .toEqual('2020-04-16T00:00:00Z') + expect(DateUtils.parseDate('16th Apr 2020', 'do MMM yyyy', en, null)) + .toEqual('2020-04-16T00:00:00Z') + expect(DateUtils.parseDate('Thu 16th Apr 2020', 'E do MMM yyyy', en, null)) + .toEqual('2020-04-16T00:00:00Z') + expect(DateUtils.parseDate('16.04.2020', 'dd.MM.yyyy', en, null)) + .toEqual('2020-04-16T00:00:00Z') + expect(DateUtils.parseDate('04.16.2020', 'MM.dd.yyyy', en, null)) + .toEqual('2020-04-16T00:00:00Z') + }) + + it('should fail to parse because of missing parser', () => { + expect(() => { + DateUtils.parseDate('16 April 2020', () => { + }, en, null) + }).toThrowError('Parser need to be a function if you are using a custom formatter') + }) + it('should give the correct day', () => { - expect(DateUtils.formatDate(new Date(2016, 8, 12), 'D')).toEqual('Mon') + expect(DateUtils.formatDate(new Date(2016, 8, 12), 'E')).toEqual('Mon') }) it('can create an array of dates', () => {