Skip to content

Commit f829984

Browse files
authored
[Major]: Remove Moment and Node 10 (#100)
* [Major]: Rm Moment and Node 10 removal
1 parent b5e4f91 commit f829984

File tree

10 files changed

+26325
-14418
lines changed

10 files changed

+26325
-14418
lines changed

CHANGELOG.md

+12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Changelog
22

3+
## v4.0.0
4+
- [[Major]: Remove Moment and Node 10](https://github.com/offirgolan/ember-validators/pull/100);
5+
- Remove Node 10 minimum requirement in favor of Node 12
6+
- removed custom String 'now' argument.
7+
- remove momentjs
8+
- Remove `precision` argument. If you need to compare based on precision, you can use the Intl.DateTimeFormat [APIs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat#using_options) to hone in on the comparison - `{ year: 'numeric' }`
9+
- Added `locale` option. Defaults to en-us when creating date times using `Intl.DateTimeFormat` API.
10+
11+
## v3.0.0
12+
13+
- Remove node v4
14+
315
## v2.0.0
416

517
### Pull Requests

addon/date.js

+106-55
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import { isEmpty, isNone } from '@ember/utils';
21
import { set } from '@ember/object';
32
import validationError from 'ember-validators/utils/validation-error';
4-
import moment from 'moment';
53

64
/**
75
* @class Date
@@ -10,99 +8,152 @@ import moment from 'moment';
108

119
/**
1210
* @method validate
13-
* @param {Any} value
11+
* @param {String|Date} value
1412
* @param {Object} options
1513
* @param {Boolean} options.allowBlank If true, skips validation if the value is empty
16-
* @param {String} options.before The specified date must be before this date
17-
* @param {String} options.onOrBefore The specified date must be on or before this date
18-
* @param {String} options.after The specified date must be after this date
19-
* @param {String} options.onOrAfter The specified date must be on or after this date
20-
* @param {String} options.precision Limit the comparison check to a specific granularity.
21-
* Possible Options: [`year`, `month`, `week`, `day`, `hour`, `minute`, `second`].
22-
* @param {String} options.format Input value date format
23-
* @param {String} options.errorFormat Error output date format. Defaults to `MMM Do, YYYY`
24-
* @param {Object} model
25-
* @param {String} attribute
14+
* @param {String|Date} options.before The specified date must be before this date
15+
* @param {String|Date} options.onOrBefore The specified date must be on or before this date
16+
* @param {String|Date} options.after The specified date must be after this date
17+
* @param {String|Date} options.onOrAfter The specified date must be on or after this date
18+
* @param {String} options.format Input value date format - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat
19+
* - { dateStyle: 'long' } or { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }
20+
* If you need to obtain precision (just compare years), use { year: 'numeric' }
21+
* @param {String} options.errorFormat Error output date format. Defaults to options.format or { dateStyle: 'long' }
2622
*/
2723
export default function validateDate(value, options) {
28-
if (!moment) {
29-
throw new Error('MomentJS is required to use the Date validator.');
30-
}
31-
32-
let errorFormat = options.errorFormat || 'MMM Do, YYYY';
33-
let { format, precision, allowBlank } = options;
24+
let { locale = 'en-us', format, allowBlank } = options;
3425
let { before, onOrBefore, after, onOrAfter } = options;
35-
let date;
3626

37-
if (allowBlank && isEmpty(value)) {
27+
let errorFormat = options.errorFormat || format || { dateStyle: 'long' };
28+
29+
if ((allowBlank && value === null) || value === undefined || value === '') {
3830
return true;
3931
}
4032

41-
if (format) {
42-
date = parseDate(value, format, true);
43-
44-
// Check to see if the passed date is actually a valid date.
45-
// This can be done by disabling the strict parsing
46-
const isActualDate = parseDate(value, format).isValid();
33+
let date;
4734

48-
if (!isActualDate) {
49-
return validationError('date', value, options);
50-
} else if (!date.isValid()) {
51-
return validationError('wrongDateFormat', value, options);
35+
if (!value) {
36+
if (format) {
37+
date = new Intl.DateTimeFormat(locale, format).format(new Date());
5238
}
53-
} else {
54-
date = parseDate(value);
5539

56-
if (!date.isValid()) {
57-
return validationError('date', value, options);
58-
}
40+
date = new Date();
41+
} else if (!isValidDate(new Date(value))) {
42+
return validationError('date', value, options);
43+
} else {
44+
date = parseAsDate(value, format, locale);
5945
}
6046

6147
if (before) {
62-
before = parseDate(before, format);
48+
before = parseAsDate(before, format, locale);
6349

64-
if (!date.isBefore(before, precision)) {
65-
set(options, 'before', before.format(errorFormat));
50+
if (!isBefore(date, before)) {
51+
set(options, 'before', parseDateError(before, errorFormat, locale));
6652
return validationError('before', value, options);
6753
}
6854
}
6955

7056
if (onOrBefore) {
71-
onOrBefore = parseDate(onOrBefore, format);
72-
73-
if (!date.isSameOrBefore(onOrBefore, precision)) {
74-
set(options, 'onOrBefore', onOrBefore.format(errorFormat));
57+
onOrBefore = parseAsDate(onOrBefore, format, locale);
58+
59+
if (!isSameOrBefore(date, onOrBefore)) {
60+
set(
61+
options,
62+
'onOrBefore',
63+
parseDateError(onOrBefore, errorFormat, locale)
64+
);
7565
return validationError('onOrBefore', value, options);
7666
}
7767
}
7868

7969
if (after) {
80-
after = parseDate(after, format);
70+
after = parseAsDate(after, format, locale);
8171

82-
if (!date.isAfter(after, precision)) {
83-
set(options, 'after', after.format(errorFormat));
72+
if (!isAfter(date, after)) {
73+
set(options, 'after', parseDateError(after, errorFormat, locale));
8474
return validationError('after', value, options);
8575
}
8676
}
8777

8878
if (onOrAfter) {
89-
onOrAfter = parseDate(onOrAfter, format);
79+
onOrAfter = parseAsDate(onOrAfter, format, locale);
9080

91-
if (!date.isSameOrAfter(onOrAfter, precision)) {
92-
set(options, 'onOrAfter', onOrAfter.format(errorFormat));
81+
if (!isSameOrAfter(date, onOrAfter)) {
82+
set(options, 'onOrAfter', parseDateError(onOrAfter, errorFormat, locale));
9383
return validationError('onOrAfter', value, options);
9484
}
9585
}
9686

9787
return true;
9888
}
9989

100-
export function parseDate(date, format, useStrict = false) {
101-
if (date === 'now' || isEmpty(date)) {
102-
return moment();
90+
/**
91+
* This is a forcing function. If `format` provided, date and comparison date will be in String format. Otherwise, instances of Date.
92+
* I don't think there is a need to force iso8601 strings.
93+
* @function parseDate
94+
* @param {Date|String} date
95+
* @param {Object} format - { dateStyle: 'long' } or { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }
96+
* If you need to obtain precision (just compare years), use { year: 'numeric' }.
97+
* @param {String} locale
98+
* @returns {Date|String}
99+
*/
100+
export function parseDate(date, format, locale) {
101+
if (format) {
102+
// new Date("2015") will give the last day in 2014. This is problematic
103+
let yearOnly = isYearFormat(format);
104+
105+
if (!(date instanceof Date)) {
106+
// format date into string
107+
// we have already checked this a valid date
108+
let d = yearOnly ? new Date(date, 0) : new Date(date);
109+
return new Intl.DateTimeFormat(locale, format).format(d);
110+
}
111+
112+
// format date into string
113+
let d = yearOnly ? new Date(date.getFullYear(), 0) : date;
114+
return new Intl.DateTimeFormat(locale, format).format(d);
115+
} else {
116+
// Date constructor accepts a variety of formats including properly represented strings and Date instances.
117+
// However, a variety of formats return an "Invalid Date" literal including DD/MM/YYYY
118+
return new Date(date);
103119
}
120+
}
121+
122+
function parseDateError(date, format, locale) {
123+
return parseDate(date, format, locale);
124+
}
125+
126+
function parseAsDate(date, format, locale) {
127+
if (format && isYearFormat(format)) {
128+
return new Date(parseDate(date, format, locale), 0);
129+
}
130+
return new Date(parseDate(date, format, locale));
131+
}
132+
133+
function isValidDate(d) {
134+
return d instanceof Date && !isNaN(d);
135+
}
136+
137+
function isSame(date, comp) {
138+
return date.getTime() === comp.getTime();
139+
}
140+
141+
function isBefore(date, comp) {
142+
return date < comp;
143+
}
144+
145+
function isAfter(date, comp) {
146+
return date > comp;
147+
}
148+
149+
function isSameOrAfter(date, comp) {
150+
return isSame(date, comp) || isAfter(date, comp);
151+
}
152+
153+
function isSameOrBefore(date, comp) {
154+
return isSame(date, comp) || isBefore(date, comp);
155+
}
104156

105-
return isNone(format)
106-
? moment(new Date(date))
107-
: moment(date, format, useStrict);
157+
function isYearFormat(format) {
158+
return Object.keys(format).length === 1 && format.year;
108159
}

addon/ds-error.js

+3-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
import { get } from '@ember/object';
2-
import { isNone } from '@ember/utils';
31
import validationError from 'ember-validators/utils/validation-error';
4-
import DS from 'ember-data';
52

63
/**
74
* @class DS Error
@@ -16,20 +13,17 @@ import DS from 'ember-data';
1613
* @param {String} attribute
1714
*/
1815
export default function validateDsError(value, options, model, attribute) {
19-
if (!DS) {
20-
throw new Error('Ember-Data is required to use the DS Error validator.');
21-
}
22-
2316
let { path, key } = getPathAndKey(attribute);
2417

2518
let errors = model[path];
2619

27-
if (!isNone(errors) && errors instanceof DS.Errors && errors.has(key)) {
20+
if (errors && errors.has && errors.has(key)) {
21+
let errorsFor = errors.errorsFor(key);
2822
return validationError(
2923
'ds',
3024
null,
3125
options,
32-
get(errors.errorsFor(key), 'lastObject.message')
26+
errorsFor.length ? errorsFor[errorsFor.length - 1].message : []
3327
);
3428
}
3529

addon/messages.js

-1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,5 @@ export default {
9696
tooShort: '{description} is too short (minimum is {min} characters)',
9797
between: '{description} must be between {min} and {max} characters',
9898
url: '{description} must be a valid url',
99-
wrongDateFormat: '{description} must be in the format of {format}',
10099
wrongLength: '{description} is the wrong length (should be {is} characters)',
101100
};

0 commit comments

Comments
 (0)