diff --git a/README.md b/README.md
index 76c23d479..8d018f19a 100644
--- a/README.md
+++ b/README.md
@@ -114,6 +114,7 @@ Validator | Description
**isHSL(str)** | check if the string is an HSL (hue, saturation, lightness, optional alpha) color based on [CSS Colors Level 4 specification](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).
Comma-separated format supported. Space-separated format supported with the exception of a few edge cases (ex: `hsl(200grad+.1%62%/1)`).
**isIBAN(str)** | check if a string is a IBAN (International Bank Account Number).
**isIdentityCard(str [, locale])** | check if the string is a valid identity card code.
`locale` is one of `['ES', 'IN', 'NO', 'zh-TW', 'he-IL', 'ar-TN', 'zh-CN']` OR `'any'`. If 'any' is used, function will check if any of the locals match.
Defaults to 'any'.
+**isIMEI(str)** | check if the string is a valid IMEI number. Imei should be of format` ###############`
**isIn(str, values)** | check if the string is in a array of allowed values.
**isInt(str [, options])** | check if the string is an integer.
`options` is an object which can contain the keys `min` and/or `max` to check the integer is within boundaries (e.g. `{ min: 10, max: 99 }`). `options` can also contain the key `allow_leading_zeroes`, which when set to false will disallow integer values with leading zeroes (e.g. `{ allow_leading_zeroes: false }`). Finally, `options` can contain the keys `gt` and/or `lt` which will enforce integers being greater than or less than, respectively, the value provided (e.g. `{gt: 1, lt: 4}` for a number between 1 and 4).
**isIP(str [, version])** | check if the string is an IP (version 4 or 6).
@@ -255,4 +256,4 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
[bower]: http://bower.io/
[mongoid]: http://docs.mongodb.org/manual/reference/object-id/
-[ISIN]: https://en.wikipedia.org/wiki/International_Securities_Identification_Number
\ No newline at end of file
+[ISIN]: https://en.wikipedia.org/wiki/International_Securities_Identification_Number
diff --git a/src/index.js b/src/index.js
index 7de1ea3a0..6fa974e5c 100644
--- a/src/index.js
+++ b/src/index.js
@@ -25,6 +25,8 @@ import isPort from './lib/isPort';
import isLowercase from './lib/isLowercase';
import isUppercase from './lib/isUppercase';
+import isIMEI from './lib/isIMEI';
+
import isAscii from './lib/isAscii';
import isFullWidth from './lib/isFullWidth';
import isHalfWidth from './lib/isHalfWidth';
@@ -150,6 +152,7 @@ const validator = {
isSemVer,
isSurrogatePair,
isInt,
+ isIMEI,
isFloat,
isFloatLocales,
isDecimal,
diff --git a/src/lib/isIMEI.js b/src/lib/isIMEI.js
new file mode 100644
index 000000000..512c68e41
--- /dev/null
+++ b/src/lib/isIMEI.js
@@ -0,0 +1,36 @@
+import assertString from './util/assertString';
+
+
+let imeiRegex = /^[0-9]{15}$/;
+
+export default function isIMEI(str) {
+ assertString(str);
+
+ if (!imeiRegex.test(str)) {
+ return false;
+ }
+
+ let sum = 0,
+ mul = 2,
+ l = 14;
+
+ for (let i = 0; i < l; i++) {
+ const digit = str.substring(l - i - 1, l - i);
+ const tp = parseInt(digit, 10) * mul;
+ if (tp >= 10) {
+ sum += (tp % 10) + 1;
+ } else {
+ sum += tp;
+ }
+ if (mul === 1) {
+ mul += 1;
+ } else {
+ mul -= 1;
+ }
+ }
+ const chk = ((10 - (sum % 10)) % 10);
+ if (chk !== parseInt(str.substring(14, 15), 10)) {
+ return false;
+ }
+ return true;
+}
diff --git a/test/validators.js b/test/validators.js
index ae4b87c09..4219bd047 100755
--- a/test/validators.js
+++ b/test/validators.js
@@ -2755,6 +2755,26 @@ describe('Validators', () => {
});
});
+
+ it('should validate imei strings', () => {
+ test({
+ validator: 'isIMEI',
+ valid: [
+ '352099001761481',
+ '868932036356090',
+ '490154203237518',
+ '546918475942169',
+ '998227667144730',
+ '532729766805999',
+ ],
+ invalid: [
+ '490154203237517',
+ '3568680000414120',
+ '3520990017614823',
+ ],
+ });
+ });
+
it('should validate uppercase strings', () => {
test({
validator: 'isUppercase',